@mcp-abap-adt/proxy 1.6.3 → 2.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.
- package/CHANGELOG.md +65 -0
- package/dist/proxy/btpProxy.d.ts.map +1 -1
- package/dist/proxy/btpProxy.js +51 -15
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,71 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0] - 2026-08-01
|
|
11
|
+
|
|
12
|
+
### Breaking Changes
|
|
13
|
+
- **Pasting the authorization code into the proxy's terminal no longer works.** A headless login
|
|
14
|
+
(`--browser none`/`headless`) used to accept the code three ways; the terminal was one of them.
|
|
15
|
+
`auth-providers@2.0.0`'s callback strategy reads no stdin at all — deliberately, since under an
|
|
16
|
+
MCP stdio transport stdin carries the protocol itself, and reading from it there would corrupt
|
|
17
|
+
the stream. **If you relied on terminal paste**, switch to one of the two remaining paths: let
|
|
18
|
+
the automatic callback reach the proxy (browser on the same machine), or open
|
|
19
|
+
`http://<proxy-host>:<browser-auth-port>/` and use the paste form the callback server already
|
|
20
|
+
serves there — it covers the same "my browser is elsewhere" case without touching stdin. See
|
|
21
|
+
[Configuration Guide](./docs/CONFIGURATION.md#headless-login---browser-none).
|
|
22
|
+
- **Requires `@mcp-abap-adt/auth-providers` `^2.0.0`** (was `^1.2.0`). That release is what removes
|
|
23
|
+
the terminal-paste channel above; it also replaces the `browser`/`redirectPort` fields on
|
|
24
|
+
`AuthorizationCodeProviderConfig` with an `authorization` strategy the consumer supplies. The
|
|
25
|
+
proxy now builds one with `browserCallbackStrategy({ browser, port, timeoutMs })` at both places
|
|
26
|
+
it constructs the provider — an internal change with no configuration impact (see below).
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- **The no-destination placeholder broker's callback port collided with the proxy's own.** The
|
|
30
|
+
`AuthorizationCodeProvider` built for `BtpProxy.create()`'s default broker never had its own
|
|
31
|
+
port fallback; an unset `browserAuthPort` fell through to `auth-providers@1.2.0`'s internal
|
|
32
|
+
default of `3001` — the same port the proxy's own HTTP server listens on by default. Making the
|
|
33
|
+
migration to `auth-providers@2.0.0` explicit is what surfaced it. Both call sites now share the
|
|
34
|
+
documented `3333` default. This only affects logins with no destination configured, which use
|
|
35
|
+
placeholder credentials and could never complete a real login anyway.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- **`--browser-auth-port` keeps its meaning and its `3333` default.** Nothing changes for existing
|
|
39
|
+
configs or CLI invocations — the port still lands inside the strategy instead of a bare config
|
|
40
|
+
field.
|
|
41
|
+
- **The login timeout is now explicit and longer.** `browserCallbackStrategy` defaults to a
|
|
42
|
+
30-second `timeoutMs`, sized for an unattended caller; this proxy drives a browser login for a
|
|
43
|
+
person, so both call sites now pass 5 minutes instead, giving room to open a tab, sign in and
|
|
44
|
+
clear MFA before the callback server gives up.
|
|
45
|
+
|
|
46
|
+
## [1.6.4] - 2026-07-29
|
|
47
|
+
|
|
48
|
+
### Fixed
|
|
49
|
+
- **The two callback-port leaks that 1.6.3 deferred are now closed**, through
|
|
50
|
+
`@mcp-abap-adt/auth-providers@1.2.0`. 1.6.3 fixed the half that survived stopping the
|
|
51
|
+
proxy — the orphaned server — and recorded these as outstanding: a callback arriving
|
|
52
|
+
without a `code` parameter left the socket bound for the lifetime of the process, and a
|
|
53
|
+
failed token exchange released it about 300 ms after the login promise had already been
|
|
54
|
+
rejected. Both are gone: the port is released when the login ends by any means, and the
|
|
55
|
+
promise settles only once the socket is actually free.
|
|
56
|
+
- **An interactive login can no longer strand a port by being abandoned.** The OIDC and
|
|
57
|
+
SAML flows in the dependency had no timeout at all, so a user who closed the tab left the
|
|
58
|
+
port held until the process exited. Every flow now has one.
|
|
59
|
+
|
|
60
|
+
### Changed
|
|
61
|
+
- Requires `@mcp-abap-adt/auth-broker` `^1.0.8` (was `^1.0.7`) and
|
|
62
|
+
`@mcp-abap-adt/auth-providers` `^1.2.0` (was `^1.1.0`).
|
|
63
|
+
- **`engines.node` is now `>=18.2.0`** (was `>=18.0.0`), matching the floor those packages
|
|
64
|
+
require for `server.closeAllConnections()`.
|
|
65
|
+
|
|
66
|
+
### Notes
|
|
67
|
+
- No change in this package's own code. `src/__tests__/bin/callbackPortLifecycle.test.ts`
|
|
68
|
+
was written in 1.6.3 against behaviour rather than implementation, and passes unchanged
|
|
69
|
+
against the rewritten dependency — including the case that starts a second proxy on the
|
|
70
|
+
same configured auth port while the first is still running.
|
|
71
|
+
- Two proxies whose interactive logins overlap still cannot share one `browserAuthPort`.
|
|
72
|
+
That is inherent: the port is held for the duration of a login.
|
|
73
|
+
|
|
74
|
+
|
|
10
75
|
## [1.6.3] - 2026-07-27
|
|
11
76
|
|
|
12
77
|
### Fixed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"btpProxy.d.ts","sourceRoot":"","sources":["../../src/proxy/btpProxy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAgB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"btpProxy.d.ts","sourceRoot":"","sources":["../../src/proxy/btpProxy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAgB,MAAM,2BAA2B,CAAC;AAgBrE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA8DnE;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAU3C;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAGD,MAAM,MAAM,YAAY,GAAG,mBAAmB,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,UAAU,CACN;IACZ,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IACjD,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAU;gBAEZ,oBAAoB,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC;IAqF3E;;;OAGG;IACU,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB3D;;;;OAIG;YACW,wBAAwB;IAiGtC;;OAEG;YACW,uBAAuB;IAyFrC;;;;OAIG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,YAAY,GAAE,OAAe,GAC5B,OAAO,CAAC,MAAM,CAAC;IAiHlB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;;OAGG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA6BhC;;OAEG;YACW,gBAAgB;IAU9B;;OAEG;IACI,OAAO,IAAI,IAAI;IAStB;;;OAGG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAexD;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;;;;;;;;;;;;;;;OAgBG;YACW,iBAAiB;IAmT/B;;OAEG;IACG,YAAY,CAChB,eAAe,EAAE,YAAY,EAC7B,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAC7D,OAAO,CAAC,aAAa,CAAC;IAiLzB;;OAEG;WACiB,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;CAuC7E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAEnB"}
|
package/dist/proxy/btpProxy.js
CHANGED
|
@@ -19,6 +19,22 @@ const axios_1 = __importDefault(require("axios"));
|
|
|
19
19
|
const config_js_1 = require("../lib/config.js");
|
|
20
20
|
const logger_js_1 = require("../lib/logger.js");
|
|
21
21
|
const stores_js_1 = require("../lib/stores.js");
|
|
22
|
+
/**
|
|
23
|
+
* Default port for the local OAuth2 callback server, kept away from the
|
|
24
|
+
* proxy's own default HTTP port (3001). auth-providers@2.0.0's own default
|
|
25
|
+
* (61001) is deliberately not inherited here: this port is documented as
|
|
26
|
+
* `--browser-auth-port` and may be registered with the identity provider, so
|
|
27
|
+
* silently moving it would break every proxy already relying on 3333.
|
|
28
|
+
*/
|
|
29
|
+
const DEFAULT_BROWSER_AUTH_PORT = 3333;
|
|
30
|
+
/**
|
|
31
|
+
* auth-providers@2.0.0's `browserCallbackStrategy` defaults `timeoutMs` to 30
|
|
32
|
+
* seconds — sized for an unattended caller. Here the login is driven by a
|
|
33
|
+
* person: a browser tab has to open, and they may need to type credentials or
|
|
34
|
+
* complete MFA before the redirect lands. Five minutes gives them room to do
|
|
35
|
+
* that without the callback server tearing itself down mid-login.
|
|
36
|
+
*/
|
|
37
|
+
const INTERACTIVE_LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
22
38
|
/**
|
|
23
39
|
* Adapter to convert proxy Logger to ILogger interface expected by AuthBroker
|
|
24
40
|
*/
|
|
@@ -211,21 +227,28 @@ class BtpProxy {
|
|
|
211
227
|
}
|
|
212
228
|
// Always use AuthorizationCodeProvider (enforced)
|
|
213
229
|
// Map IAuthorizationConfig (uaaClientId) to ProviderConfig (clientId)
|
|
214
|
-
//
|
|
230
|
+
// How the login is conducted is now a strategy the provider config
|
|
231
|
+
// carries under `authorization`; the callback port lives inside it.
|
|
232
|
+
//
|
|
233
|
+
// uaaUrl/clientId/clientSecret fall back to '' rather than being omitted
|
|
234
|
+
// when authConfig is missing: AuthorizationCodeProviderConfig declares
|
|
235
|
+
// them required, and the provider's own constructor already treats an
|
|
236
|
+
// empty string the same as absent, throwing its "Missing required
|
|
237
|
+
// fields" ValidationError — which is the clear failure this was always
|
|
238
|
+
// meant to produce.
|
|
215
239
|
const providerConfig = {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
240
|
+
authorization: (0, auth_providers_1.browserCallbackStrategy)({
|
|
241
|
+
browser: this.config.browser,
|
|
242
|
+
port: this.config.browserAuthPort || DEFAULT_BROWSER_AUTH_PORT,
|
|
243
|
+
timeoutMs: INTERACTIVE_LOGIN_TIMEOUT_MS,
|
|
244
|
+
}),
|
|
245
|
+
// Pass a logger so the callback strategy can surface the "Open this
|
|
246
|
+
// URL" prompt in 'none'/'headless' mode. Without it, the callback
|
|
247
|
+
// server gets a null logger and silently drops the authorization URL.
|
|
221
248
|
logger: loggerAdapter,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
clientId: authConfig.uaaClientId,
|
|
226
|
-
clientSecret: authConfig.uaaClientSecret,
|
|
227
|
-
}
|
|
228
|
-
: {}),
|
|
249
|
+
uaaUrl: authConfig?.uaaUrl ?? '',
|
|
250
|
+
clientId: authConfig?.uaaClientId ?? '',
|
|
251
|
+
clientSecret: authConfig?.uaaClientSecret ?? '',
|
|
229
252
|
};
|
|
230
253
|
const tokenProvider = new auth_providers_1.AuthorizationCodeProvider(providerConfig);
|
|
231
254
|
broker = new auth_broker_1.AuthBroker({
|
|
@@ -928,8 +951,21 @@ class BtpProxy {
|
|
|
928
951
|
uaaUrl: 'https://placeholder.authentication.sap.hana.ondemand.com',
|
|
929
952
|
clientId: 'placeholder',
|
|
930
953
|
clientSecret: 'placeholder',
|
|
931
|
-
|
|
932
|
-
|
|
954
|
+
authorization: (0, auth_providers_1.browserCallbackStrategy)({
|
|
955
|
+
browser: loadedConfig.browser,
|
|
956
|
+
// This call site never had its own fallback: it passed
|
|
957
|
+
// `redirectPort` straight through and relied on
|
|
958
|
+
// auth-providers@1.2.0 defaulting an omitted value to 3001
|
|
959
|
+
// internally — which is this proxy's own default `httpPort`
|
|
960
|
+
// (src/lib/config.ts). An omitted `browserAuthPort` therefore
|
|
961
|
+
// told the callback server to bind the port the proxy already
|
|
962
|
+
// listens on, failing every such login with "Port 3001 is
|
|
963
|
+
// already in use". Both call sites now share the one documented
|
|
964
|
+
// default instead of leaving this one to an invisible, colliding
|
|
965
|
+
// number.
|
|
966
|
+
port: loadedConfig.browserAuthPort || DEFAULT_BROWSER_AUTH_PORT,
|
|
967
|
+
timeoutMs: INTERACTIVE_LOGIN_TIMEOUT_MS,
|
|
968
|
+
}),
|
|
933
969
|
logger: loggerAdapter,
|
|
934
970
|
}),
|
|
935
971
|
}, 'none', loggerAdapter);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/proxy",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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",
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"typescript": "^6.0.3"
|
|
63
63
|
},
|
|
64
64
|
"dependencies": {
|
|
65
|
-
"@mcp-abap-adt/auth-broker": "^1.0.
|
|
66
|
-
"@mcp-abap-adt/auth-providers": "^
|
|
65
|
+
"@mcp-abap-adt/auth-broker": "^1.0.8",
|
|
66
|
+
"@mcp-abap-adt/auth-providers": "^2.0.0",
|
|
67
67
|
"@mcp-abap-adt/auth-stores": "^1.0.4",
|
|
68
68
|
"@mcp-abap-adt/header-validator": "^0.1.8",
|
|
69
69
|
"@mcp-abap-adt/interfaces": "^7.0.0",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"zod": "^4.3.6"
|
|
76
76
|
},
|
|
77
77
|
"engines": {
|
|
78
|
-
"node": ">=18.
|
|
78
|
+
"node": ">=18.2.0",
|
|
79
79
|
"npm": ">=9.0.0"
|
|
80
80
|
},
|
|
81
81
|
"files": [
|