@agimon-ai/mcp-proxy 0.7.1 → 0.7.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.
@@ -25,13 +25,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
  }) : target, mod));
26
26
 
27
27
  //#endregion
28
+ let __agimon_ai_foundation_validator = require("@agimon-ai/foundation-validator");
28
29
  let __modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js");
29
30
  let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
31
+ let zod = require("zod");
30
32
  let node_fs = require("node:fs");
31
33
  let node_fs_promises = require("node:fs/promises");
32
34
  let js_yaml = require("js-yaml");
33
35
  js_yaml = __toESM(js_yaml);
34
- let zod = require("zod");
35
36
  let node_crypto = require("node:crypto");
36
37
  let node_os = require("node:os");
37
38
  let node_path = require("node:path");
@@ -52,7 +53,7 @@ let __modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sd
52
53
  let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
53
54
 
54
55
  //#region package.json
55
- var version = "0.7.0";
56
+ var version = "0.7.2";
56
57
 
57
58
  //#endregion
58
59
  //#region src/utils/mcpConfigSchema.ts
@@ -1365,6 +1366,9 @@ var DefinitionsCacheService = class {
1365
1366
  async getServersForTool(toolName) {
1366
1367
  return (await this.getServerDefinitions()).filter((serverDefinition) => serverDefinition.tools.some((tool) => tool.name === toolName)).map((serverDefinition) => serverDefinition.serverName);
1367
1368
  }
1369
+ async getToolSchema(serverName, toolName) {
1370
+ return (await this.getDefinitions()).servers[serverName]?.tools.find((t) => t.name === toolName)?.inputSchema;
1371
+ }
1368
1372
  async getServersForResource(uri) {
1369
1373
  return (await this.getServerDefinitions()).filter((serverDefinition) => serverDefinition.resources.some((resource) => resource.uri === uri)).map((serverDefinition) => serverDefinition.serverName);
1370
1374
  }
@@ -1810,7 +1814,7 @@ var McpClientManagerService = class {
1810
1814
  async createConnection(serverName, config) {
1811
1815
  const timeoutMs = config.timeout ?? DEFAULT_CONNECTION_TIMEOUT_MS;
1812
1816
  const client = new __modelcontextprotocol_sdk_client_index_js.Client({
1813
- name: `@agimon-ai/mcp-proxy-client`,
1817
+ name: "@agimon-ai/mcp-proxy-client",
1814
1818
  version: "0.1.0"
1815
1819
  }, { capabilities: {} });
1816
1820
  const mcpClient = new McpClient(serverName, config.transport, client, this.logger, {
@@ -2994,7 +2998,7 @@ var PrefetchService = class {
2994
2998
 
2995
2999
  //#endregion
2996
3000
  //#region src/templates/toolkit-description.liquid?raw
2997
- var toolkit_description_default = "<toolkit id=\"{{ serverId }}\">\n<instruction>\nBefore you use any capabilities below, you MUST call this tool with a list of names to learn how to use them properly; this includes:\n- For tools: Arguments schema needed to pass to use_tool\n- For skills: Detailed instructions that will expand when invoked (Prefer to be explored first when relevant)\n\nThis tool is optimized for batch queries - you can request multiple capabilities at once for better performance.\n\nHow to invoke:\n- For MCP tools: Use use_tool with toolName and toolArgs based on the schema\n- For skills: Use this tool with the skill name to get expanded instructions\n</instruction>\n\n<available_capabilities>\n{% for server in servers -%}\n<group name=\"{{ server.name }}\">\n{% if server.instruction -%}\n<group_instruction>{{ server.instruction }}</group_instruction>\n{% endif -%}\n{% if server.omitToolDescription -%}\n{% for toolName in server.toolNames -%}\n<item name=\"{{ toolName }}\"></item>\n{% endfor -%}\n{% else -%}\n{% for tool in server.tools -%}\n<item name=\"{{ tool.displayName }}\"><description>{{ tool.description | default: \"No description\" }}</description></item>\n{% endfor -%}\n{% endif -%}\n</group>\n{% endfor -%}\n{% if skills.size > 0 -%}\n<group name=\"skills\">\n{% for skill in skills -%}\n<item name=\"{{ skill.displayName }}\"><description>{{ skill.description }}</description></item>\n{% endfor -%}\n</group>\n{% endif -%}\n</available_capabilities>\n</toolkit>\n";
3001
+ var toolkit_description_default = "<toolkit id=\"{{ serverId }}\">\n<instruction>\nBefore you use any capabilities below, you MUST call this tool with a list of names to learn how to use them properly; this includes:\n- For tools: Arguments schema needed to pass to use_tool\n- For skills: Detailed instructions that will expand when invoked (Prefer to be explored first when relevant)\n\nThis tool is optimized for batch queries - you can request multiple capabilities at once for better performance.\n\nHow to invoke:\n- For MCP tools: Use use_tool with toolName and toolArgs based on the schema\n- For skills: Use this tool with the skill name to get expanded instructions\n</instruction>\n\n<available_capabilities>\n{% for server in servers -%}\n<group original-mcp-server=\"{{ server.name }}\">\n{% if server.instruction -%}\n<group_instruction>{{ server.instruction }}</group_instruction>\n{% endif -%}\n{% if server.omitToolDescription -%}\n{% for toolName in server.toolNames -%}\n<item name=\"{{ toolName }}\"></item>\n{% endfor -%}\n{% else -%}\n{% for tool in server.tools -%}\n<item name=\"{{ tool.displayName }}\"><description>{{ tool.description | default: \"No description\" }}</description></item>\n{% endfor -%}\n{% endif -%}\n</group>\n{% endfor -%}\n{% if skills.size > 0 -%}\n<group name=\"skills\">\n{% for skill in skills -%}\n<item name=\"{{ skill.displayName }}\"><description>{{ skill.description }}</description></item>\n{% endfor -%}\n</group>\n{% endif -%}\n</available_capabilities>\n</toolkit>\n";
2998
3002
 
2999
3003
  //#endregion
3000
3004
  //#region src/tools/DescribeToolsTool.ts
@@ -3010,6 +3014,11 @@ function formatSkillInstructions(name, instructions) {
3010
3014
  return `<command-message>The "${name}" skill is loading</command-message>\n${instructions}`;
3011
3015
  }
3012
3016
  /**
3017
+ * Input schema for the DescribeToolsTool
3018
+ * @property toolNames - Array of tool names to get detailed information about
3019
+ */
3020
+ const DescribeToolsToolInputSchema = zod.z.object({ toolNames: zod.z.array(zod.z.string().min(1)).min(1).describe("List of tool names to get detailed information about") });
3021
+ /**
3013
3022
  * DescribeToolsTool provides progressive disclosure of MCP tools and skills.
3014
3023
  *
3015
3024
  * This tool lists available tools from all connected MCP servers and skills
@@ -3266,25 +3275,15 @@ var DescribeToolsTool = class DescribeToolsTool {
3266
3275
  *
3267
3276
  * @returns Tool definition with description and input schema
3268
3277
  */
3278
+ getInputSchema() {
3279
+ return DescribeToolsToolInputSchema;
3280
+ }
3269
3281
  async getDefinition() {
3270
3282
  const { content } = await this.buildToolkitDescription();
3271
3283
  return {
3272
3284
  name: DescribeToolsTool.TOOL_NAME,
3273
3285
  description: content,
3274
- inputSchema: {
3275
- type: "object",
3276
- properties: { toolNames: {
3277
- type: "array",
3278
- items: {
3279
- type: "string",
3280
- minLength: 1
3281
- },
3282
- description: "List of tool names to get detailed information about",
3283
- minItems: 1
3284
- } },
3285
- required: ["toolNames"],
3286
- additionalProperties: false
3287
- }
3286
+ inputSchema: zod.z.toJSONSchema(DescribeToolsToolInputSchema, { reused: "inline" })
3288
3287
  };
3289
3288
  }
3290
3289
  /**
@@ -3298,9 +3297,9 @@ var DescribeToolsTool = class DescribeToolsTool {
3298
3297
  * @param input - Object containing toolNames array
3299
3298
  * @returns CallToolResult with tool/skill descriptions or error
3300
3299
  */
3301
- async execute(input) {
3300
+ async execute(rawInput) {
3302
3301
  try {
3303
- const { toolNames } = input;
3302
+ const { toolNames } = DescribeToolsToolInputSchema.parse(rawInput);
3304
3303
  const serverDefinitions = await this.definitionsCacheService.getServerDefinitions();
3305
3304
  if (!toolNames || toolNames.length === 0) return {
3306
3305
  content: [{
@@ -3474,6 +3473,10 @@ function getUniqueSortedCapabilities(tools) {
3474
3473
 
3475
3474
  //#endregion
3476
3475
  //#region src/tools/SearchListToolsTool.ts
3476
+ const SearchListToolsToolInputSchema = zod.z.object({
3477
+ capability: zod.z.string().optional().describe("Optional capability filter. Matches explicit capability tags first, then server summaries, server names, tool names, and tool descriptions."),
3478
+ serverName: zod.z.string().optional().describe("Optional server name filter.")
3479
+ });
3477
3480
  var SearchListToolsTool = class SearchListToolsTool {
3478
3481
  static TOOL_NAME = "list_tools";
3479
3482
  constructor(_clientManager, definitionsCacheService) {
@@ -3483,6 +3486,9 @@ var SearchListToolsTool = class SearchListToolsTool {
3483
3486
  formatToolName(toolName, serverName, toolToServers) {
3484
3487
  return (toolToServers.get(toolName) || []).length > 1 ? `${serverName}__${toolName}` : toolName;
3485
3488
  }
3489
+ getInputSchema() {
3490
+ return SearchListToolsToolInputSchema;
3491
+ }
3486
3492
  async getDefinition() {
3487
3493
  const serverDefinitions = await this.definitionsCacheService.getServerDefinitions();
3488
3494
  const capabilitySummary = serverDefinitions.length > 0 ? serverDefinitions.map((server) => {
@@ -3493,23 +3499,11 @@ var SearchListToolsTool = class SearchListToolsTool {
3493
3499
  return {
3494
3500
  name: SearchListToolsTool.TOOL_NAME,
3495
3501
  description: `Search proxied MCP tools by server capability summary.\n\nAvailable capabilities:\n${capabilitySummary}`,
3496
- inputSchema: {
3497
- type: "object",
3498
- properties: {
3499
- capability: {
3500
- type: "string",
3501
- description: "Optional capability filter. Matches explicit capability tags first, then server summaries, server names, tool names, and tool descriptions."
3502
- },
3503
- serverName: {
3504
- type: "string",
3505
- description: "Optional server name filter."
3506
- }
3507
- },
3508
- additionalProperties: false
3509
- }
3502
+ inputSchema: zod.z.toJSONSchema(SearchListToolsToolInputSchema, { reused: "inline" })
3510
3503
  };
3511
3504
  }
3512
- async execute(input) {
3505
+ async execute(rawInput) {
3506
+ const input = SearchListToolsToolInputSchema.parse(rawInput);
3513
3507
  const serverDefinitions = await this.definitionsCacheService.getServerDefinitions();
3514
3508
  const capabilityFilter = input.capability?.trim().toLowerCase();
3515
3509
  const serverNameFilter = input.serverName?.trim().toLowerCase();
@@ -3552,6 +3546,39 @@ var SearchListToolsTool = class SearchListToolsTool {
3552
3546
  //#endregion
3553
3547
  //#region src/tools/UseToolTool.ts
3554
3548
  /**
3549
+ * UseToolTool - Progressive disclosure tool for calling MCP tools and skills
3550
+ *
3551
+ * DESIGN PATTERNS:
3552
+ * - Tool pattern with getDefinition() and execute() methods
3553
+ * - Dependency injection for client manager and skill service
3554
+ * - Progressive disclosure pattern
3555
+ * - Proxy pattern for forwarding tool calls
3556
+ *
3557
+ * CODING STANDARDS:
3558
+ * - Implement Tool interface from ../types
3559
+ * - Use TOOL_NAME constant with snake_case
3560
+ * - Return CallToolResult with content array
3561
+ * - Handle errors with isError flag
3562
+ *
3563
+ * AVOID:
3564
+ * - Complex business logic in execute method
3565
+ * - Unhandled promise rejections
3566
+ * - Missing error handling
3567
+ *
3568
+ * NAMING CONVENTIONS:
3569
+ * - Tools from MCP servers use serverName__toolName format when clashing
3570
+ * - Skills use skill__skillName format (skill__ prefix)
3571
+ */
3572
+ /**
3573
+ * Input schema for UseToolTool
3574
+ * @property toolName - Name of the tool or skill to execute
3575
+ * @property toolArgs - Arguments to pass to the tool (from describe_tools schema)
3576
+ */
3577
+ const UseToolToolInputSchema = zod.z.object({
3578
+ toolName: zod.z.string().min(1).describe("Name of the tool to execute"),
3579
+ toolArgs: zod.z.record(zod.z.string(), zod.z.unknown()).optional().describe("Arguments to pass to the tool, as discovered from describe_tools")
3580
+ });
3581
+ /**
3555
3582
  * UseToolTool executes MCP tools and skills with proper error handling.
3556
3583
  *
3557
3584
  * This tool supports three invocation patterns:
@@ -3591,6 +3618,9 @@ var UseToolTool = class UseToolTool {
3591
3618
  *
3592
3619
  * @returns The tool definition conforming to MCP spec
3593
3620
  */
3621
+ getInputSchema() {
3622
+ return UseToolToolInputSchema;
3623
+ }
3594
3624
  getDefinition() {
3595
3625
  return {
3596
3626
  name: UseToolTool.TOOL_NAME,
@@ -3600,22 +3630,7 @@ var UseToolTool = class UseToolTool {
3600
3630
 
3601
3631
  IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverId}".
3602
3632
  `,
3603
- inputSchema: {
3604
- type: "object",
3605
- properties: {
3606
- toolName: {
3607
- type: "string",
3608
- description: "Name of the tool to execute",
3609
- minLength: 1
3610
- },
3611
- toolArgs: {
3612
- type: "object",
3613
- description: "Arguments to pass to the tool, as discovered from describe_tools"
3614
- }
3615
- },
3616
- required: ["toolName"],
3617
- additionalProperties: false
3618
- }
3633
+ inputSchema: zod.z.toJSONSchema(UseToolToolInputSchema, { reused: "inline" })
3619
3634
  };
3620
3635
  }
3621
3636
  /**
@@ -3628,6 +3643,16 @@ IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverI
3628
3643
  * @param skill - The skill that was requested
3629
3644
  * @returns CallToolResult with guidance message
3630
3645
  */
3646
+ /**
3647
+ * Coerce toolArgs using the downstream tool's cached JSON Schema.
3648
+ * Converts the schema to Zod and runs coerceArgs so that string-encoded
3649
+ * objects/arrays are parsed before being forwarded to the downstream server.
3650
+ */
3651
+ async coerceToolArgs(serverName, toolName, toolArgs) {
3652
+ const jsonSchema = await this.definitionsCacheService.getToolSchema(serverName, toolName);
3653
+ if (!jsonSchema) return toolArgs;
3654
+ return (0, __agimon_ai_foundation_validator.coerceArgs)(toolArgs, (0, __agimon_ai_foundation_validator.jsonSchemaToZod)(jsonSchema));
3655
+ }
3631
3656
  executeSkill(skill) {
3632
3657
  return { content: [{
3633
3658
  type: "text",
@@ -3673,9 +3698,9 @@ IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverI
3673
3698
  * @param input - The tool/skill name and optional arguments
3674
3699
  * @returns CallToolResult with execution output or error
3675
3700
  */
3676
- async execute(input) {
3701
+ async execute(rawInput) {
3677
3702
  try {
3678
- const { toolName: inputToolName, toolArgs = {} } = input;
3703
+ const { toolName: inputToolName, toolArgs = {} } = UseToolToolInputSchema.parse(rawInput);
3679
3704
  if (inputToolName.startsWith(SKILL_PREFIX)) {
3680
3705
  const skillName = inputToolName.slice(SKILL_PREFIX.length);
3681
3706
  if (this.skillService) {
@@ -3704,7 +3729,8 @@ IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverI
3704
3729
  isError: true
3705
3730
  };
3706
3731
  const reqTimeout = this.clientManager.getServerRequestTimeout(serverName);
3707
- return await client.callTool(actualToolName, toolArgs, reqTimeout ? { timeout: reqTimeout } : void 0);
3732
+ const coercedArgs = await this.coerceToolArgs(serverName, actualToolName, toolArgs);
3733
+ return await client.callTool(actualToolName, coercedArgs, reqTimeout ? { timeout: reqTimeout } : void 0);
3708
3734
  } catch (error) {
3709
3735
  return {
3710
3736
  content: [{
@@ -3741,7 +3767,8 @@ IMPORTANT: Only use tools discovered from describe_tools with id="${this.serverI
3741
3767
  const targetServerName = matchingServers[0];
3742
3768
  const client = await this.clientManager.ensureConnected(targetServerName);
3743
3769
  const targetReqTimeout = this.clientManager.getServerRequestTimeout(targetServerName);
3744
- return await client.callTool(actualToolName, toolArgs, targetReqTimeout ? { timeout: targetReqTimeout } : void 0);
3770
+ const coercedArgs = await this.coerceToolArgs(targetServerName, actualToolName, toolArgs);
3771
+ return await client.callTool(actualToolName, coercedArgs, targetReqTimeout ? { timeout: targetReqTimeout } : void 0);
3745
3772
  } catch (error) {
3746
3773
  return {
3747
3774
  content: [{
@@ -4422,19 +4449,38 @@ var StdioTransportHandler = class {
4422
4449
  * - Transport handler pattern implementing TransportHandler interface
4423
4450
  * - STDIO transport with MCP request forwarding to HTTP backend
4424
4451
  * - Graceful cleanup with error isolation
4452
+ * - Reconnection with exponential backoff on connection loss
4425
4453
  *
4426
4454
  * CODING STANDARDS:
4427
4455
  * - Use StdioServerTransport for stdio communication
4428
4456
  * - Reuse a single StreamableHTTP client connection
4429
4457
  * - Wrap async operations with try-catch and descriptive errors
4458
+ * - Reconnect transparently on connection reset
4430
4459
  *
4431
4460
  * AVOID:
4432
4461
  * - Starting HTTP server lifecycle in this transport entry point
4433
4462
  * - Recreating HTTP client per request
4434
4463
  * - Swallowing cleanup failures silently
4435
4464
  */
4465
+ const CONNECTION_ERROR_PATTERNS = [
4466
+ "econnrefused",
4467
+ "econnreset",
4468
+ "enotfound",
4469
+ "connection refused",
4470
+ "fetch failed",
4471
+ "socket hang up",
4472
+ "network error",
4473
+ "failed to fetch"
4474
+ ];
4475
+ function isConnectionError(error) {
4476
+ if (!(error instanceof Error)) return false;
4477
+ const message = error.message.toLowerCase();
4478
+ return CONNECTION_ERROR_PATTERNS.some((pattern) => message.includes(pattern));
4479
+ }
4436
4480
  /**
4437
4481
  * Transport that serves MCP over stdio and forwards MCP requests to an HTTP endpoint.
4482
+ * Automatically reconnects to the HTTP backend with exponential backoff when the
4483
+ * connection is lost (e.g. backend crash + restart).
4438
4484
  */
4439
4485
  var StdioHttpTransportHandler = class {
4440
4486
  endpoint;
@@ -4442,24 +4488,19 @@ var StdioHttpTransportHandler = class {
4442
4488
  stdioTransport = null;
4443
4489
  httpClient = null;
4444
4490
  logger;
4491
+ MAX_RECONNECT_ATTEMPTS = 5;
4492
+ RECONNECT_BASE_MS = 1e3;
4493
+ RECONNECT_MAX_MS = 3e4;
4445
4494
  constructor(config, logger = console) {
4446
4495
  this.endpoint = config.endpoint;
4447
4496
  this.logger = logger;
4448
4497
  }
4449
4498
  async start() {
4450
4499
  try {
4451
- const httpClientTransport = new __modelcontextprotocol_sdk_client_streamableHttp_js.StreamableHTTPClientTransport(this.endpoint);
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);
4500
+ const client = await this.createAndConnectClient();
4457
4501
  this.httpClient = client;
4458
- this.stdioProxyServer = this.createProxyServer(client);
4459
- const proxyServer = this.stdioProxyServer;
4460
- client.setRequestHandler(__modelcontextprotocol_sdk_types_js.ElicitRequestSchema, async (request) => {
4461
- return await proxyServer.elicitInput(request.params);
4462
- });
4502
+ this.stdioProxyServer = this.createProxyServer();
4503
+ this.registerElicitationHandler(client);
4463
4504
  this.stdioTransport = new __modelcontextprotocol_sdk_server_stdio_js.StdioServerTransport();
4464
4505
  await this.stdioProxyServer.connect(this.stdioTransport);
4465
4506
  this.logger.info(`@agimon-ai/mcp-proxy MCP stdio proxy connected to ${this.endpoint.toString()}`);
@@ -4501,7 +4542,52 @@ var StdioHttpTransportHandler = class {
4501
4542
  ]);
4502
4543
  if (cleanupErrors.length > 0) throw new Error(`Failed to stop stdio-http proxy transport: ${cleanupErrors.join("; ")}`);
4503
4544
  }
4504
- createProxyServer(client) {
4545
+ async createAndConnectClient() {
4546
+ const httpClientTransport = new __modelcontextprotocol_sdk_client_streamableHttp_js.StreamableHTTPClientTransport(this.endpoint);
4547
+ const client = new __modelcontextprotocol_sdk_client_index_js.Client({
4548
+ name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
4549
+ version: "0.1.0"
4550
+ }, { capabilities: { elicitation: {} } });
4551
+ await client.connect(httpClientTransport);
4552
+ return client;
4553
+ }
4554
+ registerElicitationHandler(client) {
4555
+ const proxyServer = this.stdioProxyServer;
4556
+ if (!proxyServer) return;
4557
+ client.setRequestHandler(__modelcontextprotocol_sdk_types_js.ElicitRequestSchema, async (request) => {
4558
+ return await proxyServer.elicitInput(request.params);
4559
+ });
4560
+ }
4561
+ async reconnectWithBackoff() {
4562
+ for (let attempt = 0; attempt < this.MAX_RECONNECT_ATTEMPTS; attempt++) {
4563
+ const delay = Math.min(this.RECONNECT_BASE_MS * 2 ** attempt, this.RECONNECT_MAX_MS);
4564
+ await new Promise((resolve$2) => setTimeout(resolve$2, delay));
4565
+ try {
4566
+ await this.httpClient?.close().catch(() => void 0);
4567
+ const client = await this.createAndConnectClient();
4568
+ this.httpClient = client;
4569
+ this.registerElicitationHandler(client);
4570
+ this.logger.info(`Reconnected to HTTP backend at ${this.endpoint.toString()} (attempt ${attempt + 1})`);
4571
+ return;
4572
+ } catch {
4573
+ this.logger.info(`Reconnect attempt ${attempt + 1}/${this.MAX_RECONNECT_ATTEMPTS} to ${this.endpoint.toString()} failed`);
4574
+ }
4575
+ }
4576
+ throw new Error(`Failed to reconnect to HTTP backend at ${this.endpoint.toString()} after ${this.MAX_RECONNECT_ATTEMPTS} attempts`);
4577
+ }
4578
+ async withReconnect(fn) {
4579
+ if (!this.httpClient) throw new Error("HTTP client not connected");
4580
+ try {
4581
+ return await fn();
4582
+ } catch (error) {
4583
+ if (isConnectionError(error)) {
4584
+ await this.reconnectWithBackoff();
4585
+ return await fn();
4586
+ }
4587
+ throw error;
4588
+ }
4589
+ }
4590
+ createProxyServer() {
4505
4591
  const proxyServer = new __modelcontextprotocol_sdk_server_index_js.Server({
4506
4592
  name: "@agimon-ai/mcp-proxy-stdio-http-proxy",
4507
4593
  version: "0.1.0"
@@ -4512,48 +4598,48 @@ var StdioHttpTransportHandler = class {
4512
4598
  } });
4513
4599
  proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListToolsRequestSchema, async () => {
4514
4600
  try {
4515
- return await client.listTools();
4601
+ return await this.withReconnect(() => this.httpClient.listTools());
4516
4602
  } catch (error) {
4517
4603
  throw new Error(`Failed forwarding tools/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
4518
4604
  }
4519
4605
  });
4520
4606
  proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => {
4521
4607
  try {
4522
- return await client.callTool({
4608
+ return await this.withReconnect(() => this.httpClient.callTool({
4523
4609
  name: request.params.name,
4524
4610
  arguments: request.params.arguments
4525
- });
4611
+ }));
4526
4612
  } catch (error) {
4527
4613
  throw new Error(`Failed forwarding tools/call (${request.params.name}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
4528
4614
  }
4529
4615
  });
4530
4616
  proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListResourcesRequestSchema, async () => {
4531
4617
  try {
4532
- return await client.listResources();
4618
+ return await this.withReconnect(() => this.httpClient.listResources());
4533
4619
  } catch (error) {
4534
4620
  throw new Error(`Failed forwarding resources/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
4535
4621
  }
4536
4622
  });
4537
4623
  proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ReadResourceRequestSchema, async (request) => {
4538
4624
  try {
4539
- return await client.readResource({ uri: request.params.uri });
4625
+ return await this.withReconnect(() => this.httpClient.readResource({ uri: request.params.uri }));
4540
4626
  } catch (error) {
4541
4627
  throw new Error(`Failed forwarding resources/read (${request.params.uri}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
4542
4628
  }
4543
4629
  });
4544
4630
  proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.ListPromptsRequestSchema, async () => {
4545
4631
  try {
4546
- return await client.listPrompts();
4632
+ return await this.withReconnect(() => this.httpClient.listPrompts());
4547
4633
  } catch (error) {
4548
4634
  throw new Error(`Failed forwarding prompts/list to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
4549
4635
  }
4550
4636
  });
4551
4637
  proxyServer.setRequestHandler(__modelcontextprotocol_sdk_types_js.GetPromptRequestSchema, async (request) => {
4552
4638
  try {
4553
- return await client.getPrompt({
4639
+ return await this.withReconnect(() => this.httpClient.getPrompt({
4554
4640
  name: request.params.name,
4555
4641
  arguments: request.params.arguments
4556
- });
4642
+ }));
4557
4643
  } catch (error) {
4558
4644
  throw new Error(`Failed forwarding prompts/get (${request.params.name}) to HTTP backend: ${error instanceof Error ? error.message : String(error)}`);
4559
4645
  }
@@ -4916,21 +5002,27 @@ async function createSessionServer(shared) {
4916
5002
  })() : [await describeTools.getDefinition(), useToolWithCache.getDefinition()] }));
4917
5003
  server.setRequestHandler(__modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (request) => {
4918
5004
  const { name, arguments: args } = request.params;
4919
- if (name === DescribeToolsTool.TOOL_NAME) try {
4920
- return await describeTools.execute(args);
4921
- } catch (error) {
4922
- throw new Error(`Failed to execute ${name}: ${error instanceof Error ? error.message : String(error)}`);
4923
- }
4924
- if (name === UseToolTool.TOOL_NAME) try {
4925
- return await useToolWithCache.execute(args);
4926
- } catch (error) {
4927
- throw new Error(`Failed to execute ${name}: ${error instanceof Error ? error.message : String(error)}`);
4928
- }
4929
- if (name === SearchListToolsTool.TOOL_NAME && proxyMode === "search") try {
4930
- return await searchListTools.execute(args);
4931
- } catch (error) {
4932
- throw new Error(`Failed to execute ${name}: ${error instanceof Error ? error.message : String(error)}`);
4933
- }
5005
+ const executeWithCoercion = async (tool, toolName) => {
5006
+ const coerced = (0, __agimon_ai_foundation_validator.coerceArgs)(args ?? {}, tool.getInputSchema());
5007
+ try {
5008
+ return await tool.execute(coerced);
5009
+ } catch (error) {
5010
+ if (error instanceof zod.z.ZodError) return {
5011
+ content: [{
5012
+ type: "text",
5013
+ text: (0, __agimon_ai_foundation_validator.formatZodError)(error, {
5014
+ schemaName: toolName,
5015
+ schema: tool.getInputSchema()
5016
+ })
5017
+ }],
5018
+ isError: true
5019
+ };
5020
+ throw new Error(`Failed to execute ${toolName}: ${error instanceof Error ? error.message : String(error)}`);
5021
+ }
5022
+ };
5023
+ if (name === DescribeToolsTool.TOOL_NAME) return await executeWithCoercion(describeTools, name);
5024
+ if (name === UseToolTool.TOOL_NAME) return await executeWithCoercion(useToolWithCache, name);
5025
+ if (name === SearchListToolsTool.TOOL_NAME && proxyMode === "search") return await executeWithCoercion(searchListTools, name);
4934
5026
  if (proxyMode === "flat") return await useToolWithCache.execute({
4935
5027
  toolName: name,
4936
5028
  toolArgs: args || {}