Claude Code Tools test

Supportedall expectations observed.

Summary

Client
Claude Code 2.1.296
Feature
Tools (tools.call)
Tested
Protocol
2026-07-28 (modern era, observed on the wire)
How
Automated over stdio
Lab version
Not recorded (run before the lab's first commit), win32, Node v24.18.0
Case
tools.call.basic, definition hash 45f8134078c9

What was checked

  • client discovered the tool via tools/list (seen on the wire)
  • client called lab_echo with the run's nonce (seen on the wire)
  • the tool result was passed back to the model (seen in the client's output)

Protocol traffic

The opening exchange and each request the result depends on, with the lab server's reply, exactly as the server recorded them. Long payloads are truncated.

  1. #0 client to server: server/discover
    {
      "jsonrpc": "2.0",
      "id": "server-discover-probe-1",
      "method": "server/discover",
      "params": {
        "_meta": {
          "io.modelcontextprotocol/protocolVersion": "2026-07-28",
          "io.modelcontextprotocol/clientInfo": {
            "name": "claude-code",
            "title": "Claude Code",
            "version": "2.1.296",
            "description": "Anthropic's agentic coding tool",
            "websiteUrl": "https://claude.com/claude-code"
          },
          "io.modelcontextprotocol/clientCapabilities": {
            "roots": {
              "listChanged": true
            },
            "elicitation": {
              "form": {},
              "url": {}
            }
          }
        }
      }
    }
  2. #1 server to client: response
    {
      "result": {
        "supportedVersions": [
          "2026-07-28"
        ],
        "capabilities": {
          "tools": {
            "listChanged": true
          },
          "prompts": {
            "listChanged": true
          },
          "resources": {
            "listChanged": true
          }
        },
        "resultType": "complete",
        "ttlMs": 0,
        "cacheScope": "private",
        "_meta": {
          "io.modelcontextprotocol/serverInfo": {
            "name": "abw-mcp-lab",
            "version": "0.1.0"
          }
        }
      },
      "jsonrpc": "2.0",
      "id": "server-discover-probe-1"
    }
  3. #9 client to server: tools/list
    {
      "jsonrpc": "2.0",
      "id": 3,
      "method": "tools/list",
      "params": {
        "_meta": {
          "io.modelcontextprotocol/protocolVersion": "2026-07-28",
          "io.modelcontextprotocol/clientInfo": {
            "name": "claude-code",
            "title": "Claude Code",
            "version": "2.1.296",
            "description": "Anthropic's agentic coding tool",
            "websiteUrl": "https://claude.com/claude-code"
          },
          "io.modelcontextprotocol/clientCapabilities": {
            "roots": {
              "listChanged": true
            },
            "elicitation": {
              "form": {},
              "url": {}
            }
          }
        }
      }
    }
  4. #11 server to client: response
    {
      "result": {
        "tools": [
          {
            "name": "lab_echo",
            "description": "MCP lab fixture: echoes a token back with an acknowledgement.",
            "inputSchema": {
              "type": "object",
              "$schema": "https://json-schema.org/draft/2020-12/schema",
              "properties": {
                "token": {
                  "type": "string",
                  "description": "Token to echo"
                }
              },
              "required": [
                "token"
              ]
            }
          }
        ],
        "resultType": "complete",
        "ttlMs": 0,
        "cacheScope": "private",
        "_meta": {
          "io.modelcontextprotocol/serverInfo": {
            "name": "abw-mcp-lab",
            "version": "0.1.0"
          }
        }
      },
      "jsonrpc": "2.0",
      "id": 3
    }
  5. #12 client to server: tools/call
    {
      "jsonrpc": "2.0",
      "id": 4,
      "method": "tools/call",
      "params": {
        "_meta": {
          "progressToken": 4,
          "io.modelcontextprotocol/protocolVersion": "2026-07-28",
          "io.modelcontextprotocol/clientInfo": {
            "name": "claude-code",
            "title": "Claude Code",
            "version": "2.1.296",
            "description": "Anthropic's agentic coding tool",
            "websiteUrl": "https://claude.com/claude-code"
          },
          "io.modelcontextprotocol/clientCapabilities": {
            "roots": {
              "listChanged": true
            },
            "elicitation": {
              "form": {},
              "url": {}
            }
          },
          "claudecode/toolUseId": "toolu_01HJcK3SW2wVAgVU8NzBmHcw"
        },
        "name": "lab_echo",
        "arguments": {
          "token": "n4b7c47c4b6f21bf0"
        }
      }
    }
  6. #13 server to client: response
    {
      "result": {
        "content": [
          {
            "type": "text",
            "text": "n4b7c47c4b6f21bf0-ack TOOL-OK-914682de7ee0"
          }
        ],
        "resultType": "complete",
        "_meta": {
          "io.modelcontextprotocol/serverInfo": {
            "name": "abw-mcp-lab",
            "version": "0.1.0"
          }
        }
      },
      "jsonrpc": "2.0",
      "id": 4
    }

Client output

What the client's model said at the end of the run. Supporting evidence only; the status is decided by the traffic above.

n4b7c47c4b6f21bf0-ack TOOL-OK-914682de7ee0
n4b7c47c4b6f21bf0-ack TOOL-OK-914682de7ee0

Test definition

id: tools.call.basic
title: Client lists tools and calls one with arguments
feature: tools.call
specRevisions: [2025-11-25, 2026-07-28]
mode: automated
drive:
  claude-code:
    prompt: >-
      Use the lab_echo tool from the lab MCP server with token "{{nonce}}".
      Then reply with the tool's exact output and nothing else.
    allowedTools: [mcp__lab__lab_echo]
manual:
  instructions: >-
    Ask the client to call the lab_echo tool with token "{{nonce}}" and show its output.
    Check whether the reply contains TOOL-OK-{{marker}}.
expect:
  - id: listed
    kind: request
    description: client discovered the tool via tools/list
    method: tools/list
  - id: called
    kind: request
    description: client called lab_echo with the run's nonce
    method: tools/call
    match:
      params.name: lab_echo
      params.arguments.token: "{{nonce}}"
  - id: result-reached-model
    kind: output
    description: the tool result was passed back to the model
    contains: TOOL-OK-{{marker}}

{{nonce}} is replaced with a fresh random value for every run, and {{marker}} with a value derived from it that only the lab server knows. Why

© 2026 ABWaters. Thinking out loud.