feat(core): split MCP timeout configuration (#33977)

Co-authored-by: Test <test@opencode.test>
This commit is contained in:
opencode-agent[bot]
2026-06-25 20:31:00 -05:00
committed by GitHub
co-authored by Test
parent 17166b271f
commit f428755851
4 changed files with 41 additions and 20 deletions
+12 -3
View File
@@ -3,6 +3,15 @@ export * as ConfigMCP from "./mcp"
import { Schema } from "effect"
import { PositiveInt } from "../schema"
export class Timeout extends Schema.Class<Timeout>("ConfigV2.MCP.Timeout")({
startup: PositiveInt.pipe(Schema.optional).annotate({
description: "Maximum time in milliseconds to establish and initialize the MCP server.",
}),
request: PositiveInt.pipe(Schema.optional).annotate({
description: "Maximum time in milliseconds to wait for each MCP request after initialization.",
}),
}) {}
export class Local extends Schema.Class<Local>("ConfigV2.MCP.Local")({
type: Schema.Literal("local"),
command: Schema.String.pipe(Schema.Array),
@@ -11,7 +20,7 @@ export class Local extends Schema.Class<Local>("ConfigV2.MCP.Local")({
}),
environment: Schema.Record(Schema.String, Schema.String).pipe(Schema.optional),
disabled: Schema.Boolean.pipe(Schema.optional),
timeout: PositiveInt.pipe(Schema.optional),
timeout: Timeout.pipe(Schema.optional),
}) {}
export class OAuth extends Schema.Class<OAuth>("ConfigV2.MCP.OAuth")({
@@ -28,12 +37,12 @@ export class Remote extends Schema.Class<Remote>("ConfigV2.MCP.Remote")({
headers: Schema.Record(Schema.String, Schema.String).pipe(Schema.optional),
oauth: Schema.Union([OAuth, Schema.Literal(false)]).pipe(Schema.optional),
disabled: Schema.Boolean.pipe(Schema.optional),
timeout: PositiveInt.pipe(Schema.optional),
timeout: Timeout.pipe(Schema.optional),
}) {}
export const Server = Schema.Union([Local, Remote]).pipe(Schema.toTaggedUnion("type"))
export class Info extends Schema.Class<Info>("ConfigV2.MCP")({
timeout: PositiveInt.pipe(Schema.optional),
timeout: Timeout.pipe(Schema.optional),
servers: Schema.Record(Schema.String, Server).pipe(Schema.optional),
}) {}
+3 -3
View File
@@ -132,7 +132,7 @@ function mcp(info: typeof ConfigV1.Info.Type) {
)
const timeout = info.experimental?.mcp_timeout
if (!timeout && !Object.keys(servers).length) return undefined
return { timeout, servers }
return { timeout: timeout === undefined ? undefined : { request: timeout }, servers }
}
function migrateMcp(info: ConfigMCPV1.Info) {
@@ -144,7 +144,7 @@ function migrateMcp(info: ConfigMCPV1.Info) {
cwd: info.cwd,
environment: info.environment,
disabled,
timeout: info.timeout,
timeout: info.timeout === undefined ? undefined : { request: info.timeout },
}
return {
type: info.type,
@@ -158,7 +158,7 @@ function migrateMcp(info: ConfigMCPV1.Info) {
redirect_uri: info.oauth.redirectUri,
},
disabled,
timeout: info.timeout,
timeout: info.timeout === undefined ? undefined : { request: info.timeout },
}
}
+16 -7
View File
@@ -298,14 +298,14 @@ describe("Config", () => {
},
tool_output: { max_lines: 1000, max_bytes: 32768 },
mcp: {
timeout: 5000,
timeout: { startup: 5000, request: 60000 },
servers: {
local: {
type: "local",
command: ["node", "./mcp/server.js"],
environment: { API_KEY: "secret" },
disabled: false,
timeout: 10000,
timeout: { request: 10000 },
},
remote: {
type: "remote",
@@ -313,6 +313,7 @@ describe("Config", () => {
headers: { Authorization: "Bearer token" },
oauth: { client_id: "client", scope: "read write", callback_port: 19876 },
disabled: true,
timeout: { startup: 15000 },
},
},
},
@@ -383,14 +384,14 @@ describe("Config", () => {
})
expect(documents[0]?.info.tool_output).toEqual({ max_lines: 1000, max_bytes: 32768 })
expect(documents[0]?.info.mcp).toEqual({
timeout: 5000,
timeout: { startup: 5000, request: 60000 },
servers: {
local: {
type: "local",
command: ["node", "./mcp/server.js"],
environment: { API_KEY: "secret" },
disabled: false,
timeout: 10000,
timeout: { request: 10000 },
},
remote: {
type: "remote",
@@ -398,6 +399,7 @@ describe("Config", () => {
headers: { Authorization: "Bearer token" },
oauth: { client_id: "client", scope: "read write", callback_port: 19876 },
disabled: true,
timeout: { startup: 15000 },
},
},
})
@@ -541,11 +543,12 @@ describe("Config", () => {
compaction: { auto: true, tail_turns: 3, preserve_recent_tokens: 2000, reserved: 10000 },
experimental: { mcp_timeout: 5000 },
mcp: {
local: { type: "local", command: ["node", "server.js"], enabled: false },
local: { type: "local", command: ["node", "server.js"], enabled: false, timeout: 10000 },
remote: {
type: "remote",
url: "https://mcp.example.com",
oauth: { clientId: "client", callbackPort: 19876 },
timeout: 20000,
},
},
}),
@@ -623,13 +626,19 @@ describe("Config", () => {
buffer: 10000,
})
expect(documents[0]?.info.mcp).toMatchObject({
timeout: 5000,
timeout: { request: 5000 },
servers: {
local: { type: "local", command: ["node", "server.js"], disabled: true },
local: {
type: "local",
command: ["node", "server.js"],
disabled: true,
timeout: { request: 10000 },
},
remote: {
type: "remote",
url: "https://mcp.example.com",
oauth: { client_id: "client", callback_port: 19876 },
timeout: { request: 20000 },
},
},
})