Visitar URL original
`add_issue_comment`'s top-level `anyOf` (added in v1.10.0 / #3085) breaks Claude tool-use API compatibility · Issue #3126 · github/github-mcp-server · GitHub
Skip to content

add_issue_comment's top-level anyOf (added in v1.10.0 / #3085) breaks Claude tool-use API compatibility #3126

Description

@takasek

What's Wrong?

add_issue_comment's inputSchema gained a top-level anyOf in v1.10.0 (introduced by #3085, fixing #3048):

"inputSchema": {
  "anyOf": [
    { "required": ["body"] },
    { "required": ["reaction"] }
  ],
  "dependentSchemas": { ... },
  "properties": { ... },
  "required": ["owner", "repo", "issue_number"],
  "type": "object"
}

Anthropic's Claude tool-use API rejects any custom tool whose input_schema uses oneOf/allOf/anyOf at the top level:

API Error: 400 tools.N.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level

Since MCP clients typically send the entire tool list in one request, this single non-conformant schema causes the whole request to fail with a 400 — even if add_issue_comment itself is never invoked in that turn.

Who hits this

Clients that eagerly forward the full MCP tool list to the Claude Messages API without sanitizing schemas first. Concretely:

Interactive Claude Code sessions are generally unaffected because they defer full tool-schema loading via Tool Search (see anthropics/claude-code#64113 and #63436), but that mitigation does not apply to headless/CI/subagent invocations, so this is a real-world breaking regression for anyone running Claude-based automation against this server.

Suggested fix

Other tools in this same release already express "at least one of A or B" without a top-level combinator, by nesting under properties/dependentSchemas instead (e.g. issue_write, projects_write, update_issue_assignees, update_issue_labels, update_issue_type). Could add_issue_comment's validation be restructured the same way?

Version

v1.10.0 (regression from v1.9.0 — introduced by #3085). The change is on main, so the latest main is affected as well.

Related

Client-side (Claude Code) issues describing the same 400 mechanism and proposing schema sanitization before forwarding:

Activity

  1. SamMorrowDrums commented on Aug 20, 2026

    @SamMorrowDrums
    Collaborator

    Maintainer investigation: MCP schema era and provider compatibility

    We validated that this regression crosses two distinct compatibility boundaries.

    MCP specification history

    • Through protocol version 2025-11-25, Tool.inputSchema was structurally restricted to $schema, root type: "object", properties, and required.
    • SEP-2106, shipped in protocol version 2026-07-28, explicitly added arbitrary JSON Schema 2020-12 keywords including root anyOf, oneOf, and allOf alongside type: "object".
    • There is no published 2026-02-28 MCP protocol version; the relevant full-schema boundary is 2026-07-28.

    This means the v1.10.0 schema was valid for modern MCP 2026-07-28, but not representable by the legacy Tool envelope when serving negotiated versions through 2025-11-25.

    Not limited to Claude

    This is also a separate provider-adapter compatibility problem:

    So protocol-version handling alone would not fix a modern MCP client that forwards schemas to a narrower provider API.

    Fix

    #3127 restores a portable canonical schema:

    • removes root anyOf and dependentSchemas;
    • retains simple field constraints (minLength, reaction enum, positive integer comment_id);
    • keeps all cross-field and mutual-exclusion rules authoritative in the handler;
    • preserves every valid comment/reaction mode and returns explicit errors for invalid combinations;
    • does not mutate schemas at runtime;
    • adds a non-mutating inventory regression guard against root composition keywords.

    The patch is valid for legacy MCP clients, modern MCP clients, Claude-forwarding clients, and OpenAI-style provider adapters. The emitted schema is also 356 bytes / 85 tokens smaller than v1.10.0.

    A future client-specific schema transformation, if needed, should deep-clone/copy-on-write per inventory response and use explicit provider capabilities. Shared canonical schemas must never be mutated in place.

    Negotiation behavior in this server

    The GitHub MCP Server supports both 2025-11-25 and 2026-07-28, but tool schemas are canonical/static rather than rendered per negotiated protocol version. A client negotiating 2025-11-25 therefore received the same v1.10.0 root anyOf, even though that keyword was outside the legacy Tool.inputSchema envelope. A client negotiating 2026-07-28 received an MCP-valid SEP-2106 schema, but Claude's downstream tool-use subset still rejected it.

    The merged flat schema is consequently an intersection-safe representation for both supported MCP eras and the provider subset, without runtime version branching or shared-schema mutation.

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

Metadata

Metadata

Assignees

No one assigned

    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