From 66ae1313755fe0365a227eecb7c0a6b10923e0d4 Mon Sep 17 00:00:00 2001 From: Rodaddy Date: Mon, 30 Mar 2026 18:31:53 -0400 Subject: [PATCH] feat: add per-service timeout support to services.json Services can now specify a `timeout` field (ms) that overrides the global MCP2CLI_TOOL_TIMEOUT env var for tool call timeouts. Useful for slow backends like AppleScript-based MCP servers. Priority: per-service config > MCP2CLI_TOOL_TIMEOUT env > 30s default Co-Authored-By: Claude Opus 4.6 --- src/config/schema.ts | 2 ++ src/daemon/server.ts | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/config/schema.ts b/src/config/schema.ts index a2f36b1..23379fb 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -9,6 +9,8 @@ import { z } from "zod"; const accessControlFields = { allowTools: z.array(z.string()).optional(), blockTools: z.array(z.string()).optional(), + /** Per-service tool call timeout in milliseconds. Overrides MCP2CLI_TOOL_TIMEOUT env var. */ + timeout: z.number().int().positive().optional(), }; /** diff --git a/src/daemon/server.ts b/src/daemon/server.ts index d2d7a49..dd654f7 100644 --- a/src/daemon/server.ts +++ b/src/daemon/server.ts @@ -107,8 +107,11 @@ export function createDaemonServer(opts: DaemonServerOptions) { callTool = body.tool; const conn = await pool.getConnection(body.service, getConfig()); - // MEM-02: AbortSignal timeout on tool calls (default 30s, configurable) - const timeout = parseInt(process.env.MCP2CLI_TOOL_TIMEOUT ?? "30000", 10); + // MEM-02: AbortSignal timeout on tool calls + // Priority: per-service config > MCP2CLI_TOOL_TIMEOUT env > 30s default + const serviceConfig = getConfig().services[body.service]; + const perServiceTimeout = serviceConfig && "timeout" in serviceConfig ? serviceConfig.timeout : undefined; + const timeout = perServiceTimeout ?? parseInt(process.env.MCP2CLI_TOOL_TIMEOUT ?? "30000", 10); const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), timeout);