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
10c9a574121a, win32, Node v24.18.0- Case
tools.call.basic, definition hash45f8134078c9
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.
- #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": {} } } } } } - #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" } - #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": {} } } } } } - #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 } - #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_01289fiu9Mqhyotaw3aC84Xi" }, "name": "lab_echo", "arguments": { "token": "ncd427288cae854b3" } } } - #13 server to client: response
{ "result": { "content": [ { "type": "text", "text": "ncd427288cae854b3-ack TOOL-OK-6f75fe8e0583" } ], "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.
ncd427288cae854b3-ack TOOL-OK-6f75fe8e0583 ncd427288cae854b3-ack TOOL-OK-6f75fe8e0583
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