Walk me through what tools/list returns and when the host calls it.
`tools/list` is the discovery call run once per session per server after initialize. It returns an array of tool definitions (name, description, inputSchema). `tools/call` handles the actual invocation.
Imagine walking into a workshop for the first time. Before you can use any tools, you need to know what the workshop has. So you ask the foreman 'show me the toolbox.' The foreman hands you a list: 'here is a hammer, here is a screwdriver, here is a saw, and here is what each one does and what it needs.' That list is what `tools/list` returns in MCP. The host asks the server 'what tools do you have' and the server replies with a catalog. Later, when the model decides to use a tool, the host says 'use the hammer with this nail' and that is `tools/call`. Discover first, then call.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
tools/list is half of MCP's tool subsystem. It is the discovery call: the host asks the server 'what tools do you have,' the server replies with a catalog, and the host translates that catalog into whatever format the LLM expects so the model can choose from it. The other half, tools/call, handles invocation when the model picks one.
This explanation walks through the call itself, the response shape, the host workflow around it, and the traps that catch newcomers.
The call and its response shape
tools/list is a JSON-RPC request with method "tools/list" and typically no params. The server responds with {tools: [Tool, ...]} where each Tool is an object with three required fields.
name is a string that uniquely identifies the tool within the server. It is the value the client uses in subsequent tools/call requests. The server is responsible for ensuring uniqueness within itself; the host deals with cross server collisions on its own (typically by prefixing tool names with a server identifier).
description is a human readable string explaining what the tool does, when to use it, and what it returns. This is the most consequential field because it is the only documentation the LLM ever sees about the tool. The model uses the description to decide whether the tool is relevant to the current task. Vague or generic descriptions lead to wrong tool selection; clear, specific descriptions guide the model accurately.
inputSchema is a JSON Schema object describing the tool's arguments. It lists the properties, marks which are required, declares each property's type and any constraints (enums, formats, min/max), and ideally includes a per property description. The host uses this both to validate arguments before forwarding them and to feed the structured output mechanism of function calling.
Recent spec versions also allow an optional annotations object with hint flags: readOnlyHint (the tool does not modify state), destructiveHint (the tool can delete or overwrite), idempotentHint (calling twice gives the same result as once), openWorldHint (the tool reaches out to external systems). Hosts can use these to drive confirmation UI: a destructive tool gets an 'are you sure' prompt while a read only tool runs without confirmation.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- Claude Desktop calls `tools/list` against each configured MCP server at session start, merges the results with server prefixed names, and injects them into Anthropic's tools parameter for every Claude inference request.
- Cursor and VS Code Copilot Agents follow the same pattern: discover tools at startup, translate to the underlying LLM's tool schema, and refresh on `notifications/tools/list_changed`.
What an interviewer would ask next. Try answering before peeking at the approach.
QWhat happens if the server's tool list changes mid session?
If the server advertised tools.listChanged: true during initialize, it emits notifications/tools/list_changed when the list changes. The host refetches via tools/list and re injects the updated catalog into the next model inference. Without the sub flag, the host assumes the list is immutable for the session.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Calling `tools/list` on every model turn. The host should call it once per session per server and cache the result. The server pushes `notifications/tools/list_changed` if the catalog ever changes mid session.
60 second bullets to scan on the way to the call.
Name the three fields in a tool definition:
name,description,inputSchemaState when the host calls
tools/list: once per session per server right after initialize
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.