GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — chatd: MCP tool input schemas lose `$schema`, so draft-07 schemas fail Anthropic 2020-12 validation and break every chat request · Issue #31363 · coder/coder

chatd: MCP tool input schemas lose $schema, so draft-07 schemas fail Anthropic 2020-12 validation and break every chat request #31363

New issue
Copy link
New issue
Copy link
Open
Bug
#31779
Open
chatd: MCP tool input schemas lose $schema, so draft-07 schemas fail Anthropic 2020-12 validation and break every chat request#31363
Bug
#31779
Copy link

Description

@bstephensStoke
bstephensStoke
opened on Oct 27, 2026
Issue body actions

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When an MCP server publishes a tool whose inputSchema is valid draft-07 but not valid draft 2020-12, every chat turn in a Coder Agents session that has that server enabled fails with HTTP 400:

    tools.N.custom.input_schema: JSON schema is invalid. It must match JSON Schema draft 2020-12

The same MCP server and the same tool list work in Anthropic's Claude Code CLI against the same model on Bedrock. Claude Code forwards the server's inputSchema as-is, including "$schema": "http://json-schema.org/draft-07/schema#", and Bedrock accepts it. Coder rebuilds the schema without $schema, so Bedrock validates it as 2020-12 and rejects the draft-07-only construct (tuple-form items: [...]).

The request path is chatd → coder-aibridge → Bedrock /v1/messages. As of #23538, buildToolDefinitions() in coderd/x/chatd/chatloop/chatloop.go built the provider schema from ToolInfo.Parameters and ToolInfo.Required only:

    inputSchema := map[string]any{
        "type":       "object",
        "properties": info.Parameters,
    }
    if len(info.Required) > 0 {
        inputSchema["required"] = info.Required
    }
    schema.Normalize(inputSchema)

so $schema (and other root keywords such as $defs) never reach the provider. That function seems to have moved since then, and I haven't ruled out aibridge also rewriting the schema, but the behavior reproduces on v2.38.1.

One invalid tool fails the entire request, so every user with that MCP server enabled loses chat completely, not just that one tool.

Relevant Log Output

[warn]  coderd.ai-gateway.pool: interception failed  route=/v1/messages  provider=bedrock  user_agent="coder-agents/v2.38.1+1ab0cd7 (linux/amd64)"  streaming=true  credential_kind=centralized  error="POST \"https://bedrock-runtime.us-gov-west-1.amazonaws.com/v1/messages\": 400 Bad Request {\"message\":\"tools.52.custom.input_schema: JSON schema is invalid. It must match JSON Schema draft 2020-12 (https://json-schema.org/draft/2020-12). Learn more about tool use at https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview.\"}"  error_type=bad_request
             - bad request: POST "http://coder-aibridge/v1/messages": 400 Bad Request {"error":{"message":"POST \"https://bedrock-runtime.us-gov-west-1.amazonaws.com/v1/messages\": 400 Bad Request {\"message\":\"tools.52.custom.input_schema: JSON schema is invalid. It must match JSON Schema draft 2020-12 (https://json-schema.org/draft/2020-12). ...\"}","type":"api_error"},"request_id":"","type":"error"}

Expected Behavior

A tool schema the MCP server declares as draft-07 reaches the provider in a form it accepts: either with its $schema intact, or normalised to an equivalent 2020-12 schema. At minimum, one bad tool should not fail every request: it should be dropped or quarantined with a visible warning.

Steps to Reproduce

  1. Run an MCP server built with @modelcontextprotocol/sdk (TypeScript, 1.31.x) and zod 4 that registers a tool with a tuple argument:
       server.registerTool('example', {
         inputSchema: { range: z.tuple([z.number(), z.number()]).optional() },
       }, handler)

The SDK serialises this as draft-07:

       {"$schema":"http://json-schema.org/draft-07/schema#","type":"object",
        "properties":{"range":{"type":"array","items":[{"type":"number"},{"type":"number"}]}}}
  1. Add the server to Coder Agents with an Anthropic model on Bedrock.
  2. Send any chat message. It fails with the 400 above (N = that tool's index in the combined tool list).

Sending the same tool to Claude on Bedrock outside Coder (Anthropic Messages format):

input_schema sent Result
As published ($schema: draft-07 present) 200
$schema removed (what Coder sends) 400, same error
$schema removed, items: [...] → items: {...}, minItems: 2, maxItems: 2 200

Environment

  • Host OS: Ubuntu 22.04
  • Coder version: v2.38.1+1ab0cd7
  • Provider: Anthropic Claude on AWS Bedrock (GovCloud), configured directly in Coder (centralized AWS credentials via ai-gateway)

Additional Context

The issue occurs consistently

Reacted by Matt

Activity

  1. bstephensStoke
    added the
    Bug
    issue type on Oct 27, 2026
  2. linear-code commented on Oct 27, 2026

    @linear-code
    linear-codeBot
    on Oct 27, 2026 – with Linear Code
    More actions

    ENG-3487

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

    Bug

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.