Skip to content

sanitize_tool_data() injects non-standard "type": "action" field, causing Claude Code to silently drop tools #137

@brigleb

Description

@brigleb

Summary

The ToolsHandler::sanitize_tool_data() method adds a "type": "action" field to every tool in the tools/list response. This field is not part of the MCP specification for Tools. Claude Code's strict schema validation silently drops tools with non-standard fields, resulting in only 1 of 3 built-in tools being available.

Current Behavior

In includes/Handlers/Tools/ToolsHandler.php line 223–227:

$safe_tool = array(
    'name'        => $tool['name'] ?? '',
    'description' => $tool['description'] ?? '',
    'type'        => $tool['type'] ?? 'action',  // ← not in MCP spec
);

This produces tool definitions like:

{
  "name": "mcp-adapter-execute-ability",
  "description": "Execute a WordPress ability...",
  "type": "action",
  ...
}

The MCP spec's Tool object only defines: name, description, inputSchema, title, outputSchema, annotations, and _meta. The type field is not among them.

Impact

Claude Code v2.0.21+ performs strict schema validation on MCP tool definitions before passing them to the Anthropic API. Tools with non-standard fields are silently dropped. In practice, this means 2 of 3 built-in tools (mcp-adapter-execute-ability and mcp-adapter-get-ability-info) are unavailable in Claude Code, while mcp-adapter-discover-abilities works (likely because its simpler schema passes validation despite the extra field).

This effectively makes the MCP adapter unusable from Claude Code — you can discover abilities but cannot execute them or get their info.

Related Claude Code issues:

  • #10858 — non-standard "strict" field caused identical silent tool dropping
  • #10606 — strict MCP schema validation introduced in v2.0.21

Steps to Reproduce

  1. Install WordPress 6.9 + MCP Adapter plugin + ACF Pro 6.8 (with AI enabled)
  2. Configure .mcp.json per the README for stdio transport
  3. Connect Claude Code to the MCP server
  4. Run mcp-adapter-discover-abilities — works
  5. Try to call mcp-adapter-execute-ability or mcp-adapter-get-ability-info — tool not found

Verify the server does register all 3 tools by querying directly:

echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | wp mcp-adapter serve --server=mcp-adapter-default-server --user=admin

Suggested Fix

Remove the 'type' line from sanitize_tool_data():

$safe_tool = array(
    'name'        => $tool['name'] ?? '',
    'description' => $tool['description'] ?? '',
);

Note that McpTool::to_array() (line 321) correctly omits type — the non-standard field is only introduced during sanitization.

Environment

  • MCP Adapter: 0.4.1
  • WordPress: 6.9 (beta)
  • ACF Pro: 6.8.0-beta2
  • Claude Code: 2.1.62
  • PHP: 8.x
  • macOS (Laravel Herd)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions