# Client Configuration Guide

This guide explains how to configure MCP clients to connect to the `mcp-abap-adt` server.

If you prefer not to edit JSON/TOML by hand, use the configurator CLI:
`@mcp-abap-adt/configurator` (repo: [`mcp-abap-adt-conf`](https://github.com/fr0ster/mcp-abap-adt-conf), docs: [CLIENT_INSTALLERS.md](https://github.com/fr0ster/mcp-abap-adt-conf/tree/main/docs/CLIENT_INSTALLERS.md)).

## Overview

The `mcp-abap-adt` server supports multiple transport modes:
- **streamable-http** - HTTP-based transport with streaming support (default)
- **stdio** - Standard input/output (for MCP clients like Cline, Cursor)
- **sse** - Server-Sent Events transport

For HTTP-based transports (streamable-http and sse), you can configure SAP connection parameters via HTTP headers, allowing dynamic connection configuration per request.

### Methods That Require SAP Configuration

**Only `tools/call` requires SAP configuration** - all other MCP methods work without SAP connection:
- `tools/list` - List available tools (no SAP config needed)
- `tools/get` - Get tool metadata (no SAP config needed)
- `initialize` - Initialize MCP session (no SAP config needed)
- `ping` - Health check (no SAP config needed)
- `notifications/initialized` - Notification (no SAP config needed)
- `tools/call` - **Execute a tool** (requires SAP configuration)

This means you can query available tools, get tool descriptions, and initialize the connection without providing SAP credentials. Only when you actually call a tool (e.g., `GetProgram`, `CreateClass`) does the server require SAP authentication.

## Streamable HTTP Configuration

### Basic Configuration

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http"
  }
}
```

### Configuration with SAP Connection Headers

When using HTTP transport, you can configure the SAP connection dynamically via HTTP headers:

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-url": "https://your-sap-system.abap.us10.hana.ondemand.com",
      "x-sap-auth-type": "jwt",
      "x-sap-jwt-token": "your_jwt_token_here",
      "x-sap-refresh-token": "your_refresh_token_here"
    }
  }
}
```

### Supported HTTP Headers

The server processes the following HTTP headers (as checked in `applyAuthHeaders` method):

| Header | Required | Description | Example |
|--------|----------|-------------|---------|
| `x-sap-url` | Yes* | SAP system URL | `https://system.abap.us10.hana.ondemand.com` |
| `x-sap-auth-type` | Yes* | Authentication type | `jwt`, `xsuaa`, or `basic` |
| `x-sap-jwt-token` | Yes* (for JWT) | JWT access token | `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...` |
| `x-sap-refresh-token` | No | Refresh token for automatic token renewal (JWT only) | `refresh_token_string` |
| `x-sap-login` | Yes* (for basic) | Username for basic authentication | `your_username` |
| `x-sap-password` | Yes* (for basic) | Password for basic authentication | `your_password` |
| `x-sap-destination` | No | Destination name for service key-based authentication | `TRIAL`, `DEV`, `PROD` |
| `x-mcp-destination` | No | Destination name for MCP destination-based authentication | `TRIAL`, `DEV`, `PROD` |
| `x-sap-master-system` | No | SAP system ID for on-prem transport binding | `DEV`, `QAS` |
| `x-sap-responsible` | No | Responsible user for transport operations | `DEVELOPER1` |

\* Required when not using `.env` file configuration or destination-based authentication. If headers are not provided, the server will use configuration from `.env` file or environment variables.

**Notes:**
- For **JWT authentication**: `x-sap-url`, `x-sap-auth-type`, and `x-sap-jwt-token` are required. `x-sap-refresh-token` is optional for automatic token refresh.
- For **basic authentication**: `x-sap-url`, `x-sap-auth-type`, `x-sap-login`, and `x-sap-password` are required.
- For **destination-based authentication**: Use `x-sap-destination` or `x-mcp-destination` header. URL is automatically derived from the service key, so `x-sap-url` is not required (and will be ignored if provided). Service keys must be stored in platform-specific locations (see [Destination-Based Authentication](#destination-based-authentication) section).
- For automatic token refresh, you only need `x-sap-refresh-token`. Client ID and Client Secret are **not needed** for refresh - they are only required for initial token generation via `mcp-auth` CLI tool (part of `@mcp-abap-adt/connection` package) or service keys.


## Basic Authentication

For on-premise systems using basic authentication:

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-url": "https://your-onpremise-system.com:8000",
      "x-sap-auth-type": "basic",
      "x-sap-login": "your_username",
      "x-sap-password": "your_password",
      "x-sap-master-system": "DEV",
      "x-sap-responsible": "DEVELOPER1"
    }
  }
}
```

**Note:** For basic authentication, you can pass username and password via HTTP headers (`x-sap-login` and `x-sap-password`) or configure them in the server's `.env` file (`SAP_USERNAME`, `SAP_PASSWORD`). Headers take priority over `.env` values.

**System context headers** (`x-sap-master-system`, `x-sap-responsible`) are optional. When provided, they override `SAP_MASTER_SYSTEM` / `SAP_RESPONSIBLE` from `.env` and the cloud `getSystemInformation()` API. This is useful for on-premise HTTP/SSE setups where no `.env` file is used.

## Destination-Based Authentication

> **Note:** Destination-based authentication (auth-broker) is available for all transport types:
> - **HTTP/streamable-http**: Use `--mcp=<destination>` parameter. To allow per-request destination override via `x-mcp-destination` header, add `--allow-destination-header`
> - **stdio**: Use `--mcp=<destination>` command-line parameter
> - **SSE**: Use `--mcp=<destination>` parameter. To allow per-request destination override via `x-mcp-destination` header, add `--allow-destination-header`
> 
> For **stdio** and **SSE** transports without `--mcp` parameter, use `.env` file configuration instead.
> 
> **Important:** When `--mcp` parameter is specified, `.env` file is **not loaded automatically** (even if it exists in current directory). This ensures that auth-broker configuration takes precedence over `.env` file settings.

The server supports destination-based authentication using service keys stored locally. This allows you to configure authentication once per destination and reuse it across multiple requests.

### When Auth-Broker is Used

The server uses auth-broker (service keys) in the following cases:

1. **By default** (when no explicit env file/destination is provided and no `.env` exists in current directory): Auth-broker is used automatically
2. **When `--auth-broker` flag is specified**: Forces use of auth-broker, ignoring any `.env` file (even if it exists in current directory)
3. **When `--mcp` parameter is specified**: Uses auth-broker with the specified destination, `.env` file is not loaded automatically
4. **When `--env=<destination>` is specified**: Uses destination env file from sessions store
5. **When `--env-path=<path|file>` is specified**: Uses explicit `.env` file instead of auth-broker

**Priority:**
1. `--env-path=<path|file>` (or `MCP_ENV_PATH`) - explicit `.env` file (highest priority)
2. `--env=<destination>` - destination env from sessions store
3. `--mcp=<destination>` - uses auth-broker, skips automatic `.env` loading
4. `.env` in current directory - used automatically if exists (default behavior)
5. `--auth-broker` - force auth-broker, ignore `.env`
6. Auth-broker - used if no `.env` found (fallback)

**Examples:**
```bash
# Default: uses .env from current directory if exists, otherwise auth-broker
mcp-abap-adt

# Forces auth-broker, ignores .env file even if exists
mcp-abap-adt --auth-broker

# Uses auth-broker with --mcp parameter (skips .env file)
mcp-abap-adt --transport=stdio --mcp=TRIAL

# Uses destination env from sessions store
mcp-abap-adt --env=trial

# Uses explicit .env file from custom path
mcp-abap-adt --env-path=/path/to/.env
```

### How It Works

1. **Service Keys**: Store SAP BTP service keys as JSON files
2. **Lazy Initialization**: AuthBroker instances are created on-demand when a destination is first used (not at server startup)
3. **Per-Destination Instances**: Each destination gets its own AuthBroker instance, cached in a map for reuse
4. **Sessions**: The server automatically manages JWT tokens and refresh tokens in `.env` files
5. **Automatic Token Management**: Tokens are validated, refreshed, and cached automatically

**Important:** AuthBroker is only initialized when needed:
- AuthBroker instances are created lazily when a request with destination header arrives
- Each destination (e.g., "TRIAL", "sk") gets its own AuthBroker instance
- Instances are cached and reused for subsequent requests to the same destination
- This reduces memory usage and startup time

### Service Key Storage

Service keys are stored in platform-specific locations:

**Unix (Linux/macOS):**
- Service keys: `~/.config/mcp-abap-adt/service-keys/{destination}.json`
- Sessions: `~/.config/mcp-abap-adt/sessions/{destination}.env` (only when `--unsafe` is used)

**Windows:**
- Service keys: `%USERPROFILE%\Documents\mcp-abap-adt\service-keys\{destination}.json`
- Sessions: `%USERPROFILE%\Documents\mcp-abap-adt\sessions\{destination}.env` (only when `--unsafe` is used)

**Fallback:** The server also searches in the current working directory (where the server is launched from).

### Session Storage

By default, session data (JWT tokens and refresh tokens) is stored **in-memory** using `SafeSessionStore`:
- **Secure by default**: Session data is not persisted to disk
- **Data loss on restart**: Session data is lost when the server restarts (requires re-authentication)
- **No file I/O**: No `.env` files are created for sessions

To enable **file-based session storage** (persists tokens to disk), use the `--unsafe` flag:

```bash
# Enable file-based session storage (persists tokens to disk)
mcp-abap-adt --auth-broker --unsafe

# Or via environment variable
MCP_UNSAFE=true mcp-abap-adt --auth-broker
```

**When `--unsafe` is used:**
- Session data is saved to platform-specific locations (see Service Key Storage above)
- Tokens persist across server restarts
- `.env` files are created/updated in the sessions directory
- **Security consideration**: Tokens are stored in plain text files on disk

**Recommendation**: Use `--unsafe` only if you need session persistence across server restarts. For production environments, consider using the default in-memory storage for better security.

### Service Key Format

Download the service key JSON file from SAP BTP (from the corresponding service instance) and save it as `{destination}.json` (e.g., `TRIAL.json`). The filename without `.json` extension becomes the destination name (case-sensitive).

**Storage locations:**
- **Linux/macOS:** `~/.config/mcp-abap-adt/service-keys/{destination}.json`
- **Windows:** `%USERPROFILE%\Documents\mcp-abap-adt\service-keys\{destination}.json`
- **Fallback:** Server also searches in current working directory (where server is launched)

### Using Destination Headers

#### Option 1: `x-sap-destination` (Highest Priority)

For SAP Cloud systems, use `x-sap-destination`:

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-destination": "TRIAL"
    }
  }
}
```

**Features:**
- URL is automatically derived from the service key
- Optional: `x-sap-client` for client number
- Optional: `x-sap-login` and `x-sap-password` for additional authentication
- Automatically uses JWT authentication

#### Option 2: `x-mcp-destination`

For MCP-specific destinations, use `x-mcp-destination`:

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-mcp-destination": "TRIAL"
    }
  }
}
```

**Features:**
- URL is automatically derived from the service key
- Optional: `x-sap-client` for client number
- Automatically uses JWT authentication
- Tokens are retrieved from the service key
- Note: If `x-sap-url` is provided, it will be ignored (URL comes from destination)

### First-Time Authentication

When using a destination for the first time:

1. The server reads the service key from `{destination}.json`
2. Opens a browser for OAuth2 authentication (if no valid session exists)
3. After successful authentication, saves tokens to `{destination}.env`
4. Subsequent requests use the cached tokens automatically

### Automatic Token Refresh

The server automatically:
- Validates tokens before use
- Refreshes expired tokens using refresh tokens
- Caches valid tokens for performance
- Falls back to browser authentication if refresh fails

### Example: Complete Setup

1. **Create service key:**
```bash
# Unix
mkdir -p ~/.config/mcp-abap-adt/service-keys
cat > ~/.config/mcp-abap-adt/service-keys/TRIAL.json << 'EOF'
{
  "uaa": {
    "url": "https://your-uaa-url.com",
    "clientid": "your-client-id",
    "clientsecret": "your-client-secret"
  },
  "url": "https://your-sap-url.com"
}
EOF
```

2. **Configure client:**
```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-destination": "TRIAL"
    }
  }
}
```

3. **First request:** Browser opens for authentication
4. **Subsequent requests:** Uses cached tokens automatically

### Using --mcp Parameter for stdio and SSE Transports

The `--mcp` parameter allows you to use auth-broker (service keys) with stdio and SSE transports, which previously required `.env` file configuration.

**For stdio transport:**
```bash
# Start server with --mcp parameter
mcp-abap-adt --transport=stdio --mcp=TRIAL
```

The server will:
1. Initialize auth-broker with the specified destination at startup
2. Load service key from `{destination}.json` (e.g., `TRIAL.json`)
3. Authenticate using OAuth2 if needed
4. Use the destination for all MCP tool calls

**For SSE transport:**
```bash
# Start server with --mcp parameter
mcp-abap-adt --transport=sse --mcp=TRIAL
```

The server will use the specified destination for all requests. To allow clients to override via `x-mcp-destination` header, add `--allow-destination-header`.

**Example Cline configuration with stdio:**
```json
{
  "mcpServers": {
    "mcp-abap-adt": {
      "command": "mcp-abap-adt",
      "args": ["--transport=stdio", "--mcp=TRIAL"]
    }
  }
}
```

**Example SSE client configuration:**
```json
{
  "local-mcp-sse": {
    "disabled": false,
    "timeout": 60,
    "type": "sse",
    "url": "http://localhost:3001/sse"
  }
}
```

The server will use `TRIAL` destination automatically (from `--mcp=TRIAL`), or you can override it per request:
```json
{
  "local-mcp-sse": {
    "disabled": false,
    "timeout": 60,
    "type": "sse",
    "url": "http://localhost:3001/sse",
    "headers": {
      "x-mcp-destination": "DEV"  // Overrides --mcp parameter
    }
  }
}
```

### Custom Paths

You can override default paths using the `AUTH_BROKER_PATH` environment variable or the `--auth-broker-path` command-line option:

**Using Environment Variable:**
```bash
# Unix (colon-separated)
export AUTH_BROKER_PATH="/custom/path:/another/path"

# Windows (semicolon-separated)
set AUTH_BROKER_PATH=C:\custom\path;C:\another\path
```

**Using Command-Line Option:**
```bash
# Unix/Linux/macOS
mcp-abap-adt --auth-broker --auth-broker-path=~/prj/tmp/

# Windows
mcp-abap-adt --auth-broker --auth-broker-path=C:\prj\tmp\
```

**Note:** When using `--auth-broker-path`, the server automatically creates `service-keys` and `sessions` subdirectories in the specified path. For example, `--auth-broker-path=~/prj/tmp/` will use:
- `~/prj/tmp/service-keys/` for service key files
- `~/prj/tmp/sessions/` for session files

The directories are created automatically if they don't exist.

### Server Command-Line Options

When starting the server, you can control whether to use auth-broker or `.env` file:

```bash
# Uses auth-broker by default (even if .env exists in current directory)
mcp-abap-adt

# Forces use of auth-broker, ignores .env file
mcp-abap-adt --auth-broker

# Forces use of auth-broker with custom path (creates service-keys and sessions subdirectories)
mcp-abap-adt --auth-broker --auth-broker-path=~/prj/tmp/

# Uses destination env from sessions store
mcp-abap-adt --env=trial
mcp-abap-adt --env trial

# Uses explicit .env file from custom path
mcp-abap-adt --env-path=/path/to/.env
mcp-abap-adt --env-path /path/to/.env
```

**Behavior:**
- **Default (no flags)**: Checks for `.env` in current directory first; if exists, uses it; otherwise uses auth-broker
- **`--auth-broker`**: Forces use of auth-broker, completely ignores `.env` file (even if exists in current directory)
- **`--auth-broker-path=<path>`**: Specifies custom path for auth-broker service keys and sessions
  - Creates `service-keys` and `sessions` subdirectories in the specified path
  - Directories are created automatically if they don't exist
  - Example: `--auth-broker-path=~/prj/tmp/` uses `~/prj/tmp/service-keys/` and `~/prj/tmp/sessions/`
  - Can be used together with `--auth-broker` flag
- **`--unsafe`**: Enables file-based session storage (persists tokens to disk)
  - By default, session data is stored in-memory (secure, lost on restart)
  - With `--unsafe`, session tokens are saved to `.env` files in the sessions directory
  - Can be set via environment variable: `MCP_UNSAFE=true`
  - Use only if you need session persistence across server restarts
- **`--env=<destination>` or `--env <destination>`**: Uses destination env file from sessions store
  - Unix: `~/.config/mcp-abap-adt/sessions/<destination>.env`
  - Windows: `%USERPROFILE%\Documents\mcp-abap-adt\sessions\<destination>.env`
- **`--env-path=<path|file>`**: Uses specified `.env` file directly, auth-broker is not used
  - Relative paths are resolved from current working directory
  - Absolute paths are used as-is

## Server Configuration

The server can be started in HTTP mode with:

```bash
npm run start:http
# or
node dist/index.js --transport streamable-http --http-port 3000
```

### Environment Variables

Alternatively, you can configure the server via environment variables in a `.env` file.

**For JWT authentication:**
```env
SAP_URL=https://your-sap-system.abap.us10.hana.ondemand.com
SAP_AUTH_TYPE=jwt
SAP_JWT_TOKEN=your_jwt_token_here
SAP_REFRESH_TOKEN=your_refresh_token_here
```

**For basic authentication (on-premise):**
```env
SAP_URL=https://your-onpremise-system.com:8000
SAP_AUTH_TYPE=basic
SAP_USERNAME=your_username
SAP_PASSWORD=your_password
SAP_CLIENT=100
SAP_SYSTEM_TYPE=onprem

# System context (required for on-prem create/update operations)
SAP_MASTER_SYSTEM=DEV
# SAP_RESPONSIBLE is optional — falls back to SAP_USERNAME
```

### SAP System Type

The `SAP_SYSTEM_TYPE` environment variable controls which tools are available and how the server interacts with the SAP system:

| Value | Description | Default |
|-------|-------------|---------|
| `cloud` | ABAP Cloud / BTP systems | **Yes** (default) |
| `onprem` | On-premise systems (BASIS ≥ 7.50) | No |
| `legacy` | Legacy on-premise systems (BASIS < 7.50) | No |

**Why this matters:** Different SAP environments support different ADT endpoints. For example, Programs are only available on `onprem` and `legacy` systems. The server uses `SAP_SYSTEM_TYPE` to filter tools accordingly.

**Default is `cloud`** — this covers most modern scenarios. On-premise users must set `SAP_SYSTEM_TYPE=onprem` to access on-premise-only tools (e.g., Programs).

You can also set this via CLI: `--system-type=onprem`

#### Per-Instance Override (embedders)

When embedding the server via `EmbeddableMcpServer`, pass `systemType` in the constructor options to bind one server instance to a specific SAP system type, independent of the process-global `SAP_SYSTEM_TYPE` env var:

```ts
new EmbeddableMcpServer({
  connection,
  exposition: ['readonly', 'high'],
  systemType: 'onprem', // or 'cloud' / 'legacy'
});
```

Use this when one host serves multiple SAP systems per request — for example, a proxy that resolves a BTP destination at request time and decides whether it is OnPremise (Cloud Connector) or an internet-facing cloud endpoint. Mutating `process.env.SAP_SYSTEM_TYPE` per request is not safe and is not required.

**Resolution order:** `options.systemType` → `process.env.SAP_SYSTEM_TYPE` → default `cloud`.

### System Context for On-Premise Systems

When creating or updating ABAP objects on on-premise systems, SAP ADT requires `masterSystem` and `responsible` attributes in the XML request body. These ensure that objects are correctly bound to transport requests.

**How system context is resolved:**

| Variable | Purpose | Resolution order |
|----------|---------|-----------------|
| `SAP_MASTER_SYSTEM` | SAP system ID (e.g., `E19`, `DEV`) | 1. Env var `SAP_MASTER_SYSTEM` → 2. `getSystemInformation()` API (cloud only) |
| `SAP_RESPONSIBLE` | Responsible user for the object | 1. Env var `SAP_RESPONSIBLE` → 2. Env var `SAP_USERNAME` → 3. `getSystemInformation()` API (cloud only) |

**On-premise systems** do not support the `getSystemInformation()` API endpoint, so `SAP_MASTER_SYSTEM` **must** be set in the `.env` file. Without it, create/update operations may fail with `403 Forbidden` because the object gets bound to the wrong transport request.

**Cloud systems** (ABAP Cloud / BTP) resolve system context automatically via the `getSystemInformation()` API — no additional configuration is needed.

**Example `.env` for on-premise:**
```env
SAP_URL=http://your-sap-system:8000
SAP_AUTH_TYPE=basic
SAP_USERNAME=JSMITH
SAP_PASSWORD=secret
SAP_CLIENT=100
SAP_SYSTEM_TYPE=onprem
SAP_MASTER_SYSTEM=DEV
```

In Claude Code (`claude_desktop_config.json` or `mcp.json`):
```json
{
  "mcpServers": {
    "mcp-abap-adt": {
      "command": "mcp-abap-adt",
      "args": ["--transport=stdio"],
      "env": {
        "SAP_URL": "http://your-sap-system:8000",
        "SAP_AUTH_TYPE": "basic",
        "SAP_USERNAME": "JSMITH",
        "SAP_PASSWORD": "secret",
        "SAP_CLIENT": "100",
        "SAP_SYSTEM_TYPE": "onprem",
        "SAP_MASTER_SYSTEM": "DEV"
      }
    }
  }
}
```

When using `.env` configuration, HTTP headers in the client configuration are optional and will override the `.env` values if provided.

## Dynamic Configuration Updates

The server automatically updates the connection configuration when it receives HTTP headers with SAP connection parameters. This allows:

1. **Multi-tenant scenarios**: Different clients can connect to different SAP systems
2. **Token refresh**: Update JWT tokens dynamically without restarting the server
3. **Runtime configuration**: Configure connections without modifying server files

### Configuration Priority

1. HTTP headers (if provided) - highest priority
2. `.env` file configuration
3. Environment variables

## SSE Mode Configuration

For Server-Sent Events transport, the configuration is similar:

**JWT authentication:**
```json
{
  "local-mcp-sse": {
    "disabled": false,
    "timeout": 60,
    "type": "sse",
    "url": "http://localhost:3001/mcp/events",
    "headers": {
      "x-sap-url": "https://your-sap-system.abap.us10.hana.ondemand.com",
      "x-sap-auth-type": "jwt",
      "x-sap-jwt-token": "your_jwt_token_here",
      "x-sap-refresh-token": "your_refresh_token_here"
    }
  }
}
```

**Basic authentication:**
```json
{
  "local-mcp-sse": {
    "disabled": false,
    "timeout": 60,
    "type": "sse",
    "url": "http://localhost:3001/mcp/events",
    "headers": {
      "x-sap-url": "https://your-onpremise-system.com:8000",
      "x-sap-auth-type": "basic",
      "x-sap-login": "your_username",
      "x-sap-password": "your_password"
    }
  }
}
```

## Security Considerations

1. **Token Storage**: Never commit tokens to version control. Use environment variables or secure secret management.
2. **HTTPS**: Always use HTTPS for production deployments.
3. **Token Refresh**: Use refresh tokens to automatically renew expired JWT tokens without manual intervention.
4. **Header Validation**: The server validates header values but does not enforce HTTPS. Ensure your deployment uses HTTPS.
5. **Connection Isolation**: Starting from version 1.1.10, each client session maintains its own isolated SAP connection. This prevents data mixing between different clients connecting to different SAP systems. Each connection is cached based on a unique combination of `sessionId` + `sapUrl` + authentication parameters.
6. **Non-Local Connection Restrictions**:
   - **SSE Transport**: Always restricted to localhost connections only (127.0.0.1, ::1, localhost). Remote connections are rejected with a 403 Forbidden error.
   - **HTTP Transport**: Non-local connections are restricted when:
     - `.env` file exists (was found at server startup)
     - AND request does not include SAP connection headers (`x-sap-url`, `x-sap-auth-type`)
   - Non-local connections with SAP headers are allowed (enables multi-tenant scenarios)
   - Local connections are always allowed regardless of `.env` file presence

## Troubleshooting

### Connection Issues

- Verify the server is running: `curl http://localhost:3000/health` (if health endpoint exists)
- Check server logs for configuration errors
- Verify header names are correct (case-insensitive, but recommended format: `x-sap-*`)

### Authentication Issues

- Ensure JWT token is not expired
- Verify refresh token is valid if using automatic token renewal
- Check that `x-sap-auth-type` matches your authentication method (`jwt` or `basic`)

### Token Refresh

The server supports automatic token refresh when `x-sap-refresh-token` is provided in HTTP headers (or `SAP_REFRESH_TOKEN` in `.env`).

The connection will automatically refresh expired tokens when a 401/403 error is detected. The refresh happens transparently without requiring manual intervention.

**Note:** For automatic token refresh, you only need the refresh token. Client ID and Client Secret are **not needed** for refresh - they are only required for initial token generation via `mcp-auth` CLI tool (part of `@mcp-abap-adt/connection` package).

## Examples

### JWT Authentication (with automatic refresh)

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-url": "https://5bff2ab7-3ad1-48e3-8980-53a354a1b276.abap.us10.hana.ondemand.com",
      "x-sap-auth-type": "jwt",
      "x-sap-jwt-token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ",
      "x-sap-refresh-token": "refresh_token_value_here"
    }
  }
}
```

### Basic Authentication

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-url": "https://your-onpremise-system.com:8000",
      "x-sap-auth-type": "basic",
      "x-sap-login": "your_username",
      "x-sap-password": "your_password"
    }
  }
}
```

**Note:** For basic authentication, you can pass username and password via HTTP headers (as shown above) or configure them in the server's `.env` file. Headers take priority over `.env` values:

```env
SAP_USERNAME=your_username
SAP_PASSWORD=your_password
SAP_CLIENT=100
```

### Destination-Based Authentication (HTTP Transport Only)

> **Note:** This feature is only available for **HTTP/streamable-http** transport. For **stdio** and **SSE** transports, use `.env` file configuration instead.

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http",
    "headers": {
      "x-sap-destination": "TRIAL"
    }
  }
}
```

In this case, the server will:
1. Look for `TRIAL.json` service key in `~/.config/mcp-abap-adt/service-keys/` (Unix) or `%USERPROFILE%\Documents\mcp-abap-adt\service-keys\` (Windows)
2. Check for existing session in `TRIAL.env` file
3. If no valid session exists, open browser for authentication
4. Save tokens to `TRIAL.env` for future use

### Minimal Configuration (using .env)

```json
{
  "local-mcp-http": {
    "disabled": false,
    "timeout": 60,
    "type": "streamableHttp",
    "url": "http://localhost:3000/mcp/stream/http"
  }
}
```

In this case, the server will use configuration from `.env` file.

## Related Documentation

- [Installation Guide](../installation/INSTALLATION.md)
- [Server README](../README.md)
- [Stateful Session Guide](../architecture/STATEFUL_SESSION_GUIDE.md)
