Summary
All tool executions (bash, MCP, built-in tools) are hard-limited to 120 seconds, regardless of any timeout configuration. This is caused by the Vercel AI SDK's streamText() default timeout.stepMs value of 120000 (120s), which wraps the entire step including tool execution.
Root Cause
In packages/opencode/src/session/llm.ts, the streamText() call does not pass a timeout parameter:
return streamText({
// ... other params
// ⚠️ no `timeout` parameter
})
The AI SDK defaults timeout.stepMs to 120000ms, which means any tool execution exceeding 120 seconds will be killed with:
Why experimental.mcp_timeout doesn't help
OpenCode exposes experimental.mcp_timeout in config and passes it to the MCP SDK's callTool():
// packages/opencode/src/mcp/index.ts — convertMcpTool()
client.callTool(
{ name: mcpTool.name, arguments: args },
CallToolResultSchema,
{
resetTimeoutOnProgress: true,
timeout, // ← from experimental.mcp_timeout
},
)
However, this timeout is set on the inner MCP SDK layer. The outer AI SDK streamText timeout (stepMs: 120000) triggers first, making experimental.mcp_timeout completely ineffective for values > 120s.
Call chain
streamText(timeout defaults to { stepMs: 120000 })
└─ tool execution (bash, MCP, all tools)
└─ convertMcpTool() → callTool(timeout: experimental.mcp_timeout)
└─ MCP SDK setTimeout (never reached if stepMs fires first)
Steps to Reproduce
- Configure
experimental.mcp_timeout: 3600000 in opencode.jsonc
- Have an MCP server with a tool that takes >120 seconds (e.g., PDF ingestion with OCR)
- Run
opencode and invoke the long-running MCP tool
- After 120 seconds, the tool is killed with
The operation timed out.
Alternatively, with a simple bash test:
opencode run -m <model> "execute a python script that sleeps for 200 seconds"
After 120 seconds: bash tool terminated command after exceeding timeout 120000 ms
Expected Behavior
experimental.mcp_timeout (or a new config option) should control the effective tool execution timeout
- Long-running MCP tools (PDF parsing, OCR, etc.) should be able to run beyond 120 seconds
Suggested Fix
In packages/opencode/src/session/llm.ts, pass the timeout to streamText():
const toolTimeout = cfg.experimental?.mcp_timeout ?? 120_000
return streamText({
// ... existing params
timeout: { stepMs: toolTimeout },
})
Environment
- OpenCode: v1.14.31 (latest as of 2026-05-02)
- AI SDK: Vercel AI SDK (streamText)
- OS: Linux (Debian 13), Windows 11
Summary
All tool executions (bash, MCP, built-in tools) are hard-limited to 120 seconds, regardless of any timeout configuration. This is caused by the Vercel AI SDK's
streamText()defaulttimeout.stepMsvalue of120000(120s), which wraps the entire step including tool execution.Root Cause
In
packages/opencode/src/session/llm.ts, thestreamText()call does not pass atimeoutparameter:The AI SDK defaults
timeout.stepMsto120000ms, which means any tool execution exceeding 120 seconds will be killed with:Why
experimental.mcp_timeoutdoesn't helpOpenCode exposes
experimental.mcp_timeoutin config and passes it to the MCP SDK'scallTool():However, this timeout is set on the inner MCP SDK layer. The outer AI SDK
streamTexttimeout (stepMs: 120000) triggers first, makingexperimental.mcp_timeoutcompletely ineffective for values > 120s.Call chain
Steps to Reproduce
experimental.mcp_timeout: 3600000inopencode.jsoncopencodeand invoke the long-running MCP toolThe operation timed out.Alternatively, with a simple bash test:
After 120 seconds:
bash tool terminated command after exceeding timeout 120000 msExpected Behavior
experimental.mcp_timeout(or a new config option) should control the effective tool execution timeoutSuggested Fix
In
packages/opencode/src/session/llm.ts, pass the timeout tostreamText():Environment