@mcp-abap-adt/proxy 1.3.0 → 1.5.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 +20 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -10
- package/dist/proxy/btpProxy.d.ts.map +1 -1
- package/dist/proxy/btpProxy.js +10 -3
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.5.0] - 2026-06-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **Exit on incomplete authentication.** When authentication is requested but not completed — at startup (eager auth) or on a request that needs a token — the proxy now logs a categorised reason (timeout / invalid credentials / service key / network) and exits with code 1, so it can be restarted to retry (mirroring the one-shot `mcp-auth` command) instead of running in a permanently unauthenticated state. A downstream/forward error (after auth succeeds) is still returned to the client without exiting.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Bump `@mcp-abap-adt/auth-broker` `^1.0.5` → `^1.0.6`: the broker no longer starts a redundant second browser login after an interactive session-login failure, so the real cause (e.g. login timeout) is reported instead of a misleading `Port <n> is already in use`.
|
|
17
|
+
|
|
18
|
+
## [1.4.0] - 2026-06-02
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Manual paste login for `--browser none` / `headless`** (via `@mcp-abap-adt/auth-providers@1.1.0`). When the browser runs on a different machine than the proxy, login can be completed by opening the paste form at `http://<host>:<browser-auth-port>/` and pasting the `code` (or the whole redirected URL), or by pasting the code in the terminal — in addition to the existing automatic localhost callback.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- **`--browser none` now prints the authorization URL.** The per-destination `AuthorizationCodeProvider` was created without a logger, so the "Open this URL" prompt from `browserAuth` was silently dropped and login could never be completed in headless mode. The proxy now passes its logger to the provider; `auth-providers@1.1.0` additionally falls back to `stderr` when no logger is supplied.
|
|
25
|
+
- **Platform-correct service-key path in `--help` and errors.** The "service key not found" hint and `--help` hard-coded the Unix `~/.config/...` path, which is wrong on Windows (`%USERPROFILE%\Documents\mcp-abap-adt\service-keys`). Both now show the real resolved directory and mention the `AUTH_BROKER_PATH` override.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- Bump `@mcp-abap-adt/auth-providers` `^1.0.5` → `^1.1.0`.
|
|
29
|
+
|
|
10
30
|
## [1.3.0] - 2026-05-28
|
|
11
31
|
|
|
12
32
|
### Added
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare class McpAbapAdtProxyServer {
|
|
|
17
17
|
private config;
|
|
18
18
|
private httpServer?;
|
|
19
19
|
private btpProxy?;
|
|
20
|
+
private authExiting;
|
|
20
21
|
constructor(transportConfig?: TransportConfig, configPath?: string);
|
|
21
22
|
/**
|
|
22
23
|
* Setup MCP handlers
|
|
@@ -38,6 +39,13 @@ export declare class McpAbapAdtProxyServer {
|
|
|
38
39
|
* Start SSE server
|
|
39
40
|
*/
|
|
40
41
|
private startSseServer;
|
|
42
|
+
/**
|
|
43
|
+
* Authentication was requested but could not be completed. Report the reason
|
|
44
|
+
* clearly, release resources, and exit(1) so the proxy is restarted (and the
|
|
45
|
+
* user gets a fresh login prompt) instead of running unauthenticated. Mirrors
|
|
46
|
+
* the one-shot `mcp-auth` command, which exits on a failed/incomplete login.
|
|
47
|
+
*/
|
|
48
|
+
private fatalAuthFailure;
|
|
41
49
|
/**
|
|
42
50
|
* Shutdown server
|
|
43
51
|
*/
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAwBH,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAgElC;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,WAAW,CAAS;gBAEhB,eAAe,CAAC,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM;IAoDlE;;OAEG;IACH,OAAO,CAAC,aAAa;IAMrB;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IA2E1B;;OAEG;YACW,eAAe;IAgG7B;;OAEG;YACW,kBAAkB;IAgEhC;;OAEG;YACW,cAAc;IA6T5B;;;;;OAKG;YACW,gBAAgB;IAiC9B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAoBhC;AAGD,eAAe,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
|
18
18
|
const reverseProxy_js_1 = require("./proxy/reverseProxy.js");
|
|
19
19
|
const config_js_1 = require("./lib/config.js");
|
|
20
20
|
const logger_js_1 = require("./lib/logger.js");
|
|
21
|
+
const stores_js_1 = require("./lib/stores.js");
|
|
21
22
|
const transportConfig_js_1 = require("./lib/transportConfig.js");
|
|
22
23
|
const btpProxy_js_1 = require("./proxy/btpProxy.js");
|
|
23
24
|
const headerAnalyzer_js_1 = require("./router/headerAnalyzer.js");
|
|
@@ -31,6 +32,38 @@ function getBodyId(body) {
|
|
|
31
32
|
}
|
|
32
33
|
return null;
|
|
33
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Classify an authentication failure into a human-readable reason so the proxy
|
|
37
|
+
* can report *why* it is exiting (timeout vs bad credentials vs network ...).
|
|
38
|
+
*/
|
|
39
|
+
function classifyAuthFailure(error) {
|
|
40
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
41
|
+
if (/timeout/i.test(msg)) {
|
|
42
|
+
return {
|
|
43
|
+
category: 'timeout',
|
|
44
|
+
reason: 'the login URL was not completed in time',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (/service key|missing required fields/i.test(msg)) {
|
|
48
|
+
return {
|
|
49
|
+
category: 'service-key',
|
|
50
|
+
reason: 'service key missing or incomplete',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (/invalid_client|unauthorized|\b401\b|invalid credentials/i.test(msg)) {
|
|
54
|
+
return {
|
|
55
|
+
category: 'credentials',
|
|
56
|
+
reason: 'invalid credentials — UAA rejected the client',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (/ENOTFOUND|ECONNREFUSED|ETIMEDOUT|network|ENETUNREACH/i.test(msg)) {
|
|
60
|
+
return {
|
|
61
|
+
category: 'network',
|
|
62
|
+
reason: 'network error reaching the authentication server',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { category: 'other', reason: msg };
|
|
66
|
+
}
|
|
34
67
|
/**
|
|
35
68
|
* MCP ABAP ADT Proxy Server
|
|
36
69
|
*/
|
|
@@ -40,6 +73,7 @@ class McpAbapAdtProxyServer {
|
|
|
40
73
|
config;
|
|
41
74
|
httpServer;
|
|
42
75
|
btpProxy;
|
|
76
|
+
authExiting = false;
|
|
43
77
|
constructor(transportConfig, configPath) {
|
|
44
78
|
// Load config first to extract transport overrides from YAML/JSON file
|
|
45
79
|
const resolvedConfigPath = configPath || (0, config_js_1.getConfigPath)();
|
|
@@ -125,20 +159,24 @@ Authorization source: BTP destination "${this.config.btpDestination}"`;
|
|
|
125
159
|
});
|
|
126
160
|
return;
|
|
127
161
|
}
|
|
128
|
-
// Eager initialization of BTP authentication
|
|
162
|
+
// Eager initialization of BTP authentication. Kept in the background so the
|
|
163
|
+
// server starts listening immediately (and, for --browser none, the auth URL
|
|
164
|
+
// is printed right away). If auth is requested but never completed, exit(1)
|
|
165
|
+
// so the proxy is restarted and the user gets a fresh login prompt.
|
|
129
166
|
if (this.config.btpDestination) {
|
|
167
|
+
const dest = this.config.btpDestination;
|
|
130
168
|
try {
|
|
131
169
|
if (!this.btpProxy) {
|
|
132
170
|
this.btpProxy = await (0, btpProxy_js_1.createBtpProxy)(this.config);
|
|
133
171
|
}
|
|
134
|
-
// Trigger initialization (background) - this will open the browser
|
|
135
|
-
this.btpProxy.initialize(this.config.btpDestination);
|
|
136
172
|
}
|
|
137
173
|
catch (error) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
});
|
|
174
|
+
await this.fatalAuthFailure(error, dest, 'startup');
|
|
175
|
+
return;
|
|
141
176
|
}
|
|
177
|
+
this.btpProxy
|
|
178
|
+
.initialize(dest)
|
|
179
|
+
.catch((error) => this.fatalAuthFailure(error, dest, 'startup'));
|
|
142
180
|
}
|
|
143
181
|
if (this.transportConfig.type === 'streamable-http') {
|
|
144
182
|
await this.startHttpServer();
|
|
@@ -246,9 +284,28 @@ Authorization source: ${authSourceObj}`;
|
|
|
246
284
|
if (!this.btpProxy) {
|
|
247
285
|
this.btpProxy = await (0, btpProxy_js_1.createBtpProxy)(this.config);
|
|
248
286
|
}
|
|
287
|
+
// Authentication is separated from forwarding: an auth failure is fatal
|
|
288
|
+
// (the proxy exits so it can be restarted), while a downstream/forward error
|
|
289
|
+
// is returned to the client without killing the proxy.
|
|
290
|
+
let jwtToken;
|
|
249
291
|
try {
|
|
250
292
|
// Get JWT token (cached, auto-refresh)
|
|
251
|
-
|
|
293
|
+
jwtToken = await this.btpProxy.getJwtToken(destination);
|
|
294
|
+
}
|
|
295
|
+
catch (authError) {
|
|
296
|
+
logger_js_1.logger?.error('Proxy request failed: authentication error', {
|
|
297
|
+
type: 'PROXY_REQUEST_AUTH_ERROR',
|
|
298
|
+
destination,
|
|
299
|
+
error: authError instanceof Error ? authError.message : String(authError),
|
|
300
|
+
});
|
|
301
|
+
if (!res.headersSent) {
|
|
302
|
+
res.writeHead(502, { 'Content-Type': 'application/json' });
|
|
303
|
+
res.end(JSON.stringify({ error: 'Authentication failed' }));
|
|
304
|
+
}
|
|
305
|
+
await this.fatalAuthFailure(authError, destination, 'request');
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
try {
|
|
252
309
|
// Get target URL
|
|
253
310
|
const targetUrl = intercepted.routingDecision.targetUrl ||
|
|
254
311
|
(await this.btpProxy.getTargetUrl(destination));
|
|
@@ -540,6 +597,37 @@ Authorization source: ${authSourceObj}`;
|
|
|
540
597
|
});
|
|
541
598
|
});
|
|
542
599
|
}
|
|
600
|
+
/**
|
|
601
|
+
* Authentication was requested but could not be completed. Report the reason
|
|
602
|
+
* clearly, release resources, and exit(1) so the proxy is restarted (and the
|
|
603
|
+
* user gets a fresh login prompt) instead of running unauthenticated. Mirrors
|
|
604
|
+
* the one-shot `mcp-auth` command, which exits on a failed/incomplete login.
|
|
605
|
+
*/
|
|
606
|
+
async fatalAuthFailure(error, destination, phase) {
|
|
607
|
+
if (this.authExiting)
|
|
608
|
+
return;
|
|
609
|
+
this.authExiting = true;
|
|
610
|
+
const { category, reason } = classifyAuthFailure(error);
|
|
611
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
612
|
+
logger_js_1.logger?.error('Authentication not completed — exiting', {
|
|
613
|
+
type: 'AUTH_FATAL_EXIT',
|
|
614
|
+
destination,
|
|
615
|
+
phase,
|
|
616
|
+
category,
|
|
617
|
+
reason,
|
|
618
|
+
error: detail,
|
|
619
|
+
});
|
|
620
|
+
console.error(`[MCP Proxy] ✗ Authentication failed for destination "${destination}" (${phase}): ${reason}.\n` +
|
|
621
|
+
`[MCP Proxy] ${detail}\n` +
|
|
622
|
+
`[MCP Proxy] Exiting (code 1) so the proxy can be restarted to retry authentication.`);
|
|
623
|
+
try {
|
|
624
|
+
await this.shutdown();
|
|
625
|
+
}
|
|
626
|
+
catch {
|
|
627
|
+
// best-effort cleanup; exit regardless
|
|
628
|
+
}
|
|
629
|
+
process.exit(1);
|
|
630
|
+
}
|
|
543
631
|
/**
|
|
544
632
|
* Shutdown server
|
|
545
633
|
*/
|
|
@@ -571,6 +659,9 @@ exports.default = McpAbapAdtProxyServer;
|
|
|
571
659
|
* Print CLI usage and exit.
|
|
572
660
|
*/
|
|
573
661
|
function printHelp() {
|
|
662
|
+
// Show the real, platform-specific directory where service keys are read from
|
|
663
|
+
// (Windows: %USERPROFILE%\Documents\mcp-abap-adt\service-keys; Unix: ~/.config/...)
|
|
664
|
+
const serviceKeyDir = (0, stores_js_1.getPlatformPaths)('service-keys')[0];
|
|
574
665
|
const help = `Usage: mcp-abap-adt-proxy [options]
|
|
575
666
|
|
|
576
667
|
Authorization proxy for MCP clients (Cline, Claude Code, etc.) that cannot
|
|
@@ -582,7 +673,8 @@ CONFIGURATION
|
|
|
582
673
|
|
|
583
674
|
AUTHENTICATION (BTP / XSUAA)
|
|
584
675
|
--btp <destination> BTP destination name. Service key is read from
|
|
585
|
-
|
|
676
|
+
${serviceKeyDir}${require('node:path').sep}<dest>.json
|
|
677
|
+
(override the base dir with AUTH_BROKER_PATH)
|
|
586
678
|
--target-url <url> Override target service URL (default: from service key)
|
|
587
679
|
--url <url> Alias for --target-url
|
|
588
680
|
--unsafe Persist session/tokens to disk (default: in-memory)
|
|
@@ -595,12 +687,18 @@ BROWSER AUTHORIZATION
|
|
|
595
687
|
chrome - Google Chrome
|
|
596
688
|
edge - Microsoft Edge
|
|
597
689
|
firefox - Firefox
|
|
598
|
-
none - Print URL to console
|
|
599
|
-
callback
|
|
690
|
+
none - Print URL to console; complete login
|
|
691
|
+
via callback OR by pasting the code
|
|
692
|
+
(for SSH/headless/remote sessions)
|
|
600
693
|
headless - Alias for 'none'
|
|
601
694
|
--browser-auth-port <port> Local OAuth callback port. Must match the
|
|
602
695
|
redirect_uri registered on XSUAA (default: 3333).
|
|
603
696
|
|
|
697
|
+
Run without auto-opening a browser (prints the URL, then completes via the
|
|
698
|
+
localhost callback, the paste form at http://<host>:<port>/, or by pasting
|
|
699
|
+
the code in the terminal):
|
|
700
|
+
mcp-abap-adt-proxy --btp <dest> --browser none --browser-auth-port 3333
|
|
701
|
+
|
|
604
702
|
TRANSPORT
|
|
605
703
|
--transport <type> stdio | streamable-http | http | sse
|
|
606
704
|
(auto-detected from stdin TTY if not set)
|
|
@@ -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;
|
|
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"}
|
package/dist/proxy/btpProxy.js
CHANGED
|
@@ -155,8 +155,9 @@ class BtpProxy {
|
|
|
155
155
|
destination,
|
|
156
156
|
error: error instanceof Error ? error.message : String(error),
|
|
157
157
|
});
|
|
158
|
-
//
|
|
159
|
-
//
|
|
158
|
+
// Re-throw so the server can decide to exit (auth requested but not
|
|
159
|
+
// completed) instead of running in a permanently unauthenticated state.
|
|
160
|
+
throw error;
|
|
160
161
|
}
|
|
161
162
|
}
|
|
162
163
|
/**
|
|
@@ -199,9 +200,10 @@ class BtpProxy {
|
|
|
199
200
|
});
|
|
200
201
|
}
|
|
201
202
|
if (!authConfig) {
|
|
203
|
+
const serviceKeyDir = (0, stores_js_1.getPlatformPaths)('service-keys')[0];
|
|
202
204
|
logger_js_1.logger?.error('Service key not found for destination', {
|
|
203
205
|
destination,
|
|
204
|
-
hint:
|
|
206
|
+
hint: `Ensure service key file "${destination}.json" exists in ${serviceKeyDir} (override the base dir with AUTH_BROKER_PATH)`,
|
|
205
207
|
});
|
|
206
208
|
// We cannot proceed without config, but we'll let it fail with a clear message
|
|
207
209
|
// Or we could throw here.
|
|
@@ -213,6 +215,10 @@ class BtpProxy {
|
|
|
213
215
|
const providerConfig = {
|
|
214
216
|
browser: this.config.browser,
|
|
215
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.
|
|
221
|
+
logger: loggerAdapter,
|
|
216
222
|
...(authConfig
|
|
217
223
|
? {
|
|
218
224
|
uaaUrl: authConfig.uaaUrl,
|
|
@@ -924,6 +930,7 @@ class BtpProxy {
|
|
|
924
930
|
clientSecret: 'placeholder',
|
|
925
931
|
browser: loadedConfig.browser,
|
|
926
932
|
redirectPort: loadedConfig.browserAuthPort,
|
|
933
|
+
logger: loggerAdapter,
|
|
927
934
|
}),
|
|
928
935
|
}, 'none', loggerAdapter);
|
|
929
936
|
return new BtpProxy(defaultBtpAuthBroker, loadedConfig);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/proxy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.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",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"typescript": "^6.0.3"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@mcp-abap-adt/auth-broker": "^1.0.
|
|
67
|
-
"@mcp-abap-adt/auth-providers": "^1.0
|
|
66
|
+
"@mcp-abap-adt/auth-broker": "^1.0.6",
|
|
67
|
+
"@mcp-abap-adt/auth-providers": "^1.1.0",
|
|
68
68
|
"@mcp-abap-adt/auth-stores": "^1.0.4",
|
|
69
69
|
"@mcp-abap-adt/header-validator": "^0.1.8",
|
|
70
70
|
"@mcp-abap-adt/interfaces": "^7.0.0",
|