@mcp-abap-adt/proxy 1.6.4 → 4.0.0

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +217 -0
  2. package/LICENSE +669 -17
  3. package/README.md +79 -8
  4. package/bin/mcp-abap-adt-proxy-mcp.js +113 -0
  5. package/dist/index.d.ts +10 -4
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +54 -97
  8. package/dist/lib/stores.d.ts +23 -2
  9. package/dist/lib/stores.d.ts.map +1 -1
  10. package/dist/lib/stores.js +56 -1
  11. package/dist/mcp/cli.d.ts +2 -0
  12. package/dist/mcp/cli.d.ts.map +1 -0
  13. package/dist/mcp/cli.js +21 -0
  14. package/dist/mcp/configs.d.ts +33 -0
  15. package/dist/mcp/configs.d.ts.map +1 -0
  16. package/dist/mcp/configs.js +142 -0
  17. package/dist/mcp/ports.d.ts +15 -0
  18. package/dist/mcp/ports.d.ts.map +1 -0
  19. package/dist/mcp/ports.js +35 -0
  20. package/dist/mcp/registry.d.ts +57 -0
  21. package/dist/mcp/registry.d.ts.map +1 -0
  22. package/dist/mcp/registry.js +145 -0
  23. package/dist/mcp/server.d.ts +34 -0
  24. package/dist/mcp/server.d.ts.map +1 -0
  25. package/dist/mcp/server.js +79 -0
  26. package/dist/mcp/shutdown.d.ts +37 -0
  27. package/dist/mcp/shutdown.d.ts.map +1 -0
  28. package/dist/mcp/shutdown.js +82 -0
  29. package/dist/mcp/supervisor.d.ts +125 -0
  30. package/dist/mcp/supervisor.d.ts.map +1 -0
  31. package/dist/mcp/supervisor.js +330 -0
  32. package/dist/mcp/tools.d.ts +28 -0
  33. package/dist/mcp/tools.d.ts.map +1 -0
  34. package/dist/mcp/tools.js +152 -0
  35. package/dist/proxy/btpProxy.d.ts +24 -73
  36. package/dist/proxy/btpProxy.d.ts.map +1 -1
  37. package/dist/proxy/btpProxy.js +116 -631
  38. package/dist/proxy/credentials.d.ts +45 -0
  39. package/dist/proxy/credentials.d.ts.map +1 -0
  40. package/dist/proxy/credentials.js +41 -0
  41. package/dist/proxy/requestHandler.d.ts +38 -0
  42. package/dist/proxy/requestHandler.d.ts.map +1 -0
  43. package/dist/proxy/requestHandler.js +73 -0
  44. package/dist/proxy/reverseProxy.d.ts +11 -2
  45. package/dist/proxy/reverseProxy.d.ts.map +1 -1
  46. package/dist/proxy/reverseProxy.js +52 -9
  47. package/dist/router/headerAnalyzer.js +2 -2
  48. package/dist/router/requestInterceptor.js +9 -9
  49. package/docs/API.md +172 -0
  50. package/docs/ARCHITECTURE.md +322 -0
  51. package/docs/CLIENT_SETUP.md +413 -0
  52. package/docs/CONFIGURATION.md +258 -0
  53. package/docs/MIGRATION-4.0.md +125 -0
  54. package/docs/ROUTING_LOGIC.md +126 -0
  55. package/docs/TROUBLESHOOTING.md +488 -0
  56. package/docs/USAGE.md +422 -0
  57. package/docs/YAML_CONFIG.md +273 -0
  58. package/docs/mcp-proxy-config.example.yaml +62 -0
  59. package/package.json +17 -10
  60. package/dist/proxy/cloudLlmHubProxy.d.ts +0 -2
  61. package/dist/proxy/cloudLlmHubProxy.d.ts.map +0 -1
  62. package/dist/proxy/cloudLlmHubProxy.js +0 -3
@@ -0,0 +1,125 @@
1
+ # Migration to 4.0
2
+
3
+ Two things changed that a consumer can see, and one that only a programmatic
4
+ consumer can. Everything else in this release is internal.
5
+
6
+ If you run the proxy from a config file and point a client at it, **read §1 and
7
+ stop there** — that is very likely all that applies to you.
8
+
9
+ ## 1. Dependencies: the contracts moved out of the umbrella
10
+
11
+ `@mcp-abap-adt/interfaces` is gone from this package's dependencies. The
12
+ contracts now come from the packages they live in:
13
+
14
+ ```
15
+ @mcp-abap-adt/interfaces ^7.0.0 → removed
16
+ @mcp-abap-adt/interfaces-network (new) → ^2.0.0 every HTTP header constant
17
+ @mcp-abap-adt/interfaces-auth (new) → ^1.2.0 ITokenRefresher
18
+ @mcp-abap-adt/interfaces-auth-sap (new) → ^1.0.0 IAuthorizationConfig
19
+ @mcp-abap-adt/connection (new) → ^9.2.0 TokenAuthProvider
20
+ ```
21
+
22
+ The sibling packages moved with them — `auth-broker` to `^2.2.0` (a major),
23
+ `auth-providers` `^2.2.2`, `auth-stores` `^1.2.0`, `header-validator` `^0.3.0`,
24
+ `logger` `^0.4.0` — because each has left the umbrella too. Nothing in this
25
+ package's tree asks for `@mcp-abap-adt/interfaces` any more.
26
+
27
+ **What you do:** if you install this package and nothing else, nothing. If your
28
+ own code imported a contract type and happened to resolve it through this
29
+ package's tree, install the package that now declares it. The old name still
30
+ exists on npm and still re-exports everything, but every one of those exports is
31
+ marked `@deprecated`.
32
+
33
+ ## 2. An SSE response streams, and carries your headers
34
+
35
+ This only matters if you use `transport: sse`. The `streamable-http` and `stdio`
36
+ transports are unaffected.
37
+
38
+ The SSE transport used to rebuild each request by hand, carry it over axios,
39
+ buffer the whole answer and rewrap it as a JSON-RPC envelope. It now goes through
40
+ the same transparent pipe as every other transport. Three consequences:
41
+
42
+ **The response arrives as it is produced**, not all at once at the end. This is
43
+ the point of the change.
44
+
45
+ **Your headers reach the target.** The old path forwarded none of them and
46
+ imposed two of its own:
47
+
48
+ ```
49
+ Accept: application/json, application/x-ndjson, text/event-stream
50
+ Content-Type: application/json
51
+ ```
52
+
53
+ It no longer does. The proxy is transparent and answers for the `Authorization`
54
+ header only. If your target requires a particular `Accept`, put it in that
55
+ proxy's `defaultHeaders`, where it is your choice and visible in your config:
56
+
57
+ ```yaml
58
+ defaultHeaders:
59
+ accept: "application/json, text/event-stream"
60
+ ```
61
+
62
+ A header your client sends always wins over `defaultHeaders`.
63
+
64
+ **The upstream path is your client's path.** The old SSE path had three branches:
65
+ with `targetUrl` set it used base + your client's path; with a service-key URL
66
+ already containing `/mcp` it used that URL as-is and *discarded* your client's
67
+ path; otherwise it appended `/mcp/stream/http`. Now it is always base + your
68
+ client's path.
69
+
70
+ **What you do:** if your config sets `targetUrl`, nothing — that is the branch
71
+ the old code took and it behaved the same way. If it relies on the service key's
72
+ own `abap.url`, set `targetUrl` explicitly to the URL you actually want.
73
+
74
+ ## 3. `BtpProxy.getJwtToken()` is replaced, not renamed
75
+
76
+ Only for code that imports `BtpProxy` directly.
77
+
78
+ ```ts
79
+ // before
80
+ const token = await proxy.getJwtToken(destination);
81
+ forward(req, res, url, token); // composed `Bearer ${token}` itself
82
+
83
+ // after
84
+ const authorization = await proxy.getAuthorizationHeader(destination);
85
+ forward(req, res, url, authorization); // a complete header VALUE, or null
86
+ ```
87
+
88
+ `getAuthorizationHeader()` answers the whole header value — `Bearer <token>` — or
89
+ `null` where the credential is not a header at all, which a certificate is not.
90
+ Pass it through as it stands: composing `Bearer` around it sends
91
+ `Bearer Bearer <token>`, and turning `null` into `''` sends an empty
92
+ `Authorization`, which is a different claim from having none.
93
+
94
+ Gone with it: `proxyRequest()`, `buildProxyRequest()`, and the `ProxyRequest` /
95
+ `ProxyResponse` types. They described the envelope the axios path built; there is
96
+ no envelope any more.
97
+
98
+ ## 4. The circuit breaker is gone
99
+
100
+ It guarded the buffered forward. The forwarding path streams, and a breaker there
101
+ would mean buffering the response again — the thing being fixed. A target that
102
+ keeps failing now fails visibly on every request instead of being
103
+ short-circuited.
104
+
105
+ `circuitBreakerThreshold`, `circuitBreakerTimeout` and
106
+ `MCP_PROXY_CIRCUIT_BREAKER_*` are still read, so existing configuration loads
107
+ unchanged. They do nothing.
108
+
109
+ Retry is unaffected and still applies to getting a token: 5xx and network
110
+ failures are retried with exponential backoff. A missing service key is not
111
+ retried — it answers at once, naming the file to create.
112
+
113
+ ## What did not change
114
+
115
+ The routing rules, `x-sap-destination` / `--btp`, `x-target-url` /
116
+ `--target-url`, `defaultHeaders`, `${VAR}` interpolation, `envFile`, the service
117
+ key layout, the transports on offer, and every configuration key except the two
118
+ named above.
119
+
120
+ ## New, and entirely optional
121
+
122
+ A second command, `mcp-abap-adt-proxy-mcp`, speaks MCP over stdio and its tools
123
+ start and stop proxies from the configs in `~/.config/mcp-abap-adt/proxy/`.
124
+ Nothing about the existing command changes because it exists — see
125
+ [Usage](./USAGE.md#the-management-mode).
@@ -0,0 +1,126 @@
1
+ # Routing Logic Specification
2
+
3
+ ## Overview
4
+
5
+ The proxy routes requests to MCP servers (local or on BTP) and handles BTP/XSUAA authentication.
6
+
7
+ ## Key Principles
8
+
9
+ 1. **No .env files in proxy**: Proxy should NOT use `.env` files for connection configuration. Only destinations via auth-broker (service key files) are used.
10
+ 2. **Validation only for destination**: Proxy validates only the `x-sap-destination` header. Other headers are passed directly to MCP server.
11
+ 3. **Destination priority**: Destination can be specified via command-line parameter (`--btp`) or header (`x-sap-destination`). Parameter takes precedence.
12
+ 4. **Header passthrough**: All other headers (except `x-sap-destination`) are passed directly to MCP server without validation.
13
+
14
+ ## Routing Scenarios
15
+
16
+ ### Scenario 1: BTP MCP Server (`--btp`)
17
+
18
+ **Configuration:**
19
+ - `--btp=<btp-destination>` (or header `x-sap-destination`) - BTP destination for authentication
20
+
21
+ **Behavior:**
22
+ - MCP server URL: From BTP destination service key (`abap.url` field)
23
+ - **BTP Authentication**: Uses `btpAuthBroker` with `ClientCredentialsProvider` to get BTP Cloud token
24
+ - Token obtained from BTP destination service key (contains `uaa.url`, `uaa.clientid`, `uaa.clientsecret`)
25
+ - Injects/overwrites `Authorization: Bearer <token>` header
26
+
27
+ **Use Case:** Production/cloud deployment with MCP server on BTP
28
+
29
+ **Example:**
30
+ ```bash
31
+ mcp-abap-adt-proxy --btp=btp-cloud
32
+ ```
33
+
34
+ ### Scenario 2: BTP MCP Server with explicit target URL (`--btp` + `--target-url`)
35
+
36
+ **Configuration:**
37
+ - `--btp=<btp-destination>` (or header `x-sap-destination`) - BTP destination for authentication
38
+ - `--target-url=<url>` (or header `x-target-url`) - Override the target URL
39
+
40
+ **Behavior:**
41
+ - MCP server URL: From `--target-url` (overrides the `abap.url` from the service key)
42
+ - **BTP Authentication**: Auth token still comes from the `--btp` destination service key
43
+ - Injects/overwrites `Authorization: Bearer <token>` header
44
+
45
+ **Use Case:** Auth comes from one service key, but requests must go to a different URL
46
+ (e.g. direct OData testing or a non-standard MCP path)
47
+
48
+ **Example:**
49
+ ```bash
50
+ mcp-abap-adt-proxy --btp=btp-cloud \
51
+ --target-url=https://mcp-server.cfapps.eu10.hana.ondemand.com
52
+ ```
53
+
54
+ > **Note:** Direct unauthenticated routing via `--mcp-url` / `x-mcp-url` has been
55
+ > **removed**. A BTP destination (`--btp` or `x-sap-destination`) is required; without
56
+ > it the proxy cannot resolve a target or obtain a token.
57
+
58
+ ## Header Mapping
59
+
60
+ ### Validated Headers
61
+
62
+ | Header | Source | Description |
63
+ |--------|--------|-------------|
64
+ | `x-sap-destination` | Request header or `--btp` parameter | BTP destination name for authentication |
65
+
66
+ **Note:** This is the ONLY header that proxy validates. All other headers are passed directly to MCP server.
67
+
68
+ ### Headers Added by Proxy
69
+
70
+ | Source | Target Header | Description |
71
+ |--------|---------------|-------------|
72
+ | BTP destination token (via `btpAuthBroker` with `ClientCredentialsProvider`) | `Authorization: Bearer <token>` | For MCP server on BTP (when `x-sap-destination` or `--btp` is provided) |
73
+
74
+ ### Headers Passed Through
75
+
76
+ All headers from the original request (except `x-sap-destination`) are passed directly to MCP server without modification. This includes any custom headers the MCP server might need.
77
+
78
+ ## Current Implementation Analysis
79
+
80
+ ### What Works Correctly
81
+
82
+ 1. **BTP AuthBroker architecture**: `btpAuthBroker` with `ClientCredentialsProvider` for BTP destinations (service keys with `uaa` section)
83
+ 2. **BTP destination handling**: Correctly gets token from BTP destination using `btpAuthBroker` for MCP server authorization
84
+ 3. **Service key store**: `XsuaaServiceKeyStore` correctly reads service keys for BTP destinations
85
+ 4. **Command-line overrides**: `--btp`, `--target-url` work as expected
86
+ 5. **Header passthrough**: Original headers are preserved and forwarded to MCP server
87
+ 6. **Platform path resolution**: Correctly determines service key and session paths for Unix and Windows
88
+
89
+ ## Testing Scenarios
90
+
91
+ ### Test 1: BTP MCP with explicit target URL
92
+ ```bash
93
+ # Start proxy
94
+ mcp-abap-adt-proxy --btp=btp-cloud \
95
+ --target-url=https://mcp-server.cfapps.eu10.hana.ondemand.com
96
+
97
+ # Send request with headers
98
+ curl -X POST http://localhost:3001/mcp/stream/http \
99
+ -H "Content-Type: application/json" \
100
+ -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
101
+ ```
102
+
103
+ **Expected:**
104
+ - Request forwarded to the `--target-url` value with `Authorization: Bearer <btp-token>`
105
+
106
+ ### Test 2: BTP MCP with BTP Destination
107
+ ```bash
108
+ # Start proxy
109
+ mcp-abap-adt-proxy --btp=btp-cloud
110
+
111
+ # Send request
112
+ curl -X POST http://localhost:3001/mcp/stream/http \
113
+ -H "Content-Type: application/json" \
114
+ -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
115
+ ```
116
+
117
+ **Expected:**
118
+ - MCP server receives: `Authorization: Bearer <btp-token>` (from BTP destination)
119
+ - MCP server URL obtained from BTP destination service key
120
+
121
+ ## Summary
122
+
123
+ The proxy supports flexible routing:
124
+ - **BTP Authentication Mode**: Use `--btp` for BTP authentication, MCP URL from service key
125
+ - **Explicit URL Mode**: Use `--btp` + `--target-url` for BTP auth with an overridden target URL
126
+ - **No .env files**: Only use destinations via auth-broker, never .env files