@mcp-abap-adt/proxy 1.6.1 → 1.6.3

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,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.6.3] - 2026-07-27
11
+
12
+ ### Fixed
13
+ - **Stopping the proxy left it running, holding its ports.** `bin/mcp-abap-adt-proxy.js` spawned the server as a child process and forwarded only `SIGINT`. Everything that stops a process with `SIGTERM` — `kill`, `pkill`, a service manager, an MCP client shutting the server down — killed the launcher while the server survived, re-parented to `init`/`systemd`, still holding both the HTTP port and the OAuth callback port. A later start then failed with `Port <n> is already in use`, naming the port from `browserAuthPort`.
14
+
15
+ The orphan was easy to miss: in `ps` it appears as `dist/index.js`, not `mcp-abap-adt-proxy`, and it is no longer attached to the terminal it was started from. Only `Ctrl+C` shut down cleanly.
16
+
17
+ The launcher no longer spawns anything — it loads the server in the same process, so signals reach the shutdown handler that was already there and already correct. It used the same Node executable, an unmodified environment, inherited stdio and the same arguments, so the child bought nothing.
18
+
19
+ - **Closing a terminal mid-login left the proxy running for another 30 seconds.** `SIGHUP` is now handled alongside `SIGINT` and `SIGTERM`. It previously did not terminate the proxy at all during a login: `@mcp-abap-adt/auth-providers` registers its own `SIGHUP` listener while the callback server is open, and any registered listener suppresses Node's default terminate. The process lingered — holding its ports — until the authentication timeout exited it with code 1.
20
+
21
+ ### Changed
22
+ - Updated dev/runtime dependencies to latest within their semver ranges (axios, zod, js-yaml, `@mcp-abap-adt/interfaces`, biome, jest toolchain, tsx, `@types/node`). Runtime `dependencies` ranges are unchanged, so consumer installs are unaffected.
23
+ - Bumped `@modelcontextprotocol/inspector` (dev) to `^0.22.0`.
24
+ - Removed unused `commander` dev dependency.
25
+
26
+ ### Notes
27
+ - The `browserAuthPort` collision that remains is by design: the callback port is held for the whole interactive login, so two proxies whose login windows overlap cannot share one. Give each config its own, or stagger the logins.
28
+ - Not addressed here, and tracked for `@mcp-abap-adt/auth-providers`: a callback that arrives without a `code` parameter leaves the callback socket open for the lifetime of the process, and a failed token exchange releases it about 300 ms after the login promise has already been rejected.
29
+
30
+ ## [1.6.2] - 2026-06-08
31
+
32
+ ### Fixed
33
+ - Bumped `@mcp-abap-adt/auth-broker` to `^1.0.7`, which moves `tsx` (and its transitive `esbuild`) out of runtime dependencies. Installing the proxy (including `npm i -g`) no longer pulls `esbuild`, so Windows/macOS package managers stop prompting about esbuild's `allow-scripts` / ignored build script during install. Runtime behavior is unchanged.
34
+
10
35
  ## [1.6.1] - 2026-06-04
11
36
 
12
37
  ### Fixed
package/README.md CHANGED
@@ -91,7 +91,7 @@ For detailed setup instructions for Cline and GitHub Copilot, see the **[Client
91
91
  - `--btp=<destination>` - Overrides `x-sap-destination` header (takes precedence)
92
92
  - `--url=<url>` - Overrides MCP server URL (required if service key lacks URL)
93
93
  - `--browser=<browser>` - Browser to use: `system` (default), `chrome`, `edge`, `firefox`, `headless`
94
- - `--browser-auth-port=<port>` - Port for OAuth2 callback (default: 3333)
94
+ - `--browser-auth-port=<port>` - Port for the OAuth2 callback (default: 3333). Bound only while you are logging in, then released — see [How long the callback port is held](./docs/CONFIGURATION.md#how-long-the-callback-port-is-held)
95
95
  - `--unsafe` - Enables file-based session storage (persists tokens to disk). By default, sessions are stored in-memory (secure, lost on restart)
96
96
 
97
97
  **Default Headers:**
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * MCP ABAP ADT Proxy Server Launcher
5
5
  *
6
- * Simple launcher that spawns the main server process.
6
+ * Parses --help/--version, then loads the main server in-process.
7
7
  *
8
8
  * Usage:
9
9
  * mcp-abap-adt-proxy [options]
@@ -13,7 +13,6 @@
13
13
 
14
14
  const path = require('path');
15
15
  const fs = require('fs');
16
- const { spawn } = require('child_process');
17
16
 
18
17
  // Parse command line arguments
19
18
  function parseArgs() {
@@ -158,68 +157,12 @@ function main() {
158
157
  return;
159
158
  }
160
159
 
161
- // Pass all arguments to server
162
- const serverArgs = process.argv.slice(2);
163
- const nodeExecPath = process.execPath;
164
- const resolvedServerPath = path.resolve(serverPath);
165
-
166
- // Verify server file exists
167
- if (!fs.existsSync(resolvedServerPath)) {
168
- process.stderr.write(`[MCP Proxy] ✗ Server file not found: ${resolvedServerPath}\n`);
169
- if (process.platform === 'win32') {
170
- setTimeout(() => process.exit(1), 30000);
171
- } else {
172
- process.exit(1);
173
- }
174
- return;
175
- }
176
-
177
- const serverEnv = {
178
- ...process.env,
179
- };
180
-
181
- // Debug logging for Windows
182
- if (process.platform === 'win32') {
183
- process.stderr.write(`[MCP Proxy] Spawning server: ${nodeExecPath} ${resolvedServerPath}\n`);
184
- process.stderr.write(`[MCP Proxy] CWD: ${process.cwd()}\n`);
185
- }
186
-
187
- // Spawn the server process
188
- const serverProcess = spawn(nodeExecPath, [resolvedServerPath, ...serverArgs], {
189
- stdio: ['inherit', 'inherit', 'inherit'],
190
- env: serverEnv,
191
- cwd: process.cwd(),
192
- shell: false,
193
- });
194
-
195
- // Handle server process exit
196
- serverProcess.on('close', (code) => {
197
- if (code !== 0 && code !== null) {
198
- process.stderr.write(`[MCP Proxy] Server exited with code: ${code}\n`);
199
- }
200
- process.exit(code || 0);
201
- });
202
-
203
- // Handle server process errors
204
- serverProcess.on('error', (error) => {
205
- process.stderr.write(`[MCP Proxy] ✗ Failed to start server: ${error.message}\n`);
206
- if (error.stack) {
207
- process.stderr.write(error.stack + '\n');
208
- }
209
- if (process.platform === 'win32') {
210
- setTimeout(() => process.exit(1), 30000);
211
- } else {
212
- process.exit(1);
213
- }
214
- });
215
-
216
- // Forward SIGINT (Ctrl+C) to server process
217
- process.on('SIGINT', () => {
218
- serverProcess.kill('SIGINT');
219
- setTimeout(() => {
220
- process.exit(0);
221
- }, 500);
222
- });
160
+ // The server is loaded in this process, not spawned as a child. A child
161
+ // would be orphaned by any signal the launcher does not forward — SIGTERM
162
+ // from `kill`/`pkill`, SIGHUP from a closing terminal, or an MCP client
163
+ // stopping the server — and would keep holding the HTTP and OAuth callback
164
+ // ports. In-process, signals reach the server's own handler directly.
165
+ require(serverPath);
223
166
  }
224
167
 
225
168
  // Run launcher
package/dist/index.js CHANGED
@@ -747,6 +747,9 @@ if (process.env.MCP_SKIP_AUTO_START !== 'true') {
747
747
  };
748
748
  process.on('SIGINT', onSignal);
749
749
  process.on('SIGTERM', onSignal);
750
+ // A closing terminal should release the OAuth callback port and the HTTP
751
+ // listener the same way an explicit stop does.
752
+ process.on('SIGHUP', onSignal);
750
753
  server.run().catch((error) => {
751
754
  logger_js_1.logger?.error('Fatal error while running MCP proxy server', {
752
755
  type: 'SERVER_FATAL_ERROR',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-abap-adt/proxy",
3
- "version": "1.6.1",
3
+ "version": "1.6.3",
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",
@@ -45,11 +45,10 @@
45
45
  "devDependencies": {
46
46
  "@biomejs/biome": "^2.4.12",
47
47
  "@jest/globals": "^30.2.0",
48
- "@modelcontextprotocol/inspector": "^0.21.2",
48
+ "@modelcontextprotocol/inspector": "^0.22.0",
49
49
  "@types/jest": "^30.0.0",
50
50
  "@types/js-yaml": "^4.0.9",
51
51
  "@types/node": "^25.2.3",
52
- "commander": "^14.0.3",
53
52
  "cors": "^2.8.6",
54
53
  "cross-env": "^10.1.0",
55
54
  "express": "^5.1.0",
@@ -63,7 +62,7 @@
63
62
  "typescript": "^6.0.3"
64
63
  },
65
64
  "dependencies": {
66
- "@mcp-abap-adt/auth-broker": "^1.0.6",
65
+ "@mcp-abap-adt/auth-broker": "^1.0.7",
67
66
  "@mcp-abap-adt/auth-providers": "^1.1.0",
68
67
  "@mcp-abap-adt/auth-stores": "^1.0.4",
69
68
  "@mcp-abap-adt/header-validator": "^0.1.8",