Skip to content

MCP: "Failed to get tools" when a tool inputSchema contains a boolean sub-schema in properties #49464

Closed as not planned

Description

@tim-simmons

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 DEBUG

Observed

  • The server process starts, the initialize handshake completes, and tools/list returns 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

Expected

One of:

  1. Boolean sub-schemas in inputSchema/outputSchema properties are accepted (they are valid JSON Schema 2020-12), so the tools load; or
  2. A schema-processing failure on a single tool is skipped/downgraded and the remaining tools still load, with a visible warning; and
  3. 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

Plugins

None — reproduced with the server alone; MCP tools do not pass through tool.definition.

Activity

  1. thdxr commented on Oct 11, 2026

    @thdxr
    Member

    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 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions