From 3cc6c4dd7b1a34f03a43943afb9d16c9d0f4fcaa Mon Sep 17 00:00:00 2001 From: Shahzaib Date: Wed, 17 Jun 2026 16:11:10 +0500 Subject: [PATCH 1/3] docs: clarify two-layer MCP timeout config (#2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document that the MCP client (Claude Code) has its own tool-call timeout separate from agy's per-tool budget; if it's shorter, the client gives up with 'timed out waiting for response' while the agy session keeps running. Adds a 'Two timeout layers — align them' section with the per-server .mcp.json timeout example, the client >= agy rule, and an expected-latency note (~40-50s cold start) so users size client timeouts correctly. Closes #2 --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 9db1e66..da99e01 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,26 @@ Failovers are annotated in the response footer (`failover: : quota exhaus Each tool has its own default timeout sized to its job: `web_lookup` 120s, `deep_search` 180s, `analyze_files` / `adversarial_review` / `follow_up` 300s, `delegate` 600s. Setting `AGY_TIMEOUT` explicitly overrides all of them at once. To change a single tool, set `AGY_TIMEOUT_` instead (e.g. `AGY_TIMEOUT_DEEP_SEARCH=300`); a per-tool override takes precedence over the global `AGY_TIMEOUT` and the tool's default. The full set of per-tool variables is `AGY_TIMEOUT_ANALYZE_FILES`, `AGY_TIMEOUT_DEEP_SEARCH`, `AGY_TIMEOUT_WEB_LOOKUP`, `AGY_TIMEOUT_ADVERSARIAL_REVIEW`, `AGY_TIMEOUT_FOLLOW_UP`, and `AGY_TIMEOUT_DELEGATE`. The kill path escalates SIGTERM → SIGKILL across the whole process group, and the deadline fires even if agy's helper processes hold the output pipes open. Cancelling the tool call from the MCP client (e.g. pressing Esc in Claude Code) also kills the agy run instead of orphaning it. +**Two timeout layers — align them.** The timeouts above are the *agy-side* budget. Your MCP client (Claude Code) has its own, separate *tool-call* timeout, and if it is shorter than the agy budget the client gives up first — you'll see `Error: timed out waiting for response` (note: agy-bridge's own timeout reads `agy timed out after Ns` instead). The work is not lost: the agy session persists, so `follow_up` with the returned `session_id` retrieves the result. But the real fix is to make the client wait at least as long as agy. In Claude Code, set a per-server `timeout` (milliseconds) on the agy-bridge entry — it's scoped to this server only: + +```jsonc +// .mcp.json (or the mcpServers entry in ~/.claude.json) +{ + "mcpServers": { + "agy-bridge": { + "command": "npx", + "args": ["-y", "agy-bridge"], + "timeout": 600000, // client waits up to 10 min + "env": { "AGY_TIMEOUT_ANALYZE_FILES": "600" } // agy budget 10 min + } + } +} +``` + +Rule of thumb: **client `timeout` ≥ agy budget**. `MCP_TOOL_TIMEOUT` works as a global env-var equivalent if you prefer. + +**Expected latency.** Most of the perceived "slowness" is cold start: the first call in a session spawns the agy CLI and warms the model. A simple `analyze_files` over 3 files measures around **40–50s cold** (≈46s observed), dropping on subsequent same-session calls. A first call that also hits a quota 429 takes longer while the bridge fails over. So a client timeout below ~60s will intermittently trip on cold starts even for "simple" questions — size it generously. + ## Configuration All optional, via environment variables: From e84b0e6c5564f2ad86a9d5ca42cbfe503cbe8423 Mon Sep 17 00:00:00 2001 From: Shahzaib Date: Wed, 17 Jun 2026 16:29:34 +0500 Subject: [PATCH 2/3] docs: install with add-json so client timeout is set up front (#2) Switch the install command to 'claude mcp add-json' with a baked-in "timeout": 600000 so users get a 10-min client-side tool-call deadline at install time, instead of discovering it only after a timeout. Note the MCP_TOOL_TIMEOUT env fallback for clients that don't honor per-server timeout. --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index da99e01..683d9ad 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,23 @@ User → Claude Code → agy-bridge (MCP) → agy CLI → Gemini / Claude / GPT- ## Install ```bash -# 1. Register the MCP server (user scope = all projects) -claude mcp add -s user agy-bridge npx -- -y agy-bridge +# 1. Register the MCP server (user scope = all projects). +# add-json bakes in a generous client-side timeout so long analyze_files / +# delegate calls don't trip Claude Code's tool-call deadline (see Timeouts). +claude mcp add-json -s user agy-bridge \ + '{"command":"npx","args":["-y","agy-bridge"],"timeout":600000}' # 2. Add delegation rules to your project (or ~/.claude/CLAUDE.md for global) curl -o CLAUDE.md https://raw.githubusercontent.com/sshahzaiib/agy-bridge/main/CLAUDE.md ``` +> The `"timeout": 600000` (10 min, milliseconds) is the **client-side** tool-call +> deadline — without it, a cold-start `analyze_files` (~40–50s) or a long +> `delegate` can hit Claude Code's default and return `timed out waiting for +> response` while the agy run is still going. If your client doesn't honor a +> per-server `timeout`, set the global env var `MCP_TOOL_TIMEOUT=600000` instead. +> Details and the agy-side budgets are in [Timeouts and cancellation](#timeouts-and-cancellation). + ## Tools | Tool | Use for | Model routing (first available) | From f85eccdbb527ed7f0c98117a58c4e61360a3700c Mon Sep 17 00:00:00 2001 From: Shahzaib Date: Wed, 17 Jun 2026 16:30:33 +0500 Subject: [PATCH 3/3] docs: drop redundant config block, point to Install (#2) --- README.md | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/README.md b/README.md index 683d9ad..15f0ac3 100644 --- a/README.md +++ b/README.md @@ -91,23 +91,7 @@ Failovers are annotated in the response footer (`failover: : quota exhaus Each tool has its own default timeout sized to its job: `web_lookup` 120s, `deep_search` 180s, `analyze_files` / `adversarial_review` / `follow_up` 300s, `delegate` 600s. Setting `AGY_TIMEOUT` explicitly overrides all of them at once. To change a single tool, set `AGY_TIMEOUT_` instead (e.g. `AGY_TIMEOUT_DEEP_SEARCH=300`); a per-tool override takes precedence over the global `AGY_TIMEOUT` and the tool's default. The full set of per-tool variables is `AGY_TIMEOUT_ANALYZE_FILES`, `AGY_TIMEOUT_DEEP_SEARCH`, `AGY_TIMEOUT_WEB_LOOKUP`, `AGY_TIMEOUT_ADVERSARIAL_REVIEW`, `AGY_TIMEOUT_FOLLOW_UP`, and `AGY_TIMEOUT_DELEGATE`. The kill path escalates SIGTERM → SIGKILL across the whole process group, and the deadline fires even if agy's helper processes hold the output pipes open. Cancelling the tool call from the MCP client (e.g. pressing Esc in Claude Code) also kills the agy run instead of orphaning it. -**Two timeout layers — align them.** The timeouts above are the *agy-side* budget. Your MCP client (Claude Code) has its own, separate *tool-call* timeout, and if it is shorter than the agy budget the client gives up first — you'll see `Error: timed out waiting for response` (note: agy-bridge's own timeout reads `agy timed out after Ns` instead). The work is not lost: the agy session persists, so `follow_up` with the returned `session_id` retrieves the result. But the real fix is to make the client wait at least as long as agy. In Claude Code, set a per-server `timeout` (milliseconds) on the agy-bridge entry — it's scoped to this server only: - -```jsonc -// .mcp.json (or the mcpServers entry in ~/.claude.json) -{ - "mcpServers": { - "agy-bridge": { - "command": "npx", - "args": ["-y", "agy-bridge"], - "timeout": 600000, // client waits up to 10 min - "env": { "AGY_TIMEOUT_ANALYZE_FILES": "600" } // agy budget 10 min - } - } -} -``` - -Rule of thumb: **client `timeout` ≥ agy budget**. `MCP_TOOL_TIMEOUT` works as a global env-var equivalent if you prefer. +**Two timeout layers — align them.** The timeouts above are the *agy-side* budget. Your MCP client (Claude Code) has its own, separate *tool-call* timeout, and if it is shorter than the agy budget the client gives up first — you'll see `Error: timed out waiting for response` (note: agy-bridge's own timeout reads `agy timed out after Ns` instead). The work is not lost: the agy session persists, so `follow_up` with the returned `session_id` retrieves the result. But the real fix is to make the client wait at least as long as agy: the [Install](#install) command already sets a per-server `timeout` of 600000ms (scoped to the agy-bridge entry only). If you registered the server without it, re-run the `add-json` command from Install, or set the global env var `MCP_TOOL_TIMEOUT=600000`. Rule of thumb: **client `timeout` ≥ agy budget**. **Expected latency.** Most of the perceived "slowness" is cold start: the first call in a session spawns the agy CLI and warms the model. A simple `analyze_files` over 3 files measures around **40–50s cold** (≈46s observed), dropping on subsequent same-session calls. A first call that also hits a quota 429 takes longer while the bridge fails over. So a client timeout below ~60s will intermittently trip on cold starts even for "simple" questions — size it generously.