1jehuang / 1jehuang/jcode

MCP: hardcoded 30s timeout on every request makes long-running tools impossible (same root cause as #617)

Open
#802 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

autonomous: no bug triage: needs-decision
Dominant language
Rust
Stars
19.9k
Forks
2.3k
Avg merge
2d 7h
Merged PRs (30d)
30

Description

Summary

Every MCP JSON-RPC request shares one hardcoded 30s timeout, including tools/call. There is no flag, config key, or mcp.json field to raise it, so any tool that legitimately takes longer than 30s can never succeed.

crates/jcode-base/src/mcp/client.rs:46 (at 02439b4):

let response = tokio::time::timeout(std::time::Duration::from_secs(30), rx)
    .await
    .context("Request timeout")?

request() is the single path used by initialize (client.rs:301), tools/list (client.rs:103) and tools/call (client.rs:71), so the same 30s covers server startup and long-running tool work alike.

I believe this is also the root cause of #617 — a slow-starting server blows the same budget during initialize.

Reproduction

Minimal MCP server (slow_mcp.py, needs pip install mcp):

import time
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("slowsrv")

@mcp.tool()
def slow_ping(seconds: int = 45) -> str:
    """Sleep then return a token."""
    time.sleep(seconds)
    return "SLOW-TOKEN-OK"

mcp.run()

.jcode/mcp.json:

{"mcpServers": {"slow": {"command": "python", "args": ["/abs/path/slow_mcp.py"], "env": {}}}}
jcode run 'Call slow_ping with seconds=45 exactly once, then report what it returned.'

Expected: the tool returns SLOW-TOKEN-OK after 45s.
Actual (0.68.0): the call fails at exactly 30s with Error: Request timeout, and the model reports the timeout instead of the result. I also tried timeout, timeout_ms, timeout_secs and tool_timeout_ms keys on the server entry in mcp.json — none are read.

Impact

I maintain a benchmark harness that drives Microsoft Word through an MCP server, where a single document edit routinely runs longer than 30s (the first call on a busy pool especially). Under jcode those calls come back as Request timeout and the model retries them; the work still completes, but every run burns turns and tokens on retries, and a slow enough backend can never finish at all. Anything else with real I/O behind it — builds, test suites, deploys, browser automation, remote APIs — has the same ceiling.

Suggestion

Two things would fix it, in rough priority order:

  1. Make the timeout configurable, and use a longer default for tools/call than for initialize/tools/list. Comparable clients all expose this: Claude Code has MCP_TIMEOUT / MCP_TOOL_TIMEOUT, VS Code and Cursor take a per-server timeout in mcp.json, goose and kimi-cli both have their own knobs. A per-server field in mcp.json plus a global default in config.toml would match what people already expect.
  2. Optionally, reset the deadline on MCP progress notifications — the spec allows implementations to do this so well-behaved long-running tools stay alive.

Happy to test a patch against the real workload if that helps. Environment: jcode 0.68.0 (installed via jcode.sh/install), Linux x86_64.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in crates/jcode-base/src/mcp/client.rs:46 and trace request() to initialize, tools/list, and tools/call at the referenced locations. Review how MCP server settings are loaded before choosing the configuration surface. Done means long-running tools can exceed the current 30-second limit while initialization and listing retain an appropriate timeout, with the existing reproduction succeeding.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.