opencode retries tools/list with outputSchema stripped when the SDK rejects one
Kind: idiosyncrasy · Status: current · Last verified: 2026-08-24 · Clients: opencode · Revisions: 2025-11-25
outputSchema arrived in 2025-06-18. The TypeScript SDK validates it, and a server whose outputSchema contains a $ref the validator cannot resolve makes the whole tools/list page fail — not just the offending tool.
opencode catches that and retries the same request against a tolerant result schema:
const TolerantListToolsResultSchema = ListToolsResultSchema.extend({
tools: ToolSchema.omit({ outputSchema: true }).array(),
})
The retry drops outputSchema from every tool on the page, not only the one that failed. Tools that had a valid output schema come back without it, so structured output is lost for the whole page whenever any tool on it has a schema the SDK dislikes.
The match is on error text
The fallback fires based on a regex over the error message:
/can't resolve reference|resolves to more than one schema|outputSchema|schema.*reference|reference.*schema/i
That is a guess about wording the SDK is under no obligation to keep. It fails in both directions. An SDK release that rephrases a resolution error stops matching, and tools/list fails outright for a server that used to work. In the other direction schema.*reference is loose enough to catch validation failures that have nothing to do with outputSchema, and the retry then silently returns tools whose input schemas were the actual problem.
Either way the client's behaviour is pinned to the phrasing of a dependency's error strings, which is not something a version pin protects.
Why this exists
The pressure is real. A server with one malformed outputSchema renders its entire tool catalog unusable to a strictly validating client, and the user sees a server that will not connect rather than a tool that will not validate. Retrying is a reasonable local fix.
The general version of the problem belongs upstream: tools/list validation is all-or-nothing when it could be per-tool, and a client wanting to skip one bad tool has to either drop a field for every tool or write its own parser. opencode chose the first. Whether the SDK should offer a per-tool degradation mode is worth raising there.
Sources
- packages/opencode/src/mcp/catalog.ts, listTools and isOutputSchemaValidationError, commit
7cde8329,packages/opencode/src/mcp/catalog.ts:14-16,143-165, 2026-08-24