@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 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;AAYrE,OAAO,EAAc,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AA4CnE;;;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;IA0FtC;;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;CA0B7E;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAEnB"}
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"}
@@ -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
- // Default redirectPort to 3333 to avoid conflict with main proxy port (default 3001)
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
- browser: this.config.browser,
217
- redirectPort: this.config.browserAuthPort || 3333,
218
- // Pass a logger so browserAuth can surface the "Open this URL" prompt in
219
- // 'none'/'headless' mode. Without it, startBrowserAuth gets a null logger
220
- // and silently drops the authorization URL.
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
- ...(authConfig
223
- ? {
224
- uaaUrl: authConfig.uaaUrl,
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
- browser: loadedConfig.browser,
932
- redirectPort: loadedConfig.browserAuthPort,
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": "1.6.3",
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.7",
66
- "@mcp-abap-adt/auth-providers": "^1.1.0",
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.0.0",
78
+ "node": ">=18.2.0",
79
79
  "npm": ">=9.0.0"
80
80
  },
81
81
  "files": [