The Problem: Server Connected, No Tools Visible
Your MCP server appears connected - the client shows a green status indicator or no errors - but when you try to use it, no tools appear in the tools list. This is one of the most frustrating MCP issues because the server seems to be working fine.
The typical symptoms include:
- Server shows as "connected" in your client's MCP settings
- No error messages in the logs
- But the tools list is empty or the AI doesn't know about any tools
- The server worked before but tools disappeared after an update
This guide covers every known cause and how to debug it using the MCP Inspector and client-specific tools.
Cause 1: Capabilities Not Declared
MCP servers must explicitly declare their capabilities during initialization. If the server doesn't declare the tools capability, clients won't even ask for the tool list.
// WRONG - no capabilities declared
const server = new Server({
name: "my-server",
version: "1.0.0"
});
// CORRECT - tools capability declared
const server = new Server({
name: "my-server",
version: "1.0.0",
}, {
capabilities: {
tools: {}
}
});
In Python with FastMCP, capabilities are usually auto-declared when you register tools, but double-check if you're using the lower-level API.
Cause 2: Tool Handler Not Registered
The server declares the tools capability but doesn't actually register any tool handlers. This can happen when your tool registration code throws a silent error during startup.
// Make sure tools are registered BEFORE the server starts
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "my_tool",
description: "Does something useful",
inputSchema: {
type: "object",
properties: {
input: { type: "string", description: "The input" }
},
required: ["input"]
}
}
]
};
});
// Don't forget the tool execution handler too!
server.setRequestHandler(CallToolRequestSchema, async (request) => {
// Handle tool calls here
});
FastMCP (Python)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def my_tool(input: str) -> str:
"""Does something useful"""
return f"Result: {input}"
# Make sure this runs
mcp.run()
Cause 3: Initialization Race Condition
Some clients send the tools/list request before the server has finished initializing its tools. This is common with servers that load tools dynamically from a database or API.
Fix
Ensure all tools are registered synchronously during server construction, or use an initialization promise that resolves before the server starts accepting requests:
// Load tools before starting the server
const tools = await loadToolsFromDatabase();
tools.forEach(tool => server.registerTool(tool));
// THEN start the server
await server.connect(transport);
Cause 4: Client-Specific Quirks
Claude Desktop
Claude Desktop caches the tool list from the initial connection. If you add new tools to a running server, Claude Desktop won't see them until you restart. Use the MCP menu (hammer icon) to verify which tools are loaded.
- Check the hammer icon in the chat input - it should show a number (e.g., "3 tools")
- Click it to see the full tool list
- If empty, restart Claude Desktop completely
Cursor
Cursor shows tool count in Settings > MCP. If the count is 0 but the server is connected, it's a capability or handler issue. Cursor also requires tools to have valid JSON Schema for the input - malformed schemas cause silent tool drops.
VS Code
VS Code MCP extensions vary in how they display tools. Check the extension's output channel for any warnings about skipped or invalid tools.
Debugging with MCP Inspector
The MCP Inspector is the best way to debug tool visibility issues. It connects to your server and shows exactly what the server returns for each MCP request.
# Install and run the MCP Inspector
npx @modelcontextprotocol/inspector
# Or for a specific server
npx @modelcontextprotocol/inspector npx -y @modelcontextprotocol/server-filesystem /tmp
In the Inspector:
- Connect to your server
- Click "List Tools" to send a
tools/listrequest - Check the response - if tools appear here but not in your client, the issue is client-side
- If no tools appear here either, the issue is in your server code
Cause 5: Invalid Tool Schema
Some clients silently drop tools with invalid JSON Schema in their inputSchema. Common schema errors:
- Missing
"type": "object"at the top level - Using
requiredwith property names that don't exist inproperties - Unsupported schema features (some clients don't support
oneOf,anyOf) - Empty
propertiesobject (some clients need at least one property)
// WRONG - missing type, invalid required
{
"name": "search",
"inputSchema": {
"properties": {
"query": { "type": "string" }
},
"required": ["query", "nonexistent_field"] // Error!
}
}
// CORRECT
{
"name": "search",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Search query" }
},
"required": ["query"]
}
}
Cause 6: Server Returning Empty Tool List
Check if your tools/list handler has a conditional that might return an empty array:
// Bug: condition prevents tools from loading
server.setRequestHandler(ListToolsRequestSchema, async () => {
if (!process.env.ENABLE_TOOLS) { // Forgot to set env var!
return { tools: [] };
}
return { tools: myTools };
});
Check your environment variables are correctly passed to the server process.
Step-by-Step Fix Process
- Test with MCP Inspector - Run your server with the Inspector to see if tools are returned.
- Check capabilities - Verify your server declares
tools: {}in capabilities. - Validate schemas - Ensure every tool has a valid
inputSchemawith"type": "object". - Check handlers - Confirm both
ListToolsRequestSchemaandCallToolRequestSchemahandlers are registered. - Restart client - Fully restart your MCP client after making changes.
- Check logs - Look for warnings or errors in client-specific log locations.
If you're building a new server, follow our Build an MCP Server tutorial which covers proper tool registration from the start.