The tools/list Method
Learn how to handle tools/list requests and return your available tools.
How Clients Discover Tools
When a client connects to your MCP server, one of the first things it does
(after initialization) is request a list of available tools. This is done
via the tools/list method.
Client Server
| |
|--- initialize ------------------> |
|<-- initialize response ---------- |
|--- notifications/initialized ---> |
| |
|--- tools/list ------------------> | <-- Client requests tools
|<-- list of tools ---------------- |
| |
The tools/list Request
The request is simple — it has no required parameters:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}
The tools/list method supports an optional cursor
parameter for pagination. This is useful if you have many tools, but most
servers can return all tools in a single response.
The tools/list Response
Your server must respond with a tools array containing all
available tool definitions:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "add",
"description": "Add two numbers together",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "number", "description": "First number"},
"b": {"type": "number", "description": "Second number"}
},
"required": ["a", "b"]
}
},
{
"name": "subtract",
"description": "Subtract the second number from the first",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "number", "description": "Number to subtract from"},
"b": {"type": "number", "description": "Number to subtract"}
},
"required": ["a", "b"]
}
}
]
}
}
Implementing tools/list in Python
Here's how to implement the tools/list handler in your MCP server:
"""
mcp_server.py - MCP server with tools/list implementation.
"""
import json
# Define your tools
TOOLS = [
{
"name": "add",
"description": "Add two numbers together and return the sum",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "number", "description": "First number"},
"b": {"type": "number", "description": "Second number"}
},
"required": ["a", "b"]
}
},
{
"name": "subtract",
"description": "Subtract the second number from the first",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "number", "description": "Number to subtract from"},
"b": {"type": "number", "description": "Number to subtract"}
},
"required": ["a", "b"]
}
},
{
"name": "multiply",
"description": "Multiply two numbers and return the product",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "number", "description": "First number"},
"b": {"type": "number", "description": "Second number"}
},
"required": ["a", "b"]
}
}
]
def handle_tools_list(request_id, params):
"""
Handle the tools/list method.
Args:
request_id: The JSON-RPC request ID
params: Request parameters (may contain cursor for pagination)
Returns:
JSON-RPC response with list of tools
"""
# For simple servers, ignore pagination and return all tools
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"tools": TOOLS
}
}
def handle_request(request):
"""Route incoming requests to the appropriate handler."""
method = request.get("method")
request_id = request.get("id")
params = request.get("params", {})
if method == "tools/list":
return handle_tools_list(request_id, params)
# ... handle other methods ...
# Method not found
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {
"code": -32601,
"message": f"Method not found: {method}"
}
}
Pagination Support (Optional)
If you have many tools, you can implement pagination using cursors:
import base64
def handle_tools_list_paginated(request_id, params):
"""
Handle tools/list with pagination support.
"""
PAGE_SIZE = 10
# Decode cursor to get starting index
cursor = params.get("cursor")
if cursor:
try:
start_index = int(base64.b64decode(cursor).decode())
except:
start_index = 0
else:
start_index = 0
# Get page of tools
end_index = start_index + PAGE_SIZE
page_tools = TOOLS[start_index:end_index]
# Create next cursor if there are more tools
next_cursor = None
if end_index < len(TOOLS):
next_cursor = base64.b64encode(str(end_index).encode()).decode()
result = {"tools": page_tools}
if next_cursor:
result["nextCursor"] = next_cursor
return {
"jsonrpc": "2.0",
"id": request_id,
"result": result
}
Most MCP servers have fewer than 100 tools. Unless you're building a server with many tools, you can skip pagination and return all tools in a single response.
Testing tools/list
You can test your implementation with curl:
curl -X POST http://localhost:8080 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
Expected response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "add",
"description": "Add two numbers together and return the sum",
"inputSchema": { ... }
},
...
]
}
}