Skip to content

fix(core): accept numeric MCP timeouts - #55851

Merged
rekram1-node merged 2 commits into
devfrom
mcp-numeric-timeout
Oct 15, 2026
Merged

rekram1-node merged 2 commits into
devfrom
mcp-numeric-timeout

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #50807
Fixes #54184
Related: #55419

A numeric timeout on a server under mcp.servers (e.g. "timeout": 60000, the V1 form) failed schema decoding, so the whole server was silently dropped. The only trace was a skipped malformed recognized value warning in the log.

A bare-number timeout on a server or on the global mcp.timeout now expands to { startup, catalog, execution }:

Where Before After
mcp.servers.<name>.timeout: n Server dropped { startup: n, catalog: n, execution: n }
mcp.timeout: n (global) Ignored, logged as invalid Same expansion
Flat V1 mcp.<name>.timeout: n { catalog, execution } Adds startup, matching V1, where this timeout also bounded connecting
experimental.mcp_timeout: n { catalog, execution } Unchanged; V1 never applied it to connecting

The object form is unchanged and remains the documented shape. Invalid numbers (e.g. -1) still fail decoding for that server.

This builds on @dajiaohuang's #50810, which targeted the since-removed packages/opencode V2 compat layer. It's credited as co-author. #54174 overlaps with the flat V1 migration part.

Tests

  • packages/core: bun test test/config test/v1 (267 pass), bun typecheck.

A bare number timeout under mcp.servers dropped the whole server. Numeric
timeouts now expand to startup, catalog, and execution everywhere: per
server, the global mcp.timeout, experimental.mcp_timeout, and V1 entries.

Co-authored-by: dajiaohuang <[email protected]>

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I ran the same config through ConfigNormalize.normalize on the base and on this branch. On the base, a server with "timeout": 60000 under mcp.servers is dropped, and a numeric mcp.timeout is ignored. With this change both expand to { startup, catalog, execution }, object-form timeouts are unchanged, and -1 is still rejected for that server. In packages/core, the config and v1 tests pass (267) and typecheck is clean.

Public API: config only, backwards compatible.

  • mcp.servers.<name>.timeout and mcp.timeout now also accept a positive integer, expanded to all three phases.
  • Flat V1 mcp.<name>.timeout and experimental.mcp_timeout now also set timeout.startup. Existing configs keep loading. The difference is that a numeric value now replaces the 30s startup default.

This also covers #54184. PR #54174 overlaps with the V1 migration part.

One point that doesn't block the merge is in an inline comment on experimental.mcp_timeout.

Fixes #54184
Related: #55419

Comment thread packages/core/src/config/normalize.ts Outdated
diagnostics,
)
if (value !== undefined) {
timeout.startup = value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In V1, experimental.mcp_timeout was only the fallback timeout for tool calls (callTool). It never applied to connecting. The per-server timeout did cover connect and listing tools, so adding startup there matches V1. For this global key, though, it means a user who set a small value (e.g. 5000) to cap tool calls now also gets a 5s connect budget instead of the 30s default, so slow-starting servers could begin failing. Is that intended? If not, consider leaving startup out for this key.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch: V1 used experimental.mcp_timeout only as the fallback for tool calls and listing (requestTimeout), never for connect. I dropped startup for this key in 8d2ee6b, so it maps to { catalog, execution } as before. Per-server numeric timeouts still set startup, which matches V1's connectTimeout = mcp.timeout.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked 8d2ee6b and it's correct. experimental.mcp_timeout now sets only catalog and execution (normalize.ts ~L260), so connecting keeps the 30s default. Per-server numeric timeouts still set startup, which matches V1's connectTimeout = mcp.timeout.

  • Tests: I ran bun test test/config test/v1 in packages/core on pr/head and all 267 passed. I used a separate worktree at /tmp/opencode/wt55851, because the shared repo/ checkout is still on 959d824. I didn't change anything in repo/.
  • PR description: one row is now out of date. The table still says experimental.mcp_timeout: n → "Adds startup". It should say it's unchanged ({ catalog, execution }). The "Public API" line in the bot section makes the same claim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant