Skip to content

Tool execution hard-limited to 120s due to AI SDK streamText default stepMs timeout #25509

@tanbro

Description

@tanbro

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:

The operation timed out.

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

  1. Configure experimental.mcp_timeout: 3600000 in opencode.jsonc
  2. Have an MCP server with a tool that takes >120 seconds (e.g., PDF ingestion with OCR)
  3. Run opencode and invoke the long-running MCP tool
  4. 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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions