@mcp-abap-adt/proxy 2.0.0 → 4.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 +218 -0
- package/LICENSE +669 -17
- package/README.md +79 -8
- package/bin/mcp-abap-adt-proxy-mcp.js +113 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -97
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +9 -1
- package/dist/lib/envInterpolation.d.ts +14 -2
- package/dist/lib/envInterpolation.d.ts.map +1 -1
- package/dist/lib/envInterpolation.js +34 -7
- package/dist/lib/stores.d.ts +23 -2
- package/dist/lib/stores.d.ts.map +1 -1
- package/dist/lib/stores.js +56 -1
- package/dist/mcp/cli.d.ts +2 -0
- package/dist/mcp/cli.d.ts.map +1 -0
- package/dist/mcp/cli.js +21 -0
- package/dist/mcp/configs.d.ts +33 -0
- package/dist/mcp/configs.d.ts.map +1 -0
- package/dist/mcp/configs.js +142 -0
- package/dist/mcp/ports.d.ts +15 -0
- package/dist/mcp/ports.d.ts.map +1 -0
- package/dist/mcp/ports.js +35 -0
- package/dist/mcp/registry.d.ts +57 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +145 -0
- package/dist/mcp/server.d.ts +34 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +79 -0
- package/dist/mcp/shutdown.d.ts +37 -0
- package/dist/mcp/shutdown.d.ts.map +1 -0
- package/dist/mcp/shutdown.js +82 -0
- package/dist/mcp/supervisor.d.ts +125 -0
- package/dist/mcp/supervisor.d.ts.map +1 -0
- package/dist/mcp/supervisor.js +330 -0
- package/dist/mcp/tools.d.ts +28 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +152 -0
- package/dist/proxy/btpProxy.d.ts +24 -73
- package/dist/proxy/btpProxy.d.ts.map +1 -1
- package/dist/proxy/btpProxy.js +65 -616
- package/dist/proxy/credentials.d.ts +45 -0
- package/dist/proxy/credentials.d.ts.map +1 -0
- package/dist/proxy/credentials.js +41 -0
- package/dist/proxy/requestHandler.d.ts +38 -0
- package/dist/proxy/requestHandler.d.ts.map +1 -0
- package/dist/proxy/requestHandler.js +73 -0
- package/dist/proxy/reverseProxy.d.ts +11 -2
- package/dist/proxy/reverseProxy.d.ts.map +1 -1
- package/dist/proxy/reverseProxy.js +52 -9
- package/dist/router/headerAnalyzer.js +2 -2
- package/dist/router/requestInterceptor.js +9 -9
- package/docs/API.md +172 -0
- package/docs/ARCHITECTURE.md +322 -0
- package/docs/CLIENT_SETUP.md +413 -0
- package/docs/CONFIGURATION.md +258 -0
- package/docs/MIGRATION-4.0.md +125 -0
- package/docs/ROUTING_LOGIC.md +126 -0
- package/docs/TROUBLESHOOTING.md +488 -0
- package/docs/USAGE.md +422 -0
- package/docs/YAML_CONFIG.md +290 -0
- package/docs/mcp-proxy-config.example.yaml +62 -0
- package/package.json +17 -10
- package/dist/proxy/cloudLlmHubProxy.d.ts +0 -2
- package/dist/proxy/cloudLlmHubProxy.d.ts.map +0 -1
- package/dist/proxy/cloudLlmHubProxy.js +0 -3
package/docs/USAGE.md
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# Usage Examples
|
|
2
|
+
|
|
3
|
+
This document provides practical examples of using `@mcp-abap-adt/proxy`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @mcp-abap-adt/proxy
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic Usage
|
|
12
|
+
|
|
13
|
+
### Starting the Proxy Server
|
|
14
|
+
|
|
15
|
+
#### Using a BTP destination
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Start server with a BTP destination (matches a service-key file)
|
|
19
|
+
mcp-abap-adt-proxy --btp=btp-cloud
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
#### Using a Configuration File
|
|
23
|
+
|
|
24
|
+
Create `mcp-proxy-config.yaml` (see [YAML Configuration Guide](./YAML_CONFIG.md)):
|
|
25
|
+
|
|
26
|
+
```yaml
|
|
27
|
+
transport: streamable-http
|
|
28
|
+
httpPort: 3001
|
|
29
|
+
btpDestination: "btp-cloud"
|
|
30
|
+
logLevel: "info"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Start server:
|
|
34
|
+
```bash
|
|
35
|
+
mcp-abap-adt-proxy --config=mcp-proxy-config.yaml
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Using Environment Variables
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
export MCP_HTTP_PORT=8080
|
|
42
|
+
export LOG_LEVEL=debug
|
|
43
|
+
mcp-abap-adt-proxy --btp=btp-cloud
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Usage Scenarios
|
|
47
|
+
|
|
48
|
+
### Scenario 1: BTP Authentication Mode
|
|
49
|
+
|
|
50
|
+
**Use Case:** Proxy requests to an MCP server on BTP with JWT authentication
|
|
51
|
+
|
|
52
|
+
**Client Configuration:**
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcp-abap-adt-proxy": {
|
|
56
|
+
"disabled": false,
|
|
57
|
+
"timeout": 60,
|
|
58
|
+
"type": "streamableHttp",
|
|
59
|
+
"url": "http://localhost:3001/mcp/stream/http",
|
|
60
|
+
"headers": {
|
|
61
|
+
"x-sap-destination": "btp-cloud"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**What Happens:**
|
|
68
|
+
1. Proxy receives request with `x-sap-destination` header
|
|
69
|
+
2. Command line override (`--btp`) takes precedence over header if provided
|
|
70
|
+
3. Uses `btpAuthBroker` with `ClientCredentialsProvider` to get BTP Cloud token from service key
|
|
71
|
+
4. Gets MCP server URL from service key (`abap.url` field)
|
|
72
|
+
5. Injects/overwrites `Authorization: Bearer <btp-token>` header
|
|
73
|
+
6. Proxies request to MCP server URL from service key
|
|
74
|
+
7. Target MCP server processes request and returns response
|
|
75
|
+
8. Proxy forwards response to client
|
|
76
|
+
|
|
77
|
+
**Using Command Line Overrides:**
|
|
78
|
+
|
|
79
|
+
You can override headers using command line parameters:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Override x-sap-destination with --btp
|
|
83
|
+
mcp-abap-adt-proxy --btp=ai
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Command line parameters work even if the corresponding headers are missing in the request.
|
|
87
|
+
|
|
88
|
+
### Scenario 2: BTP Auth with Target URL Override
|
|
89
|
+
|
|
90
|
+
**Use Case:** Authenticate with one BTP destination's service key, but forward requests
|
|
91
|
+
to a different URL (e.g. direct OData testing or a non-standard MCP path).
|
|
92
|
+
|
|
93
|
+
**Client Configuration:**
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcp-abap-adt-proxy": {
|
|
97
|
+
"disabled": false,
|
|
98
|
+
"timeout": 60,
|
|
99
|
+
"type": "streamableHttp",
|
|
100
|
+
"url": "http://localhost:3001/mcp/stream/http",
|
|
101
|
+
"headers": {
|
|
102
|
+
"x-sap-destination": "btp-cloud",
|
|
103
|
+
"x-target-url": "https://your-service.cfapps.eu10.hana.ondemand.com"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Or using command line:**
|
|
110
|
+
```bash
|
|
111
|
+
mcp-abap-adt-proxy --btp=btp-cloud \
|
|
112
|
+
--target-url=https://your-service.cfapps.eu10.hana.ondemand.com
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**What Happens:**
|
|
116
|
+
1. Proxy gets a BTP token from the `btp-cloud` service key
|
|
117
|
+
2. Injects `Authorization: Bearer <token>`
|
|
118
|
+
3. Forwards the request to `x-target-url` / `--target-url` instead of the key's `abap.url`
|
|
119
|
+
4. Target server processes request and returns response
|
|
120
|
+
|
|
121
|
+
**Service Key Structure:**
|
|
122
|
+
The service key for BTP destination should contain the MCP server URL:
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"uaa": {
|
|
126
|
+
"url": "https://your-uaa-url.com",
|
|
127
|
+
"clientid": "your-client-id",
|
|
128
|
+
"clientsecret": "your-client-secret"
|
|
129
|
+
},
|
|
130
|
+
"abap": {
|
|
131
|
+
"url": "https://your-mcp-server.com"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The `abap.url` field is used as the MCP server URL (even though it's named "abap", it can point to any MCP server).
|
|
137
|
+
|
|
138
|
+
## The management mode
|
|
139
|
+
|
|
140
|
+
A second command, `mcp-abap-adt-proxy-mcp`, speaks MCP over stdio and its tools
|
|
141
|
+
start and stop proxies. Use it when the client should decide which proxy runs and
|
|
142
|
+
when; use `mcp-abap-adt-proxy` when you want to be proxied.
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"mcpServers": {
|
|
147
|
+
"abap-proxy": { "command": "mcp-abap-adt-proxy-mcp" }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
It works from the configs in `~/.config/mcp-abap-adt/proxy/` — the same files
|
|
153
|
+
`--config` takes — so starting a proxy is choosing a name:
|
|
154
|
+
|
|
155
|
+
| Tool | |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `proxy_configs` | the names available; call it first, they cannot be guessed |
|
|
158
|
+
| `proxy_start` | starts one on a **free port** and returns the URL bound |
|
|
159
|
+
| `proxy_stop` | frees the port and releases the credential; never touches another session's proxy |
|
|
160
|
+
| `proxy_status` | this session's proxies and everyone else's, dead records pruned on read |
|
|
161
|
+
|
|
162
|
+
Two things worth knowing before you rely on it:
|
|
163
|
+
|
|
164
|
+
- **The proxies live in the management process.** Closing the session — or
|
|
165
|
+
`SIGINT`, or `SIGTERM` — stops all of them. A stop cuts requests still in
|
|
166
|
+
flight after a short grace, because a streamed response never ends on its own
|
|
167
|
+
and the port has to come back.
|
|
168
|
+
- **`proxy_start` proves the credential before reporting success**, so an
|
|
169
|
+
interactive login happens where you asked for it rather than inside whatever
|
|
170
|
+
tool call happens to make the first request.
|
|
171
|
+
|
|
172
|
+
See [Configuration](./CONFIGURATION.md#the-management-mode) for `idleTimeoutMs`
|
|
173
|
+
and what the mode deliberately ignores from a config.
|
|
174
|
+
|
|
175
|
+
## Programmatic Usage
|
|
176
|
+
|
|
177
|
+
### Using as a Library
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
import { McpAbapAdtProxyServer } from "@mcp-abap-adt/proxy";
|
|
181
|
+
|
|
182
|
+
async function main() {
|
|
183
|
+
const server = new McpAbapAdtProxyServer();
|
|
184
|
+
|
|
185
|
+
// Handle shutdown gracefully
|
|
186
|
+
process.on("SIGINT", async () => {
|
|
187
|
+
await server.shutdown();
|
|
188
|
+
process.exit(0);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
await server.run();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
main().catch(console.error);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Custom Configuration
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { McpAbapAdtProxyServer } from "@mcp-abap-adt/proxy";
|
|
201
|
+
import { parseTransportConfig } from "@mcp-abap-adt/proxy/lib/transportConfig";
|
|
202
|
+
|
|
203
|
+
const transportConfig = parseTransportConfig();
|
|
204
|
+
const server = new McpAbapAdtProxyServer(
|
|
205
|
+
transportConfig,
|
|
206
|
+
"/path/to/custom-config.json"
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
await server.run();
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Transport Modes
|
|
213
|
+
|
|
214
|
+
### HTTP/Streamable HTTP (Default)
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
mcp-abap-adt-proxy --transport=streamable-http --http-port=3001
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### SSE (Server-Sent Events)
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
mcp-abap-adt-proxy --transport=sse --sse-port=3002
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Stdio (for MCP clients)
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
mcp-abap-adt-proxy --transport=stdio
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Advanced Configuration
|
|
233
|
+
|
|
234
|
+
### Custom Retry Settings
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
btpDestination: "btp-cloud"
|
|
238
|
+
maxRetries: 5
|
|
239
|
+
retryDelay: 2000
|
|
240
|
+
requestTimeout: 120000
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Circuit Breaker Configuration
|
|
244
|
+
|
|
245
|
+
```yaml
|
|
246
|
+
btpDestination: "btp-cloud"
|
|
247
|
+
circuitBreakerThreshold: 10
|
|
248
|
+
circuitBreakerTimeout: 120000
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Integration Examples
|
|
252
|
+
|
|
253
|
+
### With Cline
|
|
254
|
+
|
|
255
|
+
1. Install proxy:
|
|
256
|
+
```bash
|
|
257
|
+
npm install -g @mcp-abap-adt/proxy
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
2. Start proxy server:
|
|
261
|
+
```bash
|
|
262
|
+
mcp-abap-adt-proxy --btp=btp-cloud
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
3. Configure Cline (`cline.json`):
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"mcpServers": {
|
|
269
|
+
"mcp-abap-adt-proxy": {
|
|
270
|
+
"disabled": false,
|
|
271
|
+
"timeout": 60,
|
|
272
|
+
"type": "streamableHttp",
|
|
273
|
+
"url": "http://localhost:3001/mcp/stream/http",
|
|
274
|
+
"headers": {
|
|
275
|
+
"x-sap-destination": "btp-cloud"
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### With Custom MCP Client
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import axios from "axios";
|
|
286
|
+
|
|
287
|
+
async function callProxy(method: string, params: any) {
|
|
288
|
+
const response = await axios.post(
|
|
289
|
+
"http://localhost:3001/mcp/stream/http",
|
|
290
|
+
{
|
|
291
|
+
jsonrpc: "2.0",
|
|
292
|
+
method,
|
|
293
|
+
params,
|
|
294
|
+
id: 1,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
headers: {
|
|
298
|
+
"Content-Type": "application/json",
|
|
299
|
+
"x-sap-destination": "btp-cloud",
|
|
300
|
+
},
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
return response.data;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Example usage
|
|
308
|
+
const result = await callProxy("tools/list", {});
|
|
309
|
+
console.log(result);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Service Key Setup
|
|
313
|
+
|
|
314
|
+
For BTP destination-based authentication, you need to set up service keys:
|
|
315
|
+
|
|
316
|
+
1. Create service key file: `btp-cloud.json`
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"uaa": {
|
|
320
|
+
"url": "https://your-uaa-url.com",
|
|
321
|
+
"clientid": "your-client-id",
|
|
322
|
+
"clientsecret": "your-client-secret"
|
|
323
|
+
},
|
|
324
|
+
"abap": {
|
|
325
|
+
"url": "https://your-mcp-server.com"
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
2. Place service key in platform-specific location:
|
|
331
|
+
- **Unix**: `~/.config/mcp-abap-adt/service-keys/btp-cloud.json`
|
|
332
|
+
- **Windows**: `%USERPROFILE%\Documents\mcp-abap-adt\service-keys\btp-cloud.json`
|
|
333
|
+
|
|
334
|
+
3. Use destination in proxy:
|
|
335
|
+
```bash
|
|
336
|
+
mcp-abap-adt-proxy --btp=btp-cloud
|
|
337
|
+
```
|
|
338
|
+
Or via header:
|
|
339
|
+
```json
|
|
340
|
+
{
|
|
341
|
+
"headers": {
|
|
342
|
+
"x-sap-destination": "btp-cloud"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Debugging
|
|
348
|
+
|
|
349
|
+
### Enable Debug Logging
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
export LOG_LEVEL=debug
|
|
353
|
+
mcp-abap-adt-proxy --btp=btp-cloud
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Check Routing Decisions
|
|
357
|
+
|
|
358
|
+
The proxy logs routing decisions:
|
|
359
|
+
```
|
|
360
|
+
[INFO] Routing decision made: { strategy: "PROXY", btpDestination: "btp-cloud" }
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Monitor Circuit Breaker
|
|
364
|
+
|
|
365
|
+
Circuit breaker state is logged:
|
|
366
|
+
```
|
|
367
|
+
[WARN] Circuit breaker opened due to failures: { failures: 5, threshold: 5 }
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Common Patterns
|
|
371
|
+
|
|
372
|
+
### Pattern 1: Development Environment
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
export LOG_LEVEL=debug
|
|
376
|
+
export MCP_HTTP_PORT=3001
|
|
377
|
+
|
|
378
|
+
mcp-abap-adt-proxy --btp=dev-btp
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Pattern 2: Production Environment
|
|
382
|
+
|
|
383
|
+
```yaml
|
|
384
|
+
# mcp-proxy-config.yaml
|
|
385
|
+
transport: streamable-http
|
|
386
|
+
httpPort: 3001
|
|
387
|
+
btpDestination: "prod-btp"
|
|
388
|
+
logLevel: "info"
|
|
389
|
+
maxRetries: 5
|
|
390
|
+
circuitBreakerThreshold: 10
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Pattern 3: Multiple Destinations
|
|
394
|
+
|
|
395
|
+
Use different destination names for different environments:
|
|
396
|
+
|
|
397
|
+
```json
|
|
398
|
+
{
|
|
399
|
+
"headers": {
|
|
400
|
+
"x-sap-destination": "dev-btp"
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
{
|
|
407
|
+
"headers": {
|
|
408
|
+
"x-sap-destination": "prod-btp"
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Pattern 4: Using Command Line Overrides
|
|
414
|
+
|
|
415
|
+
Override destination via command line (useful for development/testing):
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
# Use 'ai' for BTP regardless of headers
|
|
419
|
+
mcp-abap-adt-proxy --btp=ai
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
This is especially useful when you want to use the same destination for all requests without modifying client configuration.
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# YAML Configuration Guide
|
|
2
|
+
|
|
3
|
+
The MCP ABAP ADT Proxy supports loading configuration from YAML or JSON files, providing a convenient alternative to command-line parameters and environment variables.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
1. Copy the example configuration file:
|
|
8
|
+
```bash
|
|
9
|
+
cp docs/mcp-proxy-config.example.yaml mcp-proxy-config.yaml
|
|
10
|
+
```
|
|
11
|
+
Or from the project root:
|
|
12
|
+
```bash
|
|
13
|
+
cp mcp-proxy-config.example.yaml mcp-proxy-config.yaml
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. Customize the configuration for your environment
|
|
17
|
+
|
|
18
|
+
3. Run the proxy with the config file:
|
|
19
|
+
```bash
|
|
20
|
+
mcp-abap-adt-proxy --config=mcp-proxy-config.yaml
|
|
21
|
+
```
|
|
22
|
+
Or use the short form:
|
|
23
|
+
```bash
|
|
24
|
+
mcp-abap-adt-proxy -c mcp-proxy-config.yaml
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Configuration File Location
|
|
28
|
+
|
|
29
|
+
There is **no auto-discovery**. The config file is loaded **only** when you pass it
|
|
30
|
+
explicitly via `--config` (or `-c`):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
mcp-abap-adt-proxy --config=/path/to/mcp-proxy-config.yaml
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Both `.yaml`/`.yml` and `.json` files are supported (format is detected by extension).
|
|
37
|
+
|
|
38
|
+
## Configuration Modes
|
|
39
|
+
|
|
40
|
+
- **With `--config`**: configuration is loaded from the file as the baseline.
|
|
41
|
+
CLI flags (`--btp`, `--target-url`, `--unsafe`, `--browser`, `--browser-auth-port`,
|
|
42
|
+
`--header`) override matching values from the file; `--header` entries are merged
|
|
43
|
+
per key with `defaultHeaders`. Any value missing from both falls back to its
|
|
44
|
+
built-in default. The proxy logs which keys were overridden on startup.
|
|
45
|
+
- **Without `--config`**: configuration comes from CLI parameters and environment
|
|
46
|
+
variables only (see [CONFIGURATION.md](./CONFIGURATION.md)). The config file is
|
|
47
|
+
not consulted.
|
|
48
|
+
|
|
49
|
+
## YAML Configuration Template
|
|
50
|
+
|
|
51
|
+
```yaml
|
|
52
|
+
# MCP ABAP ADT Proxy Configuration
|
|
53
|
+
# Load explicitly: mcp-abap-adt-proxy --config=mcp-proxy-config.yaml
|
|
54
|
+
|
|
55
|
+
# Transport configuration
|
|
56
|
+
transport: streamable-http # stdio | http | streamable-http | sse
|
|
57
|
+
httpPort: 3001
|
|
58
|
+
httpHost: "127.0.0.1"
|
|
59
|
+
ssePort: 3002
|
|
60
|
+
sseHost: "127.0.0.1"
|
|
61
|
+
|
|
62
|
+
# BTP destination for Cloud authorization (Authorization: Bearer token).
|
|
63
|
+
# Must match a service key: ~/.config/mcp-abap-adt/service-keys/<btpDestination>.json
|
|
64
|
+
btpDestination: "btp"
|
|
65
|
+
|
|
66
|
+
# Target URL override (optional). Auth still comes from the service key above,
|
|
67
|
+
# but requests are forwarded here instead of the key's abap.url.
|
|
68
|
+
# targetUrl: "https://your-service.cfapps.eu10.hana.ondemand.com"
|
|
69
|
+
|
|
70
|
+
# Default headers injected into every forwarded request.
|
|
71
|
+
# Client-supplied headers take precedence over these.
|
|
72
|
+
defaultHeaders:
|
|
73
|
+
x-sap-destination: "S4HANA_E19"
|
|
74
|
+
|
|
75
|
+
# OAuth2 login browser
|
|
76
|
+
browser: "system" # system | headless | chrome | edge | firefox | none
|
|
77
|
+
browserAuthPort: 7777 # port for the local OAuth2 callback server;
|
|
78
|
+
# bound only while you are logging in, then released.
|
|
79
|
+
# Pick a number no other local service listens on.
|
|
80
|
+
|
|
81
|
+
# Session storage mode
|
|
82
|
+
unsafe: false # If true, persists tokens to disk. If false, uses in-memory storage (secure)
|
|
83
|
+
|
|
84
|
+
# Error handling & resilience
|
|
85
|
+
maxRetries: 3
|
|
86
|
+
retryDelay: 1000 # milliseconds
|
|
87
|
+
requestTimeout: 60000 # milliseconds
|
|
88
|
+
|
|
89
|
+
# Logging
|
|
90
|
+
logLevel: "info" # debug | info | warn | error
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Configuration Examples
|
|
94
|
+
|
|
95
|
+
### Example 1: BTP Authentication Mode
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
transport: http
|
|
99
|
+
httpPort: 3001
|
|
100
|
+
btpDestination: "btp"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Run with:
|
|
104
|
+
```bash
|
|
105
|
+
mcp-abap-adt-proxy --config=mcp-proxy-config.yaml
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Example 2: BTP Auth with Target URL Override
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
transport: http
|
|
112
|
+
httpPort: 3001
|
|
113
|
+
btpDestination: "btp"
|
|
114
|
+
targetUrl: "https://your-service.cfapps.eu10.hana.ondemand.com/v1"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Auth tokens come from the `btp` service key, but requests are forwarded to `targetUrl` instead of the URL in the service key.
|
|
118
|
+
|
|
119
|
+
### Example 3: BTP Auth with Per-User ABAP Credentials
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
transport: streamable-http
|
|
123
|
+
httpPort: 3001
|
|
124
|
+
btpDestination: "btp"
|
|
125
|
+
envFile: "secrets.env" # resolved relative to this file's directory
|
|
126
|
+
defaultHeaders:
|
|
127
|
+
x-sap-destination: "S4HANA_E19"
|
|
128
|
+
x-sap-login: "${SAP_USER}"
|
|
129
|
+
x-sap-password: "${SAP_PASSWORD}"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Every forwarded request gets `x-sap-destination` (unless the client supplies one)
|
|
133
|
+
plus the caller's `x-sap-login` / `x-sap-password`, resolved from environment
|
|
134
|
+
variables.
|
|
135
|
+
|
|
136
|
+
#### Environment-variable interpolation
|
|
137
|
+
|
|
138
|
+
String config values may contain `${VAR}` or `${VAR:-default}` placeholders:
|
|
139
|
+
|
|
140
|
+
- Values resolve from `process.env` first, then the `envFile`, then `:-default`.
|
|
141
|
+
- `process.env` overrides the same key in the `envFile`.
|
|
142
|
+
- A `${VAR}` without a default that cannot be resolved fails the proxy at startup
|
|
143
|
+
with an error naming the variable.
|
|
144
|
+
- `envFile` is resolved relative to the config file's directory; `--env-file <path>`
|
|
145
|
+
on the command line overrides it. There is no automatic `.env` discovery.
|
|
146
|
+
- The `envFile` is user-local and must never be committed.
|
|
147
|
+
|
|
148
|
+
### Example 4: SSE Transport
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
transport: sse
|
|
152
|
+
ssePort: 3002
|
|
153
|
+
sseHost: "127.0.0.1"
|
|
154
|
+
btpDestination: "btp"
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Example 5: Custom Error Handling
|
|
158
|
+
|
|
159
|
+
```yaml
|
|
160
|
+
transport: http
|
|
161
|
+
httpPort: 3001
|
|
162
|
+
btpDestination: "btp"
|
|
163
|
+
maxRetries: 5
|
|
164
|
+
retryDelay: 2000
|
|
165
|
+
requestTimeout: 120000
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Configuration Fields Reference
|
|
169
|
+
|
|
170
|
+
### Transport Configuration
|
|
171
|
+
|
|
172
|
+
| Field | Type | Default | Description |
|
|
173
|
+
|-------|------|---------|-------------|
|
|
174
|
+
| `transport` | `string` | `"streamable-http"` | Transport type: `stdio`, `http`, `streamable-http`, `sse` |
|
|
175
|
+
| `httpPort` | `number` | `3001` | HTTP server port |
|
|
176
|
+
| `ssePort` | `number` | `3002` | SSE server port |
|
|
177
|
+
| `httpHost` | `string` | `"127.0.0.1"` | HTTP server host (loopback by default; set `0.0.0.0` to expose) |
|
|
178
|
+
| `sseHost` | `string` | `"127.0.0.1"` | SSE server host (loopback by default; set `0.0.0.0` to expose) |
|
|
179
|
+
|
|
180
|
+
### Destination & Headers
|
|
181
|
+
|
|
182
|
+
| Field | Type | Default | Description |
|
|
183
|
+
|-------|------|---------|-------------|
|
|
184
|
+
| `btpDestination` | `string` | `undefined` | BTP destination name (for Cloud authorization). Must match a service key file. |
|
|
185
|
+
| `targetUrl` | `string` | `undefined` | Override target URL (uses auth from `btpDestination` but forwards to this URL) |
|
|
186
|
+
| `defaultHeaders` | `map` | `undefined` | Headers injected into every forwarded request; client headers take precedence |
|
|
187
|
+
| `envFile` | `string` | `undefined` | Path to a `.env` file (resolved relative to the config file) supplying variables for `${VAR}` interpolation; overridden by `--env-file` |
|
|
188
|
+
|
|
189
|
+
### Authentication Browser
|
|
190
|
+
|
|
191
|
+
| Field | Type | Default | Description |
|
|
192
|
+
|-------|------|---------|-------------|
|
|
193
|
+
| `browser` | `string` | `"system"` | OAuth2 login browser: `system`, `headless`, `chrome`, `edge`, `firefox`, `none` |
|
|
194
|
+
| `browserAuthPort` | `number` | `3333` | Port for the local OAuth2 callback server. Bound only for the duration of an interactive login, then released — see [How long the callback port is held](./CONFIGURATION.md#how-long-the-callback-port-is-held) |
|
|
195
|
+
|
|
196
|
+
### Session Storage
|
|
197
|
+
|
|
198
|
+
| Field | Type | Default | Description |
|
|
199
|
+
|-------|------|---------|-------------|
|
|
200
|
+
| `unsafe` | `boolean` | `false` | If `true`, persists tokens to disk. If `false`, uses in-memory storage (secure) |
|
|
201
|
+
|
|
202
|
+
### Error Handling
|
|
203
|
+
|
|
204
|
+
| Field | Type | Default | Description |
|
|
205
|
+
|-------|------|---------|-------------|
|
|
206
|
+
| `maxRetries` | `number` | `3` | Maximum number of retry attempts |
|
|
207
|
+
| `retryDelay` | `number` | `1000` | Delay between retries (milliseconds) |
|
|
208
|
+
| `requestTimeout` | `number` | `60000` | Request timeout (milliseconds) |
|
|
209
|
+
### Windows paths must not go in double quotes
|
|
210
|
+
|
|
211
|
+
In YAML, a double-quoted string is an **escape context**, and a Windows path is
|
|
212
|
+
full of backslashes. Measured with the parser this package uses:
|
|
213
|
+
|
|
214
|
+
| written as | result |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `envFile: "C:\Users\me\e19.env"` | **fails** — `expected hexadecimal character`, because `\U` starts a Unicode escape |
|
|
217
|
+
| `envFile: "C:\temp\e19.env"` | **silently wrong** — `\e` becomes the escape character `0x1B`, so the path points nowhere |
|
|
218
|
+
| `envFile: 'C:\Users\me\e19.env'` | correct |
|
|
219
|
+
| `envFile: C:\Users\me\e19.env` | correct |
|
|
220
|
+
| `envFile: "C:/Users/me/e19.env"` | correct |
|
|
221
|
+
|
|
222
|
+
The second row is the dangerous one: it does not fail, it resolves to a path that
|
|
223
|
+
does not exist. Forward slashes are the safest form — Node accepts them on
|
|
224
|
+
Windows, and they carry no meaning inside quotes.
|
|
225
|
+
|
|
226
|
+
| ~~`circuitBreakerThreshold`~~ | `number` | — | **No effect since 4.0.0.** Still accepted so existing files load; the circuit breaker guarded the buffered forward that release removed |
|
|
227
|
+
| ~~`circuitBreakerTimeout`~~ | `number` | — | **No effect since 4.0.0.** As above |
|
|
228
|
+
|
|
229
|
+
### Logging
|
|
230
|
+
|
|
231
|
+
| Field | Type | Default | Description |
|
|
232
|
+
|-------|------|---------|-------------|
|
|
233
|
+
| `logLevel` | `string` | `"info"` | Log level: `debug`, `info`, `warn`, `error` |
|
|
234
|
+
|
|
235
|
+
## Using YAML Config in VS Code Debugging
|
|
236
|
+
|
|
237
|
+
You can use YAML configuration files when debugging in VS Code. The `launch.json` includes a configuration for this:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"type": "node",
|
|
242
|
+
"request": "launch",
|
|
243
|
+
"name": "MCP Proxy (YAML Config)",
|
|
244
|
+
"program": "${workspaceFolder}/bin/mcp-abap-adt-proxy.js",
|
|
245
|
+
"args": [
|
|
246
|
+
"--config=mcp-proxy-config.yaml"
|
|
247
|
+
],
|
|
248
|
+
"console": "integratedTerminal",
|
|
249
|
+
"env": {
|
|
250
|
+
"NODE_ENV": "development",
|
|
251
|
+
"LOG_LEVEL": "debug"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Security Notes
|
|
257
|
+
|
|
258
|
+
- **Never commit** your `mcp-proxy-config.yaml` file to version control (it's already in `.gitignore`)
|
|
259
|
+
- Use `.mcp-proxy-config.yaml` (with leading dot) for hidden configuration files
|
|
260
|
+
- Service keys are stored separately in `~/.config/mcp-abap-adt/service-keys/` (Unix) or `%USERPROFILE%\Documents\mcp-abap-adt\service-keys` (Windows)
|
|
261
|
+
- Set `unsafe: false` (default) to use secure in-memory session storage
|
|
262
|
+
|
|
263
|
+
## Troubleshooting
|
|
264
|
+
|
|
265
|
+
### Configuration file not found
|
|
266
|
+
|
|
267
|
+
If you get an error that the configuration file is not found:
|
|
268
|
+
1. Check that the file exists at the specified path
|
|
269
|
+
2. Verify the file extension (`.yaml`, `.yml`, or `.json`)
|
|
270
|
+
3. Check file permissions
|
|
271
|
+
|
|
272
|
+
### Configuration values not applied
|
|
273
|
+
|
|
274
|
+
Remember that command-line parameters take precedence over configuration files. If a value isn't being applied:
|
|
275
|
+
1. Check if you're passing the same parameter via command line
|
|
276
|
+
2. Verify the YAML syntax is correct (use a YAML validator)
|
|
277
|
+
3. Check for typos in field names
|
|
278
|
+
|
|
279
|
+
### YAML parsing errors
|
|
280
|
+
|
|
281
|
+
If you get YAML parsing errors:
|
|
282
|
+
1. Verify the YAML syntax (indentation matters!)
|
|
283
|
+
2. Check for special characters that need quoting
|
|
284
|
+
3. Ensure all strings are properly quoted if they contain special characters
|
|
285
|
+
|
|
286
|
+
## See Also
|
|
287
|
+
|
|
288
|
+
- [Configuration Guide](./CONFIGURATION.md) - General configuration documentation
|
|
289
|
+
- [Usage Guide](./USAGE.md) - Command-line usage examples
|
|
290
|
+
- [Client Setup Guide](./CLIENT_SETUP.md) - Setting up clients like Cline
|