@agimon-ai/mcp-proxy 0.7.1 → 0.7.2
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 +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.mjs +1 -1
- package/dist/{src-DyWwAp8e.cjs → src-BXEt-Hpg.cjs} +80 -21
- package/dist/{src-NOWQwaRe.mjs → src-NZo_eM6U.mjs} +80 -21
- package/package.json +4 -4
package/dist/cli.cjs
CHANGED
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
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, w as generateServerId, y as StopServerService } 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, w as generateServerId, y as StopServerService } from "./src-NZo_eM6U.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";
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
|
@@ -1197,6 +1197,8 @@ interface StdioHttpProxyTransportConfig {
|
|
|
1197
1197
|
}
|
|
1198
1198
|
/**
|
|
1199
1199
|
* Transport that serves MCP over stdio and forwards MCP requests to an HTTP endpoint.
|
|
1200
|
+
* Automatically reconnects to the HTTP backend with exponential backoff when the
|
|
1201
|
+
* connection is lost (e.g. backend crash + restart).
|
|
1200
1202
|
*/
|
|
1201
1203
|
declare class StdioHttpTransportHandler implements TransportHandler {
|
|
1202
1204
|
private readonly endpoint;
|
|
@@ -1204,9 +1206,16 @@ declare class StdioHttpTransportHandler implements TransportHandler {
|
|
|
1204
1206
|
private stdioTransport;
|
|
1205
1207
|
private httpClient;
|
|
1206
1208
|
private logger;
|
|
1209
|
+
private readonly MAX_RECONNECT_ATTEMPTS;
|
|
1210
|
+
private readonly RECONNECT_BASE_MS;
|
|
1211
|
+
private readonly RECONNECT_MAX_MS;
|
|
1207
1212
|
constructor(config: StdioHttpProxyTransportConfig, logger?: LoggerLike);
|
|
1208
1213
|
start(): Promise<void>;
|
|
1209
1214
|
stop(): Promise<void>;
|
|
1215
|
+
private createAndConnectClient;
|
|
1216
|
+
private registerElicitationHandler;
|
|
1217
|
+
private reconnectWithBackoff;
|
|
1218
|
+
private withReconnect;
|
|
1210
1219
|
private createProxyServer;
|
|
1211
1220
|
}
|
|
1212
1221
|
//#endregion
|
package/dist/index.d.mts
CHANGED
|
@@ -1198,6 +1198,8 @@ interface StdioHttpProxyTransportConfig {
|
|
|
1198
1198
|
}
|
|
1199
1199
|
/**
|
|
1200
1200
|
* Transport that serves MCP over stdio and forwards MCP requests to an HTTP endpoint.
|
|
1201
|
+
* Automatically reconnects to the HTTP backend with exponential backoff when the
|
|
1202
|
+
* connection is lost (e.g. backend crash + restart).
|
|
1201
1203
|
*/
|
|
1202
1204
|
declare class StdioHttpTransportHandler implements TransportHandler {
|
|
1203
1205
|
private readonly endpoint;
|
|
@@ -1205,9 +1207,16 @@ declare class StdioHttpTransportHandler implements TransportHandler {
|
|
|
1205
1207
|
private stdioTransport;
|
|
1206
1208
|
private httpClient;
|
|
1207
1209
|
private logger;
|
|
1210
|
+
private readonly MAX_RECONNECT_ATTEMPTS;
|
|
1211
|
+
private readonly RECONNECT_BASE_MS;
|
|
1212
|
+
private readonly RECONNECT_MAX_MS;
|
|
1208
1213
|
constructor(config: StdioHttpProxyTransportConfig, logger?: LoggerLike);
|
|
1209
1214
|
start(): Promise<void>;
|
|
1210
1215
|
stop(): Promise<void>;
|
|
1216
|
+
private createAndConnectClient;
|
|
1217
|
+
private registerElicitationHandler;
|
|
1218
|
+
private reconnectWithBackoff;
|
|
1219
|
+
private withReconnect;
|
|
1211
1220
|
private createProxyServer;
|
|
1212
1221
|
}
|
|
1213
1222
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
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 SkillService, w as generateServerId, x as McpClientManagerService, y as StopServerService } 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 SkillService, w as generateServerId, x as McpClientManagerService, y as StopServerService } from "./src-NZo_eM6U.mjs";
|
|
2
2
|
|
|
3
3
|
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 };
|
|
@@ -52,7 +52,7 @@ let __modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sd
|
|
|
52
52
|
let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
53
53
|
|
|
54
54
|
//#region package.json
|
|
55
|
-
var version = "0.7.
|
|
55
|
+
var version = "0.7.1";
|
|
56
56
|
|
|
57
57
|
//#endregion
|
|
58
58
|
//#region src/utils/mcpConfigSchema.ts
|
|
@@ -4422,19 +4422,38 @@ var StdioTransportHandler = class {
|
|
|
4422
4422
|
* - Transport handler pattern implementing TransportHandler interface
|
|
4423
4423
|
* - STDIO transport with MCP request forwarding to HTTP backend
|
|
4424
4424
|
* - Graceful cleanup with error isolation
|
|
4425
|
+
* - Reconnection with exponential backoff on connection loss
|
|
4425
4426
|
*
|
|
4426
4427
|
* CODING STANDARDS:
|
|
4427
4428
|
* - Use StdioServerTransport for stdio communication
|
|
4428
4429
|
* - Reuse a single StreamableHTTP client connection
|
|
4429
4430
|
* - Wrap async operations with try-catch and descriptive errors
|
|
4431
|
+
* - Reconnect transparently on connection reset
|
|
4430
4432
|
*
|
|
4431
4433
|
* AVOID:
|
|
4432
4434
|
* - Starting HTTP server lifecycle in this transport entry point
|
|
4433
4435
|
* - Recreating HTTP client per request
|
|
4434
4436
|
* - Swallowing cleanup failures silently
|
|
4435
4437
|
*/
|
|
4438
|
+
const CONNECTION_ERROR_PATTERNS = [
|
|
4439
|
+
"econnrefused",
|
|
4440
|
+
"econnreset",
|
|
4441
|
+
"enotfound",
|
|
4442
|
+
"connection refused",
|
|
4443
|
+
"fetch failed",
|
|
4444
|
+
"socket hang up",
|
|
4445
|
+
"network error",
|
|
4446
|
+
"failed to fetch"
|
|
4447
|
+
];
|
|
4448
|
+
function isConnectionError(error) {
|
|
4449
|
+
if (!(error instanceof Error)) return false;
|
|
4450
|
+
const message = error.message.toLowerCase();
|
|
4451
|
+
return CONNECTION_ERROR_PATTERNS.some((pattern) => message.includes(pattern));
|
|
4452
|
+
}
|
|
4436
4453
|
/**
|
|
4437
4454
|
* Transport that serves MCP over stdio and forwards MCP requests to an HTTP endpoint.
|
|
4455
|
+
* Automatically reconnects to the HTTP backend with exponential backoff when the
|
|
4456
|
+
* connection is lost (e.g. backend crash + restart).
|
|
4438
4457
|
*/
|
|
4439
4458
|
var StdioHttpTransportHandler = class {
|
|
4440
4459
|
endpoint;
|
|
@@ -4442,24 +4461,19 @@ var StdioHttpTransportHandler = class {
|
|
|
4442
4461
|
stdioTransport = null;
|
|
4443
4462
|
httpClient = null;
|
|
4444
4463
|
logger;
|
|
4464
|
+
MAX_RECONNECT_ATTEMPTS = 5;
|
|
4465
|
+
RECONNECT_BASE_MS = 1e3;
|
|
4466
|
+
RECONNECT_MAX_MS = 3e4;
|
|
4445
4467
|
constructor(config, logger = console) {
|
|
4446
4468
|
this.endpoint = config.endpoint;
|
|
4447
4469
|
this.logger = logger;
|
|
4448
4470
|
}
|
|
4449
4471
|
async start() {
|
|
4450
4472
|
try {
|
|
4451
|
-
const
|
|
4452
|
-
const client = new __modelcontextprotocol_sdk_client_index_js.Client({
|
|
4453
|
-
name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
|
|
4454
|
-
version: "0.1.0"
|
|
4455
|
-
}, { capabilities: { elicitation: {} } });
|
|
4456
|
-
await client.connect(httpClientTransport);
|
|
4473
|
+
const client = await this.createAndConnectClient();
|
|
4457
4474
|
this.httpClient = client;
|
|
4458
|
-
this.stdioProxyServer = this.createProxyServer(
|
|
4459
|
-
|
|
4460
|
-
client.setRequestHandler(__modelcontextprotocol_sdk_types_js.ElicitRequestSchema, async (request) => {
|
|
4461
|
-
return await proxyServer.elicitInput(request.params);
|
|
4462
|
-
});
|
|
4475
|
+
this.stdioProxyServer = this.createProxyServer();
|
|
4476
|
+
this.registerElicitationHandler(client);
|
|
4463
4477
|
this.stdioTransport = new __modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
|
|
4464
4478
|
await this.stdioProxyServer.connect(this.stdioTransport);
|
|
4465
4479
|
this.logger.info(`@agimon-ai/mcp-proxy MCP stdio proxy connected to ${this.endpoint.toString()}`);
|
|
@@ -4501,7 +4515,52 @@ var StdioHttpTransportHandler = class {
|
|
|
4501
4515
|
]);
|
|
4502
4516
|
if (cleanupErrors.length > 0) throw new Error(`Failed to stop stdio-http proxy transport: ${cleanupErrors.join("; ")}`);
|
|
4503
4517
|
}
|
|
4504
|
-
|
|
4518
|
+
async createAndConnectClient() {
|
|
4519
|
+
const httpClientTransport = new __modelcontextprotocol_sdk_client_streamableHttp_js.StreamableHTTPClientTransport(this.endpoint);
|
|
4520
|
+
const client = new __modelcontextprotocol_sdk_client_index_js.Client({
|
|
4521
|
+
name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
|
|
4522
|
+
version: "0.1.0"
|
|
4523
|
+
}, { capabilities: { elicitation: {} } });
|
|
4524
|
+
await client.connect(httpClientTransport);
|
|
4525
|
+
return client;
|
|
4526
|
+
}
|
|
4527
|
+
registerElicitationHandler(client) {
|
|
4528
|
+
const proxyServer = this.stdioProxyServer;
|
|
4529
|
+
if (!proxyServer) return;
|
|
4530
|
+
client.setRequestHandler(__modelcontextprotocol_sdk_types_js.ElicitRequestSchema, async (request) => {
|
|
4531
|
+
return await proxyServer.elicitInput(request.params);
|
|
4532
|
+
});
|
|
4533
|
+
}
|
|
4534
|
+
async reconnectWithBackoff() {
|
|
4535
|
+
for (let attempt = 0; attempt < this.MAX_RECONNECT_ATTEMPTS; attempt++) {
|
|
4536
|
+
const delay = Math.min(this.RECONNECT_BASE_MS * 2 ** attempt, this.RECONNECT_MAX_MS);
|
|
4537
|
+
await new Promise((resolve$2) => setTimeout(resolve$2, delay));
|
|
4538
|
+
try {
|
|
4539
|
+
await this.httpClient?.close().catch(() => void 0);
|
|
4540
|
+
const client = await this.createAndConnectClient();
|
|
4541
|
+
this.httpClient = client;
|
|
4542
|
+
this.registerElicitationHandler(client);
|
|
4543
|
+
this.logger.info(`Reconnected to HTTP backend at ${this.endpoint.toString()} (attempt ${attempt + 1})`);
|
|
4544
|
+
return;
|
|
4545
|
+
} catch {
|
|
4546
|
+
this.logger.info(`Reconnect attempt ${attempt + 1}/${this.MAX_RECONNECT_ATTEMPTS} to ${this.endpoint.toString()} failed`);
|
|
4547
|
+
}
|
|
4548
|
+
}
|
|
4549
|
+
throw new Error(`Failed to reconnect to HTTP backend at ${this.endpoint.toString()} after ${this.MAX_RECONNECT_ATTEMPTS} attempts`);
|
|
4550
|
+
}
|
|
4551
|
+
async withReconnect(fn) {
|
|
4552
|
+
if (!this.httpClient) throw new Error("HTTP client not connected");
|
|
4553
|
+
try {
|
|
4554
|
+
return await fn();
|
|
4555
|
+
} catch (error) {
|
|
4556
|
+
if (isConnectionError(error)) {
|
|
4557
|
+
await this.reconnectWithBackoff();
|
|
4558
|
+
return await fn();
|
|
4559
|
+
}
|
|
4560
|
+
throw error;
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4563
|
+
createProxyServer() {
|
|
4505
4564
|
const proxyServer = new __modelcontextprotocol_sdk_server_index_js.Server({
|
|
4506
4565
|
name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
|
|
4507
4566
|
version: "0.1.0"
|
|
@@ -4512,48 +4571,48 @@ var StdioHttpTransportHandler = class {
|
|
|
4512
4571
|
} });
|
|
4513
4572
|
proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => {
|
|
4514
4573
|
try {
|
|
4515
|
-
return await
|
|
4574
|
+
return await this.withReconnect(() => this.httpClient.listTools());
|
|
4516
4575
|
} catch (error) {
|
|
4517
4576
|
throw new Error(`Failed forwarding tools/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4518
4577
|
}
|
|
4519
4578
|
});
|
|
4520
4579
|
proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => {
|
|
4521
4580
|
try {
|
|
4522
|
-
return await
|
|
4581
|
+
return await this.withReconnect(() => this.httpClient.callTool({
|
|
4523
4582
|
name: request.params.name,
|
|
4524
4583
|
arguments: request.params.arguments
|
|
4525
|
-
});
|
|
4584
|
+
}));
|
|
4526
4585
|
} catch (error) {
|
|
4527
4586
|
throw new Error(`Failed forwarding tools/call (${request.params.name}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4528
4587
|
}
|
|
4529
4588
|
});
|
|
4530
4589
|
proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListResourcesRequestSchema, async () => {
|
|
4531
4590
|
try {
|
|
4532
|
-
return await
|
|
4591
|
+
return await this.withReconnect(() => this.httpClient.listResources());
|
|
4533
4592
|
} catch (error) {
|
|
4534
4593
|
throw new Error(`Failed forwarding resources/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4535
4594
|
}
|
|
4536
4595
|
});
|
|
4537
4596
|
proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ReadResourceRequestSchema, async (request) => {
|
|
4538
4597
|
try {
|
|
4539
|
-
return await
|
|
4598
|
+
return await this.withReconnect(() => this.httpClient.readResource({ uri: request.params.uri }));
|
|
4540
4599
|
} catch (error) {
|
|
4541
4600
|
throw new Error(`Failed forwarding resources/read (${request.params.uri}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4542
4601
|
}
|
|
4543
4602
|
});
|
|
4544
4603
|
proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListPromptsRequestSchema, async () => {
|
|
4545
4604
|
try {
|
|
4546
|
-
return await
|
|
4605
|
+
return await this.withReconnect(() => this.httpClient.listPrompts());
|
|
4547
4606
|
} catch (error) {
|
|
4548
4607
|
throw new Error(`Failed forwarding prompts/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4549
4608
|
}
|
|
4550
4609
|
});
|
|
4551
4610
|
proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.GetPromptRequestSchema, async (request) => {
|
|
4552
4611
|
try {
|
|
4553
|
-
return await
|
|
4612
|
+
return await this.withReconnect(() => this.httpClient.getPrompt({
|
|
4554
4613
|
name: request.params.name,
|
|
4555
4614
|
arguments: request.params.arguments
|
|
4556
|
-
});
|
|
4615
|
+
}));
|
|
4557
4616
|
} catch (error) {
|
|
4558
4617
|
throw new Error(`Failed forwarding prompts/get (${request.params.name}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4559
4618
|
}
|
|
@@ -24,7 +24,7 @@ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
|
24
24
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
25
25
|
|
|
26
26
|
//#region package.json
|
|
27
|
-
var version = "0.7.
|
|
27
|
+
var version = "0.7.1";
|
|
28
28
|
|
|
29
29
|
//#endregion
|
|
30
30
|
//#region src/utils/mcpConfigSchema.ts
|
|
@@ -4394,19 +4394,38 @@ var StdioTransportHandler = class {
|
|
|
4394
4394
|
* - Transport handler pattern implementing TransportHandler interface
|
|
4395
4395
|
* - STDIO transport with MCP request forwarding to HTTP backend
|
|
4396
4396
|
* - Graceful cleanup with error isolation
|
|
4397
|
+
* - Reconnection with exponential backoff on connection loss
|
|
4397
4398
|
*
|
|
4398
4399
|
* CODING STANDARDS:
|
|
4399
4400
|
* - Use StdioServerTransport for stdio communication
|
|
4400
4401
|
* - Reuse a single StreamableHTTP client connection
|
|
4401
4402
|
* - Wrap async operations with try-catch and descriptive errors
|
|
4403
|
+
* - Reconnect transparently on connection reset
|
|
4402
4404
|
*
|
|
4403
4405
|
* AVOID:
|
|
4404
4406
|
* - Starting HTTP server lifecycle in this transport entry point
|
|
4405
4407
|
* - Recreating HTTP client per request
|
|
4406
4408
|
* - Swallowing cleanup failures silently
|
|
4407
4409
|
*/
|
|
4410
|
+
const CONNECTION_ERROR_PATTERNS = [
|
|
4411
|
+
"econnrefused",
|
|
4412
|
+
"econnreset",
|
|
4413
|
+
"enotfound",
|
|
4414
|
+
"connection refused",
|
|
4415
|
+
"fetch failed",
|
|
4416
|
+
"socket hang up",
|
|
4417
|
+
"network error",
|
|
4418
|
+
"failed to fetch"
|
|
4419
|
+
];
|
|
4420
|
+
function isConnectionError(error) {
|
|
4421
|
+
if (!(error instanceof Error)) return false;
|
|
4422
|
+
const message = error.message.toLowerCase();
|
|
4423
|
+
return CONNECTION_ERROR_PATTERNS.some((pattern) => message.includes(pattern));
|
|
4424
|
+
}
|
|
4408
4425
|
/**
|
|
4409
4426
|
* Transport that serves MCP over stdio and forwards MCP requests to an HTTP endpoint.
|
|
4427
|
+
* Automatically reconnects to the HTTP backend with exponential backoff when the
|
|
4428
|
+
* connection is lost (e.g. backend crash + restart).
|
|
4410
4429
|
*/
|
|
4411
4430
|
var StdioHttpTransportHandler = class {
|
|
4412
4431
|
endpoint;
|
|
@@ -4414,24 +4433,19 @@ var StdioHttpTransportHandler = class {
|
|
|
4414
4433
|
stdioTransport = null;
|
|
4415
4434
|
httpClient = null;
|
|
4416
4435
|
logger;
|
|
4436
|
+
MAX_RECONNECT_ATTEMPTS = 5;
|
|
4437
|
+
RECONNECT_BASE_MS = 1e3;
|
|
4438
|
+
RECONNECT_MAX_MS = 3e4;
|
|
4417
4439
|
constructor(config, logger = console) {
|
|
4418
4440
|
this.endpoint = config.endpoint;
|
|
4419
4441
|
this.logger = logger;
|
|
4420
4442
|
}
|
|
4421
4443
|
async start() {
|
|
4422
4444
|
try {
|
|
4423
|
-
const
|
|
4424
|
-
const client = new Client({
|
|
4425
|
-
name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
|
|
4426
|
-
version: "0.1.0"
|
|
4427
|
-
}, { capabilities: { elicitation: {} } });
|
|
4428
|
-
await client.connect(httpClientTransport);
|
|
4445
|
+
const client = await this.createAndConnectClient();
|
|
4429
4446
|
this.httpClient = client;
|
|
4430
|
-
this.stdioProxyServer = this.createProxyServer(
|
|
4431
|
-
|
|
4432
|
-
client.setRequestHandler(ElicitRequestSchema, async (request) => {
|
|
4433
|
-
return await proxyServer.elicitInput(request.params);
|
|
4434
|
-
});
|
|
4447
|
+
this.stdioProxyServer = this.createProxyServer();
|
|
4448
|
+
this.registerElicitationHandler(client);
|
|
4435
4449
|
this.stdioTransport = new StdioServerTransport();
|
|
4436
4450
|
await this.stdioProxyServer.connect(this.stdioTransport);
|
|
4437
4451
|
this.logger.info(`@agimon-ai/mcp-proxy MCP stdio proxy connected to ${this.endpoint.toString()}`);
|
|
@@ -4473,7 +4487,52 @@ var StdioHttpTransportHandler = class {
|
|
|
4473
4487
|
]);
|
|
4474
4488
|
if (cleanupErrors.length > 0) throw new Error(`Failed to stop stdio-http proxy transport: ${cleanupErrors.join("; ")}`);
|
|
4475
4489
|
}
|
|
4476
|
-
|
|
4490
|
+
async createAndConnectClient() {
|
|
4491
|
+
const httpClientTransport = new StreamableHTTPClientTransport(this.endpoint);
|
|
4492
|
+
const client = new Client({
|
|
4493
|
+
name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
|
|
4494
|
+
version: "0.1.0"
|
|
4495
|
+
}, { capabilities: { elicitation: {} } });
|
|
4496
|
+
await client.connect(httpClientTransport);
|
|
4497
|
+
return client;
|
|
4498
|
+
}
|
|
4499
|
+
registerElicitationHandler(client) {
|
|
4500
|
+
const proxyServer = this.stdioProxyServer;
|
|
4501
|
+
if (!proxyServer) return;
|
|
4502
|
+
client.setRequestHandler(ElicitRequestSchema, async (request) => {
|
|
4503
|
+
return await proxyServer.elicitInput(request.params);
|
|
4504
|
+
});
|
|
4505
|
+
}
|
|
4506
|
+
async reconnectWithBackoff() {
|
|
4507
|
+
for (let attempt = 0; attempt < this.MAX_RECONNECT_ATTEMPTS; attempt++) {
|
|
4508
|
+
const delay = Math.min(this.RECONNECT_BASE_MS * 2 ** attempt, this.RECONNECT_MAX_MS);
|
|
4509
|
+
await new Promise((resolve$1) => setTimeout(resolve$1, delay));
|
|
4510
|
+
try {
|
|
4511
|
+
await this.httpClient?.close().catch(() => void 0);
|
|
4512
|
+
const client = await this.createAndConnectClient();
|
|
4513
|
+
this.httpClient = client;
|
|
4514
|
+
this.registerElicitationHandler(client);
|
|
4515
|
+
this.logger.info(`Reconnected to HTTP backend at ${this.endpoint.toString()} (attempt ${attempt + 1})`);
|
|
4516
|
+
return;
|
|
4517
|
+
} catch {
|
|
4518
|
+
this.logger.info(`Reconnect attempt ${attempt + 1}/${this.MAX_RECONNECT_ATTEMPTS} to ${this.endpoint.toString()} failed`);
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
throw new Error(`Failed to reconnect to HTTP backend at ${this.endpoint.toString()} after ${this.MAX_RECONNECT_ATTEMPTS} attempts`);
|
|
4522
|
+
}
|
|
4523
|
+
async withReconnect(fn) {
|
|
4524
|
+
if (!this.httpClient) throw new Error("HTTP client not connected");
|
|
4525
|
+
try {
|
|
4526
|
+
return await fn();
|
|
4527
|
+
} catch (error) {
|
|
4528
|
+
if (isConnectionError(error)) {
|
|
4529
|
+
await this.reconnectWithBackoff();
|
|
4530
|
+
return await fn();
|
|
4531
|
+
}
|
|
4532
|
+
throw error;
|
|
4533
|
+
}
|
|
4534
|
+
}
|
|
4535
|
+
createProxyServer() {
|
|
4477
4536
|
const proxyServer = new Server({
|
|
4478
4537
|
name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
|
|
4479
4538
|
version: "0.1.0"
|
|
@@ -4484,48 +4543,48 @@ var StdioHttpTransportHandler = class {
|
|
|
4484
4543
|
} });
|
|
4485
4544
|
proxyServer.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
4486
4545
|
try {
|
|
4487
|
-
return await
|
|
4546
|
+
return await this.withReconnect(() => this.httpClient.listTools());
|
|
4488
4547
|
} catch (error) {
|
|
4489
4548
|
throw new Error(`Failed forwarding tools/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4490
4549
|
}
|
|
4491
4550
|
});
|
|
4492
4551
|
proxyServer.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
4493
4552
|
try {
|
|
4494
|
-
return await
|
|
4553
|
+
return await this.withReconnect(() => this.httpClient.callTool({
|
|
4495
4554
|
name: request.params.name,
|
|
4496
4555
|
arguments: request.params.arguments
|
|
4497
|
-
});
|
|
4556
|
+
}));
|
|
4498
4557
|
} catch (error) {
|
|
4499
4558
|
throw new Error(`Failed forwarding tools/call (${request.params.name}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4500
4559
|
}
|
|
4501
4560
|
});
|
|
4502
4561
|
proxyServer.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
4503
4562
|
try {
|
|
4504
|
-
return await
|
|
4563
|
+
return await this.withReconnect(() => this.httpClient.listResources());
|
|
4505
4564
|
} catch (error) {
|
|
4506
4565
|
throw new Error(`Failed forwarding resources/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4507
4566
|
}
|
|
4508
4567
|
});
|
|
4509
4568
|
proxyServer.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
4510
4569
|
try {
|
|
4511
|
-
return await
|
|
4570
|
+
return await this.withReconnect(() => this.httpClient.readResource({ uri: request.params.uri }));
|
|
4512
4571
|
} catch (error) {
|
|
4513
4572
|
throw new Error(`Failed forwarding resources/read (${request.params.uri}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4514
4573
|
}
|
|
4515
4574
|
});
|
|
4516
4575
|
proxyServer.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
4517
4576
|
try {
|
|
4518
|
-
return await
|
|
4577
|
+
return await this.withReconnect(() => this.httpClient.listPrompts());
|
|
4519
4578
|
} catch (error) {
|
|
4520
4579
|
throw new Error(`Failed forwarding prompts/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4521
4580
|
}
|
|
4522
4581
|
});
|
|
4523
4582
|
proxyServer.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
4524
4583
|
try {
|
|
4525
|
-
return await
|
|
4584
|
+
return await this.withReconnect(() => this.httpClient.getPrompt({
|
|
4526
4585
|
name: request.params.name,
|
|
4527
4586
|
arguments: request.params.arguments
|
|
4528
|
-
});
|
|
4587
|
+
}));
|
|
4529
4588
|
} catch (error) {
|
|
4530
4589
|
throw new Error(`Failed forwarding prompts/get (${request.params.name}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
|
|
4531
4590
|
}
|
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.7.
|
|
4
|
+
"version": "0.7.2",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"js-yaml": "^4.1.0",
|
|
29
29
|
"liquidjs": "^10.21.0",
|
|
30
30
|
"zod": "^3.24.1",
|
|
31
|
-
"@agimon-ai/foundation-process-registry": "0.5.
|
|
32
|
-
"@agimon-ai/foundation-port-registry": "0.5.
|
|
33
|
-
"@agimon-ai/log-sink-mcp": "0.5.
|
|
31
|
+
"@agimon-ai/foundation-process-registry": "0.5.2",
|
|
32
|
+
"@agimon-ai/foundation-port-registry": "0.5.2",
|
|
33
|
+
"@agimon-ai/log-sink-mcp": "0.5.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/js-yaml": "^4.0.9",
|