Repository navigation
Description
Summary
OpenCode marks an entire MCP server as failed with "Failed to get tools" when any tool's inputSchema contains a boolean sub-schema inside properties (e.g. "properties": { "raw_input": true }). Boolean sub-schemas are valid JSON Schema (2020-12 permits true/false where a schema is expected), and the same server works in clients that tolerate them. A single such tool takes down every tool on the server.
This is the same failure path as #21591 / #26529 (a schema-processing error in listTools() collapsing to "Failed to get tools"), but a different trigger: those were outputSchema $refs and were fixed by the tolerant retry keyed off isOutputSchemaValidationError(). Boolean inputSchema sub-schemas are not covered by that retry.
Related: #47644 (the underlying error is discarded), #48196 (silent failure), and the same class in the MCP Python SDK surface types — modelcontextprotocol/python-sdk#3353 / PR #3354.
Steps to reproduce
repro-mcp.mjs — dependency-free stdio MCP server with one offending tool:
let buffer = "";
const send = (message) => process.stdout.write(JSON.stringify(message) + "\n");
process.stdin.on("data", (chunk) => {
buffer += chunk;
let newline;
while ((newline = buffer.indexOf("\n")) >= 0) {
const line = buffer.slice(0, newline).trim();
buffer = buffer.slice(newline + 1);
if (!line) continue;
const message = JSON.parse(line);
if (message.method === "initialize") {
send({ jsonrpc: "2.0", id: message.id, result: {
protocolVersion: "2024-11-05",
capabilities: { tools: {} },
serverInfo: { name: "repro", version: "1.0.0" },
}});
} else if (message.method === "tools/list") {
send({ jsonrpc: "2.0", id: message.id, result: { tools: [{
name: "read_everything",
description: "Example tool.",
inputSchema: {
type: "object",
additionalProperties: false,
properties: {
reason: { type: "string" },
raw_input: true, // <-- boolean sub-schema
input: {
type: "object",
properties: { input: true }, // <-- boolean sub-schema (nested)
},
},
},
}]}});
} else if (message.id !== undefined) {
send({ jsonrpc: "2.0", id: message.id, result: {} });
}
}
});opencode.json beside it:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"repro": { "type": "local", "command": ["node", "repro-mcp.mjs"], "enabled": true }
}
}Then:
opencode mcp list --print-logs --log-level DEBUGObserved
- The server process starts, the
initializehandshake completes, andtools/listreturns a valid response over stdio (verifiable with any raw MCP client). - OpenCode closes the connection and reports the whole server as failed:
● ✗ repro failed
│ Failed to get tools
│ node repro-mcp.mjs
- No underlying schema error is surfaced, even with
--print-logs --log-level DEBUG— only the constant"Failed to get tools"(MCP: every tool-list failure collapses to "Failed to get tools" — the underlying error is discarded #47644).
Expected
One of:
- Boolean sub-schemas in
inputSchema/outputSchemapropertiesare accepted (they are valid JSON Schema 2020-12), so the tools load; or - A schema-processing failure on a single tool is skipped/downgraded and the remaining tools still load, with a visible warning; and
- The real underlying error is surfaced instead of the constant string.
Workaround
Because MCP tool definitions skip the tool.definition hook (#46628), a plugin cannot fix this. The only user-space workaround is to proxy the server and rewrite the tools/list response — rewriting boolean sub-schemas (true -> {}, false -> {"not": {}}) and dropping outputSchema. I verified this against a real server with 45 tools carrying "raw_input": true: after sanitizing, opencode mcp list reports connected and all 45 tools are preserved.
Environment
- OpenCode version: 1.18.31
- OS: macOS (darwin) x86_64
- MCP transport: stdio (local), server protocol
2024-11-05 - Also reproduced against a Go-based stdio MCP server; the same class is reported for third-party servers against Claude Code ([BUG] MCP client silently drops all tools when third-party server includes outputSchema in tools/list response anthropics/claude-code#25081) and the MCP Python SDK (2025-11-25
Tool.inputSchema/outputSchemareject boolean sub-schemas inproperties, failing the wholetools/listmodelcontextprotocol/python-sdk#3353).
Plugins
None — reproduced with the server alone; MCP tools do not pass through tool.definition.
Activity
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊