@mcp-abap-adt/proxy 0.2.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.1] - 2026-04-07
11
+
12
+ ### Added
13
+ - **Default headers injection (`defaultHeaders` / `--header`)**
14
+ - Proxy can inject configurable headers into every forwarded request
15
+ - YAML config: `defaultHeaders` map (e.g., `x-sap-destination: S4HANA_E19`)
16
+ - CLI: repeatable `--header key=value` flag
17
+ - Client headers override defaults (low priority injection)
18
+ - Enables MCP clients (Cline, Claude Code) that cannot set custom headers to pass SAP headers to the MCP server on BTP
19
+
20
+ ## [1.0.0] - 2026-04-07
21
+
22
+ ### Breaking Changes
23
+ - **Header renamed: `x-btp-destination` → `x-sap-destination`**
24
+ - The proxy now uses `x-sap-destination` header (same as MCP server) instead of the proxy-specific `x-btp-destination`
25
+ - The `--btp` CLI parameter is unchanged
26
+ - Clients sending `x-btp-destination` header must update to `x-sap-destination`
27
+
28
+ ### Added
29
+ - **Transparent reverse proxy for BTP request forwarding**
30
+ - Replaced buffered axios-based proxy with Node.js native HTTP streaming reverse proxy
31
+ - Supports any HTTP API including OpenAI-compatible streaming endpoints
32
+ - `targetUrl` parameter for explicit target URL override (`--target-url`/`--url` or `x-target-url` header)
33
+ - **Interactive configuration wizard (TUI)**
34
+ - `npx @mcp-abap-adt/proxy --tui` launches interactive setup wizard
35
+ - Service key existence checker validates BTP destination before configuration
36
+ - Generates YAML config files with inline comments
37
+ - Supports BTP and Direct URL scenarios with advanced settings
38
+ - **Dependencies updated**
39
+ - `@mcp-abap-adt/interfaces` bumped to v5
40
+ - `@mcp-abap-adt/auth-stores` bumped to v1.0.4
41
+ - Added `@inquirer/prompts` for TUI wizard
42
+
43
+ ### Fixed
44
+ - **Header validation skipped in reverse proxy mode** when config provides destination
45
+ - **YAML config file now correctly loads transport/port settings** (`--config` flag)
46
+ - **targetUrl loading from YAML config** now works correctly
47
+
10
48
  ## [0.1.9] - 2026-02-12
11
49
 
12
50
  ### Changed
@@ -45,7 +83,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
45
83
 
46
84
  ### Added
47
85
  - **Separate AuthBroker instances for BTP and ABAP destinations**
48
- - `btpAuthBroker` with `XsuaaTokenProvider` for BTP destinations (`--btp` or `x-btp-destination`)
86
+ - `btpAuthBroker` with `XsuaaTokenProvider` for BTP destinations (`--btp` or `x-sap-destination`)
49
87
  - `abapAuthBroker` with `BtpTokenProvider` for ABAP destinations (`--mcp` or `x-mcp-destination`)
50
88
  - Proper separation ensures correct token provider is used for each destination type
51
89
  - **Client Setup Guide** (`docs/CLIENT_SETUP.md`)
@@ -89,7 +127,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
89
127
  - **Documentation for BTP-Only authentication mode**
90
128
  - Added "Scenario 2: BTP Authentication Only (No SAP Configuration)" in `docs/USAGE.md`
91
129
  - Documented use case for connecting to any BTP service without SAP ABAP configuration
92
- - Explained that `x-mcp-destination` is optional when using `x-btp-destination` or `--btp`
130
+ - Explained that `x-mcp-destination` is optional when using `x-sap-destination` or `--btp`
93
131
  - Updated README.md with "BTP-Only Mode" section explaining behavior when only `--btp` is provided
94
132
  - **Enhanced help text in `bin/mcp-abap-adt-proxy.js`**
95
133
  - Added detailed "Usage Modes" section with three modes:
@@ -111,7 +149,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
111
149
  ### Fixed
112
150
  - **Unit tests updated to match new routing logic**
113
151
  - Fixed tests that expected `UNKNOWN` strategy when only `x-mcp-destination` or `x-mcp-url` is provided
114
- - Updated test expectations to reflect that `x-btp-destination` is now optional
152
+ - Updated test expectations to reflect that `x-sap-destination` is now optional
115
153
  - Added tests for `x-mcp-url` header support
116
154
  - Updated `shouldProxy` function tests to cover all routing scenarios (BTP, MCP destination, MCP URL)
117
155
  - All 51 unit tests now pass successfully
@@ -134,7 +172,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
134
172
 
135
173
  ### Added
136
174
  - **Local testing mode without BTP authentication**
137
- - Proxy can now run with only `--mcp` or `x-mcp-destination` (without `--btp` or `x-btp-destination`)
175
+ - Proxy can now run with only `--mcp` or `x-mcp-destination` (without `--btp` or `x-sap-destination`)
138
176
  - Enables local integration testing without BTP authentication
139
177
  - MCP server URL can be obtained from MCP destination service key or specified directly via `--mcp-url`
140
178
  - **`--mcp-url` parameter support**
@@ -149,16 +187,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
149
187
  - Default configuration: ADT on port 3000 (HTTP), Proxy on port 3001 (HTTP)
150
188
  - Available via `npm run test:servers`
151
189
  - **Flexible routing requirements**
152
- - Proxy accepts either `x-btp-destination/--btp`, `x-mcp-destination/--mcp`, or `x-mcp-url/--mcp-url`
190
+ - Proxy accepts either `x-sap-destination/--btp`, `x-mcp-destination/--mcp`, or `x-mcp-url/--mcp-url`
153
191
  - Removed strict requirement for BTP destination when using MCP destination or URL
154
192
 
155
193
  ### Changed
156
194
  - **Routing logic updated**
157
- - `x-btp-destination` is now optional (was required)
195
+ - `x-sap-destination` is now optional (was required)
158
196
  - Proxy can work with only `x-mcp-destination` or `x-mcp-url` for local testing
159
197
  - MCP URL can be obtained from multiple sources (priority order):
160
198
  1. `x-mcp-url` header or `--mcp-url` parameter (direct URL)
161
- 2. Service key for `x-btp-destination` (if provided)
199
+ 2. Service key for `x-sap-destination` (if provided)
162
200
  3. Service key for `x-mcp-destination` (if only MCP destination is provided)
163
201
  - **Token retrieval made optional for MCP destination**
164
202
  - Token retrieval for `mcpDestination` is now optional (won't fail if token unavailable)
package/README.md CHANGED
@@ -76,7 +76,7 @@ For detailed setup instructions for Cline and GitHub Copilot, see the **[Client
76
76
  "type": "streamableHttp",
77
77
  "url": "http://localhost:3001/mcp/stream/http",
78
78
  "headers": {
79
- "x-btp-destination": "btp-cloud"
79
+ "x-sap-destination": "btp-cloud"
80
80
  }
81
81
  }
82
82
  }
@@ -84,20 +84,42 @@ For detailed setup instructions for Cline and GitHub Copilot, see the **[Client
84
84
  ```
85
85
 
86
86
  **Required Headers:**
87
- - `x-btp-destination` - Destination name for BTP Cloud authorization token and MCP server URL
87
+ - `x-sap-destination` - Destination name for BTP Cloud authorization token and MCP server URL
88
88
 
89
89
  **Command Line Overrides:**
90
- - `--btp=<destination>` - Overrides `x-btp-destination` header (takes precedence)
90
+ - `--btp=<destination>` - Overrides `x-sap-destination` header (takes precedence)
91
91
  - `--url=<url>` - Overrides MCP server URL (required if service key lacks URL)
92
92
  - `--browser=<browser>` - Browser to use: `system` (default), `chrome`, `edge`, `firefox`, `headless`
93
93
  - `--browser-auth-port=<port>` - Port for OAuth2 callback (default: 3333)
94
94
  - `--unsafe` - Enables file-based session storage (persists tokens to disk). By default, sessions are stored in-memory (secure, lost on restart)
95
95
 
96
+ **Default Headers:**
97
+
98
+ MCP clients like Cline and Claude Code cannot set arbitrary request headers. Use default headers to inject SAP-specific headers (e.g. `x-sap-destination`, `x-sap-client`) that the target MCP server requires.
99
+
100
+ Client-supplied headers always take precedence over defaults.
101
+
102
+ Via YAML config (`defaultHeaders` map):
103
+ ```yaml
104
+ btpDestination: mcp
105
+ targetUrl: https://example.com
106
+ defaultHeaders:
107
+ x-sap-destination: S4HANA_E19
108
+ x-sap-client: "100"
109
+ ```
110
+
111
+ Via CLI (`--header`, repeatable):
112
+ ```bash
113
+ mcp-abap-adt-proxy --btp=mcp --url=https://example.com \
114
+ --header x-sap-destination=S4HANA_E19 \
115
+ --header x-sap-client=100
116
+ ```
117
+
96
118
  **How It Works:**
97
119
 
98
120
  The proxy uses BTP/XSUAA authentication:
99
121
 
100
- 1. **BTP Authentication** (if `--btp` or `x-btp-destination` is present):
122
+ 1. **BTP Authentication** (if `--btp` or `x-sap-destination` is present):
101
123
  - Uses `AuthorizationCodeProvider` (browser-based OAuth2 flow)
102
124
  - **Eager Authentication**: Opens browser immediately on startup to get token
103
125
  - Injects/overwrites `Authorization: Bearer <token>` header
@@ -106,7 +128,7 @@ The proxy uses BTP/XSUAA authentication:
106
128
 
107
129
  **BTP Authentication Mode** (with `--btp`):
108
130
  1. Proxy starts → Opens browser for login (Eager Auth) → Gets/Refreshes JWT token
109
- 2. `x-btp-destination` (or `--btp`) → Adds `Authorization: Bearer <token>` header
131
+ 2. `x-sap-destination` (or `--btp`) → Adds `Authorization: Bearer <token>` header
110
132
  3. MCP server URL obtained from service key OR `--url` parameter
111
133
 
112
134
  ## Documentation
@@ -126,16 +148,16 @@ The proxy uses BTP/XSUAA authentication:
126
148
 
127
149
  The proxy performs the following steps for each request:
128
150
 
129
- 1. **Extract Headers**: Reads `x-btp-destination` header
151
+ 1. **Extract Headers**: Reads `x-sap-destination` header
130
152
  2. **Apply Command Line Overrides**: `--btp` parameter overrides header (if provided)
131
- 3. **Validate Routing Requirements**: Requires `x-btp-destination/--btp`
132
- 4. **BTP Authentication** (if `x-btp-destination` or `--btp` is provided):
153
+ 3. **Validate Routing Requirements**: Requires `x-sap-destination/--btp`
154
+ 4. **BTP Authentication** (if `x-sap-destination` or `--btp` is provided):
133
155
  - Uses `AuthorizationCodeProvider` (browser-based login)
134
156
  - **Eagerly** obtains token on startup (if configured via `--btp`)
135
157
  - Retrieves JWT token using cached refresh token or opens browser
136
158
  - Injects/overwrites `Authorization: Bearer <token>` header
137
159
  5. **Get MCP Server URL**:
138
- - From service key for `x-btp-destination`
160
+ - From service key for `x-sap-destination`
139
161
  6. **Forward Request**: Sends request to MCP server URL with all injected headers
140
162
  7. **Return Response**: Forwards the response back to the client
141
163
 
@@ -55,13 +55,15 @@ Options:
55
55
  --sse-port=<port> SSE server port (default: 3002)
56
56
  --http-host=<host> HTTP server host (default: 0.0.0.0)
57
57
  --sse-host=<host> SSE server host (default: 0.0.0.0)
58
- --btp=<destination> Override x-btp-destination header (for BTP Cloud authorization)
58
+ --btp=<destination> Override x-sap-destination header (for BTP Cloud authorization)
59
59
  Required for stdio/SSE transports unless provided in headers
60
60
  --target-url=<url> Override target URL (separates Auth from Connection)
61
61
  Useful for direct OData service testing or non-standard MCP URLs
62
62
  --config=<file>, -c Load configuration from YAML or JSON file
63
63
  Alternative to command-line parameters
64
64
  --unsafe Enable file-based session storage (persists tokens to disk)
65
+ --header key=value Add default header to every forwarded request (repeatable)
66
+ Example: --header x-sap-destination=S4HANA
65
67
  --help, -h Show this help message
66
68
  --version, -v Show version number
67
69
 
@@ -82,6 +84,7 @@ Examples:
82
84
  mcp-abap-adt-proxy --transport=sse --sse-port=3002 # SSE mode on port 3002
83
85
  mcp-abap-adt-proxy --btp=ai # With BTP destination override
84
86
  mcp-abap-adt-proxy --btp=ai --unsafe # With file-based session storage
87
+ mcp-abap-adt-proxy --btp=ai --header x-sap-destination=S4HANA # With default SAP headers
85
88
  mcp-abap-adt-proxy tui # Interactive configuration wizard
86
89
  mcp-abap-adt-proxy --config=proxy-config.yaml # Load configuration from YAML file
87
90
  mcp-abap-adt-proxy -c proxy-config.yml # Load configuration from YAML file (short form)
@@ -100,7 +103,7 @@ Usage Modes:
100
103
  Example: mcp-abap-adt-proxy --btp=ai
101
104
 
102
105
  Headers (for HTTP/SSE transports):
103
- - x-btp-destination: Destination for BTP Cloud authorization (optional if --btp is used)
106
+ - x-sap-destination: Destination for BTP Cloud authorization (optional if --btp is used)
104
107
 
105
108
  At least one of the above headers (or corresponding --btp parameter) is required.
106
109
 
package/dist/index.js CHANGED
@@ -252,8 +252,8 @@ Authorization source: ${authSourceObj}`;
252
252
  // Get target URL
253
253
  const targetUrl = intercepted.routingDecision.targetUrl ||
254
254
  (await this.btpProxy.getTargetUrl(destination));
255
- // Forward request transparently
256
- await (0, reverseProxy_js_1.forwardRequest)(req, res, targetUrl, jwtToken);
255
+ // Forward request transparently (inject default headers from config)
256
+ await (0, reverseProxy_js_1.forwardRequest)(req, res, targetUrl, jwtToken, this.config.defaultHeaders);
257
257
  }
258
258
  catch (error) {
259
259
  logger_js_1.logger?.error('Proxy request failed', {
@@ -9,6 +9,7 @@ export interface ProxyConfig {
9
9
  logLevel: string;
10
10
  btpDestination?: string;
11
11
  targetUrl?: string;
12
+ defaultHeaders?: Record<string, string>;
12
13
  unsafe?: boolean;
13
14
  maxRetries?: number;
14
15
  retryDelay?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAEjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,CAqC3D;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,mBAAmB,CAQrB;AAgBD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAYhC;AA0GD;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAUD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAoDA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAEjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAGxC,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAG/B,OAAO,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACzE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,CAqC3D;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,mBAAmB,CAQrB;AAgBD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAYhC;AA4ID;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAElD;AAUD;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG;IACnD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAoDA"}
@@ -137,6 +137,7 @@ function applyDefaults(fileConfig) {
137
137
  logLevel: fileConfig.logLevel || 'info',
138
138
  btpDestination: fileConfig.btpDestination,
139
139
  targetUrl: fileConfig.targetUrl,
140
+ defaultHeaders: fileConfig.defaultHeaders,
140
141
  unsafe: fileConfig.unsafe ?? false,
141
142
  maxRetries: fileConfig.maxRetries ?? 3,
142
143
  retryDelay: fileConfig.retryDelay ?? 1000,
@@ -161,6 +162,20 @@ function loadFromEnv() {
161
162
  const browserAuthPort = browserAuthPortStr
162
163
  ? parseInt(browserAuthPortStr, 10)
163
164
  : undefined;
165
+ // Parse repeatable --header key=value arguments
166
+ const headerArgs = getAllArgValues('--header');
167
+ let defaultHeaders;
168
+ if (headerArgs.length > 0) {
169
+ defaultHeaders = {};
170
+ for (const arg of headerArgs) {
171
+ const eqIndex = arg.indexOf('=');
172
+ if (eqIndex > 0) {
173
+ const key = arg.substring(0, eqIndex).toLowerCase();
174
+ const value = arg.substring(eqIndex + 1);
175
+ defaultHeaders[key] = value;
176
+ }
177
+ }
178
+ }
164
179
  return {
165
180
  httpPort: parseInt(process.env.MCP_HTTP_PORT || '3001', 10),
166
181
  ssePort: parseInt(process.env.MCP_SSE_PORT || '3002', 10),
@@ -169,6 +184,7 @@ function loadFromEnv() {
169
184
  logLevel: process.env.LOG_LEVEL || 'info',
170
185
  btpDestination,
171
186
  targetUrl,
187
+ defaultHeaders,
172
188
  unsafe,
173
189
  maxRetries: parseInt(process.env.MCP_PROXY_MAX_RETRIES || '3', 10),
174
190
  retryDelay: parseInt(process.env.MCP_PROXY_RETRY_DELAY || '1000', 10),
@@ -194,6 +210,22 @@ function getArgValue(argName) {
194
210
  }
195
211
  return undefined;
196
212
  }
213
+ /**
214
+ * Get all values for a repeatable argument from command line
215
+ */
216
+ function getAllArgValues(argName) {
217
+ const args = process.argv;
218
+ const values = [];
219
+ for (let i = 0; i < args.length; i++) {
220
+ if (args[i] === argName && i + 1 < args.length) {
221
+ values.push(args[i + 1]);
222
+ }
223
+ if (args[i].startsWith(`${argName}=`)) {
224
+ values.push(args[i].substring(argName.length + 1));
225
+ }
226
+ }
227
+ return values;
228
+ }
197
229
  /**
198
230
  * Get config file path from command line (--config or -c)
199
231
  */
@@ -217,7 +249,7 @@ function validateConfig(config) {
217
249
  // Check if BTP destination is provided
218
250
  const hasDestination = config.btpDestination;
219
251
  if (!hasDestination) {
220
- warnings.push('No BTP destination provided (--btp). Proxy will not work unless requests include x-btp-destination header.');
252
+ warnings.push('No BTP destination provided (--btp). Proxy will not work unless requests include x-sap-destination header.');
221
253
  }
222
254
  if (config.httpPort < 1 || config.httpPort > 65535) {
223
255
  errors.push('MCP_HTTP_PORT must be between 1 and 65535');
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * BTP Proxy - Proxies requests to MCP servers with JWT authentication
3
3
  *
4
- * For requests with x-btp-destination, proxies to target MCP server
4
+ * For requests with x-sap-destination, proxies to target MCP server
5
5
  * with JWT token from auth-broker (XSUAA/BTP)
6
6
  */
7
7
  import { AuthBroker } from '@mcp-abap-adt/auth-broker';
@@ -79,7 +79,7 @@ export declare class BtpProxy {
79
79
  * Process flow:
80
80
  *
81
81
  * 1. BTP Authentication (XSUAA):
82
- * 1.1 If x-btp-destination header exists:
82
+ * 1.1 If x-sap-destination header exists:
83
83
  * - Check map for broker with key = destination, get or create, save to map
84
84
  * - Get token from xsuaa broker
85
85
  * - Add/replace Authorization: Bearer <token> header
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * BTP Proxy - Proxies requests to MCP servers with JWT authentication
4
4
  *
5
- * For requests with x-btp-destination, proxies to target MCP server
5
+ * For requests with x-sap-destination, proxies to target MCP server
6
6
  * with JWT token from auth-broker (XSUAA/BTP)
7
7
  */
8
8
  var __importDefault = (this && this.__importDefault) || function (mod) {
@@ -437,7 +437,7 @@ class BtpProxy {
437
437
  * Process flow:
438
438
  *
439
439
  * 1. BTP Authentication (XSUAA):
440
- * 1.1 If x-btp-destination header exists:
440
+ * 1.1 If x-sap-destination header exists:
441
441
  * - Check map for broker with key = destination, get or create, save to map
442
442
  * - Get token from xsuaa broker
443
443
  * - Add/replace Authorization: Bearer <token> header
@@ -464,21 +464,21 @@ class BtpProxy {
464
464
  // ============================================
465
465
  // BTP Authentication (XSUAA)
466
466
  // ============================================
467
- const btpDestinationHeader = this.getHeaderValue(originalHeaders[interfaces_1.HEADER_BTP_DESTINATION]);
467
+ const btpDestinationHeader = this.getHeaderValue(originalHeaders[interfaces_1.HEADER_SAP_DESTINATION]);
468
468
  const btpDestinationFromParam = routingDecision.btpDestination && !btpDestinationHeader
469
469
  ? routingDecision.btpDestination
470
470
  : undefined;
471
471
  let btpDestination;
472
472
  if (btpDestinationHeader) {
473
473
  btpDestination = btpDestinationHeader;
474
- logger_js_1.logger?.debug('Using x-btp-destination from header', {
474
+ logger_js_1.logger?.debug('Using x-sap-destination from header', {
475
475
  type: 'BTP_DESTINATION_FROM_HEADER',
476
476
  destination: btpDestination,
477
477
  });
478
478
  }
479
479
  else if (btpDestinationFromParam) {
480
480
  btpDestination = btpDestinationFromParam;
481
- logger_js_1.logger?.debug('Using x-btp-destination from parameter', {
481
+ logger_js_1.logger?.debug('Using x-sap-destination from parameter', {
482
482
  type: 'BTP_DESTINATION_FROM_PARAM',
483
483
  destination: btpDestination,
484
484
  });
@@ -3,5 +3,5 @@ import * as http from 'node:http';
3
3
  * Forward an HTTP request to a target URL with JWT injection.
4
4
  * Streams both request and response using pipe().
5
5
  */
6
- export declare function forwardRequest(clientReq: http.IncomingMessage, clientRes: http.ServerResponse, targetBaseUrl: string, jwtToken: string): Promise<void>;
6
+ export declare function forwardRequest(clientReq: http.IncomingMessage, clientRes: http.ServerResponse, targetBaseUrl: string, jwtToken: string, defaultHeaders?: Record<string, string>): Promise<void>;
7
7
  //# sourceMappingURL=reverseProxy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reverseProxy.d.ts","sourceRoot":"","sources":["../../src/proxy/reverseProxy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAoBlC;;;GAGG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,SAAS,EAAE,IAAI,CAAC,cAAc,EAC9B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA+Ef"}
1
+ {"version":3,"file":"reverseProxy.d.ts","sourceRoot":"","sources":["../../src/proxy/reverseProxy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAoBlC;;;GAGG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,IAAI,CAAC,eAAe,EAC/B,SAAS,EAAE,IAAI,CAAC,cAAc,EAC9B,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAwFf"}
@@ -57,10 +57,17 @@ const HOP_BY_HOP_HEADERS = new Set([
57
57
  * Forward an HTTP request to a target URL with JWT injection.
58
58
  * Streams both request and response using pipe().
59
59
  */
60
- async function forwardRequest(clientReq, clientRes, targetBaseUrl, jwtToken) {
60
+ async function forwardRequest(clientReq, clientRes, targetBaseUrl, jwtToken, defaultHeaders) {
61
61
  const targetUrl = new node_url_1.URL(clientReq.url || '/', targetBaseUrl);
62
- // Build forwarded headers (skip hop-by-hop and replace auth)
62
+ // Build forwarded headers: defaults first, then client headers override
63
63
  const forwardedHeaders = {};
64
+ // 1. Inject default headers (low priority)
65
+ if (defaultHeaders) {
66
+ for (const [key, value] of Object.entries(defaultHeaders)) {
67
+ forwardedHeaders[key.toLowerCase()] = value;
68
+ }
69
+ }
70
+ // 2. Copy client headers (high priority — overrides defaults)
64
71
  for (const [key, value] of Object.entries(clientReq.headers)) {
65
72
  if (HOP_BY_HOP_HEADERS.has(key.toLowerCase()))
66
73
  continue;
@@ -18,17 +18,17 @@ export interface RoutingDecision {
18
18
  * Analyze headers and extract routing information
19
19
  *
20
20
  * Proxy validates only one header for authentication:
21
- * - x-btp-destination (or --btp): destination for BTP Cloud authorization token (Authorization: Bearer) and MCP server URL
21
+ * - x-sap-destination (or --btp): destination for BTP Cloud authorization token (Authorization: Bearer) and MCP server URL
22
22
  *
23
23
 
24
24
  *
25
25
  * Command-line overrides (take precedence over headers):
26
- * - --btp=<destination>: overrides x-btp-destination header
26
+ * - --btp=<destination>: overrides x-sap-destination header
27
27
  *
28
28
  * Other headers are passed directly to MCP server without validation.
29
29
  *
30
30
  * MPC server URL is obtained from:
31
- * - service key for x-btp-destination (via auth-broker)
31
+ * - service key for x-sap-destination (via auth-broker)
32
32
  *
33
33
  *
34
34
  * Note: Proxy does NOT use .env files for connection configuration. Only destinations via auth-broker (service key files) are used.
@@ -19,17 +19,17 @@ var RoutingStrategy;
19
19
  * Analyze headers and extract routing information
20
20
  *
21
21
  * Proxy validates only one header for authentication:
22
- * - x-btp-destination (or --btp): destination for BTP Cloud authorization token (Authorization: Bearer) and MCP server URL
22
+ * - x-sap-destination (or --btp): destination for BTP Cloud authorization token (Authorization: Bearer) and MCP server URL
23
23
  *
24
24
 
25
25
  *
26
26
  * Command-line overrides (take precedence over headers):
27
- * - --btp=<destination>: overrides x-btp-destination header
27
+ * - --btp=<destination>: overrides x-sap-destination header
28
28
  *
29
29
  * Other headers are passed directly to MCP server without validation.
30
30
  *
31
31
  * MPC server URL is obtained from:
32
- * - service key for x-btp-destination (via auth-broker)
32
+ * - service key for x-sap-destination (via auth-broker)
33
33
  *
34
34
  *
35
35
  * Note: Proxy does NOT use .env files for connection configuration. Only destinations via auth-broker (service key files) are used.
@@ -48,9 +48,9 @@ function analyzeHeaders(headers, configOverrides) {
48
48
  }
49
49
  return typeof headerValue === 'string' ? headerValue.trim() : undefined;
50
50
  };
51
- // Extract authorization destination for BTP Cloud (x-btp-destination)
51
+ // Extract authorization destination for BTP Cloud (x-sap-destination)
52
52
  // Command-line parameter --btp takes precedence over header
53
- const btpDestinationHeader = getHeaderValue(interfaces_1.HEADER_BTP_DESTINATION);
53
+ const btpDestinationHeader = getHeaderValue(interfaces_1.HEADER_SAP_DESTINATION);
54
54
  const extractedBtpDestination = configOverrides?.btpDestination
55
55
  ? configOverrides.btpDestination
56
56
  : btpDestinationHeader;
@@ -72,10 +72,10 @@ function analyzeHeaders(headers, configOverrides) {
72
72
  if (!extractedBtpDestination) {
73
73
  return {
74
74
  strategy: RoutingStrategy.UNKNOWN,
75
- reason: 'No BTP destination provided (missing x-btp-destination or --btp)',
75
+ reason: 'No BTP destination provided (missing x-sap-destination or --btp)',
76
76
  };
77
77
  }
78
- // If x-btp-destination is present, we can proxy with BTP authentication (URL will be obtained from service key)
78
+ // If x-sap-destination is present, we can proxy with BTP authentication (URL will be obtained from service key)
79
79
  // If x-mcp-url is provided, we can use it directly (for local testing)
80
80
  logger_js_1.logger?.debug('Routing decision: PROXY', {
81
81
  btpDestination: extractedBtpDestination,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/proxy",
3
- "version": "0.2.0",
3
+ "version": "1.0.1",
4
4
  "description": "MCP proxy server for SAP ABAP ADT - proxies local requests to cloud-llm-hub with JWT authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",