@agimon-ai/mcp-proxy 0.10.0 → 0.10.1
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/dist/cli.cjs +8 -3
- package/dist/cli.mjs +8 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +1 -1
- package/dist/{src-9L_ccN5I.mjs → src-C48MCBti.mjs} +46 -31
- package/dist/{src-DIQjnEBk.cjs → src-CRhtaDaz.cjs} +46 -31
- package/package.json +3 -3
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_src = require("./src-
|
|
2
|
+
const require_src = require("./src-CRhtaDaz.cjs");
|
|
3
3
|
let node_fs = require("node:fs");
|
|
4
4
|
let node_fs_promises = require("node:fs/promises");
|
|
5
5
|
let js_yaml = require("js-yaml");
|
|
@@ -7,11 +7,11 @@ js_yaml = require_src.__toESM(js_yaml);
|
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
let node_path = require("node:path");
|
|
9
9
|
node_path = require_src.__toESM(node_path);
|
|
10
|
+
let _agimon_ai_foundation_process_registry = require("@agimon-ai/foundation-process-registry");
|
|
10
11
|
let node_child_process = require("node:child_process");
|
|
11
12
|
let liquidjs = require("liquidjs");
|
|
12
13
|
let commander = require("commander");
|
|
13
14
|
let node_url = require("node:url");
|
|
14
|
-
let _agimon_ai_foundation_process_registry = require("@agimon-ai/foundation-process-registry");
|
|
15
15
|
let _agimon_ai_foundation_port_registry = require("@agimon-ai/foundation-port-registry");
|
|
16
16
|
//#region src/commands/prestart-http.ts
|
|
17
17
|
/**
|
|
@@ -1156,9 +1156,14 @@ async function createAndStartHttpRuntime(serverOptions, config, resolvedConfigPa
|
|
|
1156
1156
|
console.error(`Runtime state: http://${runtimeRecord.host}:${runtimeRecord.port} (${runtimeRecord.serverId})`);
|
|
1157
1157
|
}
|
|
1158
1158
|
async function startStdioTransport(serverOptions) {
|
|
1159
|
+
let server;
|
|
1159
1160
|
try {
|
|
1160
|
-
|
|
1161
|
+
server = await require_src.createServer(serverOptions);
|
|
1162
|
+
await startServer(new require_src.StdioTransportHandler(server, createStdioSafeLogger()), async () => {
|
|
1163
|
+
await server?.dispose?.();
|
|
1164
|
+
});
|
|
1161
1165
|
} catch (error) {
|
|
1166
|
+
await server?.dispose?.();
|
|
1162
1167
|
throw new Error(`Failed to start stdio transport: ${toErrorMessage$3(error)}`);
|
|
1163
1168
|
}
|
|
1164
1169
|
}
|
package/dist/cli.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as DefinitionsCacheService, D as version, T as findConfigFile, b as RuntimeStateService, d as StdioHttpTransportHandler, f as StdioTransportHandler, m as HttpTransportHandler, n as createServer, o as createProxyIoCContainer, p as SseTransportHandler, r as createSessionServer, t as TRANSPORT_MODE, u as initializeSharedServices, v as StopServerService, w as generateServerId } from "./src-
|
|
2
|
+
import { C as DefinitionsCacheService, D as version, T as findConfigFile, b as RuntimeStateService, d as StdioHttpTransportHandler, f as StdioTransportHandler, m as HttpTransportHandler, n as createServer, o as createProxyIoCContainer, p as SseTransportHandler, r as createSessionServer, t as TRANSPORT_MODE, u as initializeSharedServices, v as StopServerService, w as generateServerId } from "./src-C48MCBti.mjs";
|
|
3
3
|
import { constants, existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { access, writeFile } from "node:fs/promises";
|
|
5
5
|
import yaml from "js-yaml";
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import path, { dirname, join, resolve } from "node:path";
|
|
8
|
+
import { ProcessRegistryService, createProcessLease, resolveSiblingRegistryPath } from "@agimon-ai/foundation-process-registry";
|
|
8
9
|
import { spawn } from "node:child_process";
|
|
9
10
|
import { Liquid } from "liquidjs";
|
|
10
11
|
import { Command } from "commander";
|
|
11
12
|
import { fileURLToPath } from "node:url";
|
|
12
|
-
import { ProcessRegistryService, createProcessLease, resolveSiblingRegistryPath } from "@agimon-ai/foundation-process-registry";
|
|
13
13
|
import { DEFAULT_PORT_RANGE, PortRegistryService } from "@agimon-ai/foundation-port-registry";
|
|
14
14
|
//#region src/commands/prestart-http.ts
|
|
15
15
|
/**
|
|
@@ -1154,9 +1154,14 @@ async function createAndStartHttpRuntime(serverOptions, config, resolvedConfigPa
|
|
|
1154
1154
|
console.error(`Runtime state: http://${runtimeRecord.host}:${runtimeRecord.port} (${runtimeRecord.serverId})`);
|
|
1155
1155
|
}
|
|
1156
1156
|
async function startStdioTransport(serverOptions) {
|
|
1157
|
+
let server;
|
|
1157
1158
|
try {
|
|
1158
|
-
|
|
1159
|
+
server = await createServer(serverOptions);
|
|
1160
|
+
await startServer(new StdioTransportHandler(server, createStdioSafeLogger()), async () => {
|
|
1161
|
+
await server?.dispose?.();
|
|
1162
|
+
});
|
|
1159
1163
|
} catch (error) {
|
|
1164
|
+
await server?.dispose?.();
|
|
1160
1165
|
throw new Error(`Failed to start stdio transport: ${toErrorMessage$3(error)}`);
|
|
1161
1166
|
}
|
|
1162
1167
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_src = require("./src-
|
|
2
|
+
const require_src = require("./src-CRhtaDaz.cjs");
|
|
3
3
|
exports.ConfigFetcherService = require_src.ConfigFetcherService;
|
|
4
4
|
exports.DefinitionsCacheService = require_src.DefinitionsCacheService;
|
|
5
5
|
exports.DescribeToolsTool = require_src.DescribeToolsTool;
|
package/dist/index.d.cts
CHANGED
|
@@ -525,12 +525,12 @@ declare class McpClientManagerService {
|
|
|
525
525
|
private serverConfigs;
|
|
526
526
|
private connectionPromises;
|
|
527
527
|
private logger;
|
|
528
|
-
|
|
528
|
+
private readonly repositoryPath;
|
|
529
|
+
constructor(logger?: LoggerLike, repositoryPath?: string);
|
|
529
530
|
/**
|
|
530
531
|
* Kill all stdio MCP server child processes.
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
* Awaiting the returned promise ensures force-kill timers complete before process.exit().
|
|
532
|
+
* Delegates to disconnectAll() so each client closes its child process and
|
|
533
|
+
* releases the corresponding process-registry lease before shutdown exits.
|
|
534
534
|
*/
|
|
535
535
|
cleanupChildProcesses(): Promise<void>;
|
|
536
536
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -525,12 +525,12 @@ declare class McpClientManagerService {
|
|
|
525
525
|
private serverConfigs;
|
|
526
526
|
private connectionPromises;
|
|
527
527
|
private logger;
|
|
528
|
-
|
|
528
|
+
private readonly repositoryPath;
|
|
529
|
+
constructor(logger?: LoggerLike, repositoryPath?: string);
|
|
529
530
|
/**
|
|
530
531
|
* Kill all stdio MCP server child processes.
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
* Awaiting the returned promise ensures force-kill timers complete before process.exit().
|
|
532
|
+
* Delegates to disconnectAll() so each client closes its child process and
|
|
533
|
+
* releases the corresponding process-registry lease before shutdown exits.
|
|
534
534
|
*/
|
|
535
535
|
cleanupChildProcesses(): Promise<void>;
|
|
536
536
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as DefinitionsCacheService, E as ConfigFetcherService, S as createProxyLogger, T as findConfigFile, _ as DescribeToolsTool, a as createProxyContainer, b as RuntimeStateService, c as createStdioHttpTransportHandler, d as StdioHttpTransportHandler, f as StdioTransportHandler, g as SearchListToolsTool, h as UseToolTool, i as createHttpTransportHandler, l as createStdioTransportHandler, m as HttpTransportHandler, n as createServer, p as SseTransportHandler, r as createSessionServer, s as createSseTransportHandler, t as TRANSPORT_MODE, u as initializeSharedServices, v as StopServerService, w as generateServerId, x as McpClientManagerService, y as SkillService } from "./src-
|
|
1
|
+
import { C as DefinitionsCacheService, E as ConfigFetcherService, S as createProxyLogger, T as findConfigFile, _ as DescribeToolsTool, a as createProxyContainer, b as RuntimeStateService, c as createStdioHttpTransportHandler, d as StdioHttpTransportHandler, f as StdioTransportHandler, g as SearchListToolsTool, h as UseToolTool, i as createHttpTransportHandler, l as createStdioTransportHandler, m as HttpTransportHandler, n as createServer, p as SseTransportHandler, r as createSessionServer, s as createSseTransportHandler, t as TRANSPORT_MODE, u as initializeSharedServices, v as StopServerService, w as generateServerId, x as McpClientManagerService, y as SkillService } from "./src-C48MCBti.mjs";
|
|
2
2
|
export { ConfigFetcherService, DefinitionsCacheService, DescribeToolsTool, HttpTransportHandler, McpClientManagerService, RuntimeStateService, SearchListToolsTool, SkillService, SseTransportHandler, StdioHttpTransportHandler, StdioTransportHandler, StopServerService, TRANSPORT_MODE, UseToolTool, createHttpTransportHandler, createProxyContainer, createProxyLogger, createServer, createSessionServer, createSseTransportHandler, createStdioHttpTransportHandler, createStdioTransportHandler, findConfigFile, generateServerId, initializeSharedServices };
|
|
@@ -10,6 +10,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
10
10
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
11
11
|
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
12
12
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
13
|
+
import { createProcessLease } from "@agimon-ai/foundation-process-registry";
|
|
13
14
|
import { spawn } from "node:child_process";
|
|
14
15
|
import { Liquid } from "liquidjs";
|
|
15
16
|
import { coerceArgs, formatZodError, jsonSchemaToZod } from "@agimon-ai/foundation-validator";
|
|
@@ -24,7 +25,7 @@ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
|
24
25
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
25
26
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
26
27
|
//#region package.json
|
|
27
|
-
var version = "0.
|
|
28
|
+
var version = "0.10.0";
|
|
28
29
|
//#endregion
|
|
29
30
|
//#region src/utils/mcpConfigSchema.ts
|
|
30
31
|
/**
|
|
@@ -1515,6 +1516,7 @@ async function createProxyLogger(options = {}) {
|
|
|
1515
1516
|
//#region src/services/McpClientManagerService.ts
|
|
1516
1517
|
/** Default connection timeout in milliseconds (30 seconds) */
|
|
1517
1518
|
const DEFAULT_CONNECTION_TIMEOUT_MS = 3e4;
|
|
1519
|
+
const PROCESS_REGISTRY_SERVICE_TYPE = "tool";
|
|
1518
1520
|
/**
|
|
1519
1521
|
* Checks if an error is a session-related error from an HTTP backend
|
|
1520
1522
|
* (e.g., downstream server restarted and no longer recognizes the session ID).
|
|
@@ -1569,6 +1571,7 @@ var McpClient = class {
|
|
|
1569
1571
|
logger;
|
|
1570
1572
|
client;
|
|
1571
1573
|
childProcess;
|
|
1574
|
+
processLease;
|
|
1572
1575
|
connected = false;
|
|
1573
1576
|
reconnectFn;
|
|
1574
1577
|
reconnectPromise;
|
|
@@ -1585,6 +1588,9 @@ var McpClient = class {
|
|
|
1585
1588
|
setChildProcess(process) {
|
|
1586
1589
|
this.childProcess = process;
|
|
1587
1590
|
}
|
|
1591
|
+
setProcessLease(processLease) {
|
|
1592
|
+
this.processLease = processLease;
|
|
1593
|
+
}
|
|
1588
1594
|
setConnected(connected) {
|
|
1589
1595
|
this.connected = connected;
|
|
1590
1596
|
}
|
|
@@ -1683,9 +1689,20 @@ var McpClient = class {
|
|
|
1683
1689
|
});
|
|
1684
1690
|
}
|
|
1685
1691
|
async close() {
|
|
1686
|
-
|
|
1687
|
-
|
|
1692
|
+
const childProcess = this.childProcess;
|
|
1693
|
+
const processLease = this.processLease;
|
|
1694
|
+
this.childProcess = void 0;
|
|
1695
|
+
this.processLease = void 0;
|
|
1688
1696
|
this.connected = false;
|
|
1697
|
+
try {
|
|
1698
|
+
if (childProcess) childProcess.kill();
|
|
1699
|
+
await this.client.close();
|
|
1700
|
+
} finally {
|
|
1701
|
+
await processLease?.release({
|
|
1702
|
+
kill: false,
|
|
1703
|
+
releasePort: false
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1689
1706
|
}
|
|
1690
1707
|
};
|
|
1691
1708
|
/**
|
|
@@ -1696,38 +1713,18 @@ var McpClientManagerService = class {
|
|
|
1696
1713
|
serverConfigs = /* @__PURE__ */ new Map();
|
|
1697
1714
|
connectionPromises = /* @__PURE__ */ new Map();
|
|
1698
1715
|
logger;
|
|
1699
|
-
|
|
1716
|
+
repositoryPath;
|
|
1717
|
+
constructor(logger = console, repositoryPath = process.cwd()) {
|
|
1700
1718
|
this.logger = logger;
|
|
1719
|
+
this.repositoryPath = repositoryPath;
|
|
1701
1720
|
}
|
|
1702
1721
|
/**
|
|
1703
1722
|
* Kill all stdio MCP server child processes.
|
|
1704
|
-
*
|
|
1705
|
-
*
|
|
1706
|
-
* Awaiting the returned promise ensures force-kill timers complete before process.exit().
|
|
1723
|
+
* Delegates to disconnectAll() so each client closes its child process and
|
|
1724
|
+
* releases the corresponding process-registry lease before shutdown exits.
|
|
1707
1725
|
*/
|
|
1708
1726
|
async cleanupChildProcesses() {
|
|
1709
|
-
|
|
1710
|
-
for (const [serverName, client] of this.clients) try {
|
|
1711
|
-
const childProcess = client["childProcess"];
|
|
1712
|
-
if (childProcess && !childProcess.killed) {
|
|
1713
|
-
this.logger.info(`Killing stdio MCP server: ${serverName} (PID: ${childProcess.pid})`);
|
|
1714
|
-
childProcess.kill("SIGTERM");
|
|
1715
|
-
killPromises.push(new Promise((resolve) => {
|
|
1716
|
-
setTimeout(() => {
|
|
1717
|
-
try {
|
|
1718
|
-
if (!childProcess.killed) {
|
|
1719
|
-
this.logger.warn(`Force killing stdio MCP server: ${serverName} (PID: ${childProcess.pid})`);
|
|
1720
|
-
childProcess.kill("SIGKILL");
|
|
1721
|
-
}
|
|
1722
|
-
} catch {}
|
|
1723
|
-
resolve();
|
|
1724
|
-
}, 1e3);
|
|
1725
|
-
}));
|
|
1726
|
-
}
|
|
1727
|
-
} catch (error) {
|
|
1728
|
-
this.logger.warn(`Failed to kill child process for ${serverName}`, error);
|
|
1729
|
-
}
|
|
1730
|
-
await Promise.all(killPromises);
|
|
1727
|
+
await this.disconnectAll();
|
|
1731
1728
|
}
|
|
1732
1729
|
/**
|
|
1733
1730
|
* Connect to an MCP server based on its configuration with timeout
|
|
@@ -1823,7 +1820,22 @@ var McpClientManagerService = class {
|
|
|
1823
1820
|
});
|
|
1824
1821
|
await mcpClient["client"].connect(transport);
|
|
1825
1822
|
const childProcess = transport["_process"];
|
|
1826
|
-
if (childProcess)
|
|
1823
|
+
if (childProcess) {
|
|
1824
|
+
if (typeof childProcess.pid !== "number" || childProcess.pid <= 0) throw new Error(`Failed to capture pid for stdio child process on server "${mcpClient.serverName}"`);
|
|
1825
|
+
mcpClient.setChildProcess(childProcess);
|
|
1826
|
+
const processLease = await createProcessLease({
|
|
1827
|
+
repositoryPath: this.repositoryPath,
|
|
1828
|
+
serviceName: mcpClient.serverName,
|
|
1829
|
+
serviceType: PROCESS_REGISTRY_SERVICE_TYPE,
|
|
1830
|
+
pid: childProcess.pid,
|
|
1831
|
+
command: config.command,
|
|
1832
|
+
args: config.args,
|
|
1833
|
+
metadata: { transport: "stdio" }
|
|
1834
|
+
});
|
|
1835
|
+
mcpClient.setProcessLease(processLease);
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
throw new Error(`Failed to capture stdio child process for server "${mcpClient.serverName}"`);
|
|
1827
1839
|
}
|
|
1828
1840
|
async connectHttpClient(mcpClient, config) {
|
|
1829
1841
|
const transport = new StreamableHTTPClientTransport(new URL(config.url), { requestInit: config.headers ? { headers: config.headers } : void 0 });
|
|
@@ -4915,7 +4927,10 @@ async function createSessionServer(shared) {
|
|
|
4915
4927
|
* For multi-session HTTP transport, use createProxyContainer() + createSessionServer() instead.
|
|
4916
4928
|
*/
|
|
4917
4929
|
async function createServer$1(options) {
|
|
4918
|
-
|
|
4930
|
+
const shared = await createProxyContainer(options);
|
|
4931
|
+
const server = await createSessionServer(shared);
|
|
4932
|
+
Object.assign(server, { dispose: shared.dispose });
|
|
4933
|
+
return server;
|
|
4919
4934
|
}
|
|
4920
4935
|
//#endregion
|
|
4921
4936
|
//#region src/types/index.ts
|
|
@@ -33,6 +33,7 @@ let _modelcontextprotocol_sdk_client_index_js = require("@modelcontextprotocol/s
|
|
|
33
33
|
let _modelcontextprotocol_sdk_client_sse_js = require("@modelcontextprotocol/sdk/client/sse.js");
|
|
34
34
|
let _modelcontextprotocol_sdk_client_stdio_js = require("@modelcontextprotocol/sdk/client/stdio.js");
|
|
35
35
|
let _modelcontextprotocol_sdk_client_streamableHttp_js = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
36
|
+
let _agimon_ai_foundation_process_registry = require("@agimon-ai/foundation-process-registry");
|
|
36
37
|
let node_child_process = require("node:child_process");
|
|
37
38
|
let liquidjs = require("liquidjs");
|
|
38
39
|
let _agimon_ai_foundation_validator = require("@agimon-ai/foundation-validator");
|
|
@@ -47,7 +48,7 @@ let _modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sdk
|
|
|
47
48
|
let _modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
48
49
|
let _modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js");
|
|
49
50
|
//#region package.json
|
|
50
|
-
var version = "0.
|
|
51
|
+
var version = "0.10.0";
|
|
51
52
|
//#endregion
|
|
52
53
|
//#region src/utils/mcpConfigSchema.ts
|
|
53
54
|
/**
|
|
@@ -1538,6 +1539,7 @@ async function createProxyLogger(options = {}) {
|
|
|
1538
1539
|
//#region src/services/McpClientManagerService.ts
|
|
1539
1540
|
/** Default connection timeout in milliseconds (30 seconds) */
|
|
1540
1541
|
const DEFAULT_CONNECTION_TIMEOUT_MS = 3e4;
|
|
1542
|
+
const PROCESS_REGISTRY_SERVICE_TYPE = "tool";
|
|
1541
1543
|
/**
|
|
1542
1544
|
* Checks if an error is a session-related error from an HTTP backend
|
|
1543
1545
|
* (e.g., downstream server restarted and no longer recognizes the session ID).
|
|
@@ -1592,6 +1594,7 @@ var McpClient = class {
|
|
|
1592
1594
|
logger;
|
|
1593
1595
|
client;
|
|
1594
1596
|
childProcess;
|
|
1597
|
+
processLease;
|
|
1595
1598
|
connected = false;
|
|
1596
1599
|
reconnectFn;
|
|
1597
1600
|
reconnectPromise;
|
|
@@ -1608,6 +1611,9 @@ var McpClient = class {
|
|
|
1608
1611
|
setChildProcess(process) {
|
|
1609
1612
|
this.childProcess = process;
|
|
1610
1613
|
}
|
|
1614
|
+
setProcessLease(processLease) {
|
|
1615
|
+
this.processLease = processLease;
|
|
1616
|
+
}
|
|
1611
1617
|
setConnected(connected) {
|
|
1612
1618
|
this.connected = connected;
|
|
1613
1619
|
}
|
|
@@ -1706,9 +1712,20 @@ var McpClient = class {
|
|
|
1706
1712
|
});
|
|
1707
1713
|
}
|
|
1708
1714
|
async close() {
|
|
1709
|
-
|
|
1710
|
-
|
|
1715
|
+
const childProcess = this.childProcess;
|
|
1716
|
+
const processLease = this.processLease;
|
|
1717
|
+
this.childProcess = void 0;
|
|
1718
|
+
this.processLease = void 0;
|
|
1711
1719
|
this.connected = false;
|
|
1720
|
+
try {
|
|
1721
|
+
if (childProcess) childProcess.kill();
|
|
1722
|
+
await this.client.close();
|
|
1723
|
+
} finally {
|
|
1724
|
+
await processLease?.release({
|
|
1725
|
+
kill: false,
|
|
1726
|
+
releasePort: false
|
|
1727
|
+
});
|
|
1728
|
+
}
|
|
1712
1729
|
}
|
|
1713
1730
|
};
|
|
1714
1731
|
/**
|
|
@@ -1719,38 +1736,18 @@ var McpClientManagerService = class {
|
|
|
1719
1736
|
serverConfigs = /* @__PURE__ */ new Map();
|
|
1720
1737
|
connectionPromises = /* @__PURE__ */ new Map();
|
|
1721
1738
|
logger;
|
|
1722
|
-
|
|
1739
|
+
repositoryPath;
|
|
1740
|
+
constructor(logger = console, repositoryPath = process.cwd()) {
|
|
1723
1741
|
this.logger = logger;
|
|
1742
|
+
this.repositoryPath = repositoryPath;
|
|
1724
1743
|
}
|
|
1725
1744
|
/**
|
|
1726
1745
|
* Kill all stdio MCP server child processes.
|
|
1727
|
-
*
|
|
1728
|
-
*
|
|
1729
|
-
* Awaiting the returned promise ensures force-kill timers complete before process.exit().
|
|
1746
|
+
* Delegates to disconnectAll() so each client closes its child process and
|
|
1747
|
+
* releases the corresponding process-registry lease before shutdown exits.
|
|
1730
1748
|
*/
|
|
1731
1749
|
async cleanupChildProcesses() {
|
|
1732
|
-
|
|
1733
|
-
for (const [serverName, client] of this.clients) try {
|
|
1734
|
-
const childProcess = client["childProcess"];
|
|
1735
|
-
if (childProcess && !childProcess.killed) {
|
|
1736
|
-
this.logger.info(`Killing stdio MCP server: ${serverName} (PID: ${childProcess.pid})`);
|
|
1737
|
-
childProcess.kill("SIGTERM");
|
|
1738
|
-
killPromises.push(new Promise((resolve) => {
|
|
1739
|
-
setTimeout(() => {
|
|
1740
|
-
try {
|
|
1741
|
-
if (!childProcess.killed) {
|
|
1742
|
-
this.logger.warn(`Force killing stdio MCP server: ${serverName} (PID: ${childProcess.pid})`);
|
|
1743
|
-
childProcess.kill("SIGKILL");
|
|
1744
|
-
}
|
|
1745
|
-
} catch {}
|
|
1746
|
-
resolve();
|
|
1747
|
-
}, 1e3);
|
|
1748
|
-
}));
|
|
1749
|
-
}
|
|
1750
|
-
} catch (error) {
|
|
1751
|
-
this.logger.warn(`Failed to kill child process for ${serverName}`, error);
|
|
1752
|
-
}
|
|
1753
|
-
await Promise.all(killPromises);
|
|
1750
|
+
await this.disconnectAll();
|
|
1754
1751
|
}
|
|
1755
1752
|
/**
|
|
1756
1753
|
* Connect to an MCP server based on its configuration with timeout
|
|
@@ -1846,7 +1843,22 @@ var McpClientManagerService = class {
|
|
|
1846
1843
|
});
|
|
1847
1844
|
await mcpClient["client"].connect(transport);
|
|
1848
1845
|
const childProcess = transport["_process"];
|
|
1849
|
-
if (childProcess)
|
|
1846
|
+
if (childProcess) {
|
|
1847
|
+
if (typeof childProcess.pid !== "number" || childProcess.pid <= 0) throw new Error(`Failed to capture pid for stdio child process on server "${mcpClient.serverName}"`);
|
|
1848
|
+
mcpClient.setChildProcess(childProcess);
|
|
1849
|
+
const processLease = await (0, _agimon_ai_foundation_process_registry.createProcessLease)({
|
|
1850
|
+
repositoryPath: this.repositoryPath,
|
|
1851
|
+
serviceName: mcpClient.serverName,
|
|
1852
|
+
serviceType: PROCESS_REGISTRY_SERVICE_TYPE,
|
|
1853
|
+
pid: childProcess.pid,
|
|
1854
|
+
command: config.command,
|
|
1855
|
+
args: config.args,
|
|
1856
|
+
metadata: { transport: "stdio" }
|
|
1857
|
+
});
|
|
1858
|
+
mcpClient.setProcessLease(processLease);
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1861
|
+
throw new Error(`Failed to capture stdio child process for server "${mcpClient.serverName}"`);
|
|
1850
1862
|
}
|
|
1851
1863
|
async connectHttpClient(mcpClient, config) {
|
|
1852
1864
|
const transport = new _modelcontextprotocol_sdk_client_streamableHttp_js.StreamableHTTPClientTransport(new URL(config.url), { requestInit: config.headers ? { headers: config.headers } : void 0 });
|
|
@@ -4938,7 +4950,10 @@ async function createSessionServer(shared) {
|
|
|
4938
4950
|
* For multi-session HTTP transport, use createProxyContainer() + createSessionServer() instead.
|
|
4939
4951
|
*/
|
|
4940
4952
|
async function createServer(options) {
|
|
4941
|
-
|
|
4953
|
+
const shared = await createProxyContainer(options);
|
|
4954
|
+
const server = await createSessionServer(shared);
|
|
4955
|
+
Object.assign(server, { dispose: shared.dispose });
|
|
4956
|
+
return server;
|
|
4942
4957
|
}
|
|
4943
4958
|
//#endregion
|
|
4944
4959
|
//#region src/types/index.ts
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/mcp-proxy",
|
|
3
3
|
"description": "MCP proxy server package",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.1",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"zod": "4.3.6",
|
|
31
31
|
"@agimon-ai/foundation-process-registry": "0.8.0",
|
|
32
32
|
"@agimon-ai/log-sink-mcp": "0.8.0",
|
|
33
|
-
"@agimon-ai/foundation-
|
|
34
|
-
"@agimon-ai/foundation-
|
|
33
|
+
"@agimon-ai/foundation-port-registry": "0.8.0",
|
|
34
|
+
"@agimon-ai/foundation-validator": "0.5.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/js-yaml": "4.0.9",
|