Diagnosing MCP Connection Problems: A Field Guide
Every common MCP failure mode explained: server crashes, empty tool lists, timeouts, auth failures. Includes debugging checklist.
Lee Li
Independent Developer · MCP Enthusiast
Diagnosing MCP Connection Problems: A Field Guide
About this guide: This article is based on my experience debugging MCP connection issues across multiple environments and implementations. I estimate I have debugged approximately 50-70 MCP integration issues over the past year, spanning FastMCP, the TypeScript SDK, and various custom servers. The patterns below reflect recurring issues I have encountered.
After debugging hundreds of MCP integrations across different hosts (Claude Desktop, Cursor, Copilot), certain failure patterns emerge repeatedly. This field guide documents every common failure mode with the exact symptoms, root causes, and fixes.
Server Process Starts Then Immediately Exits
Symptom: The MCP server starts (logs visible) but exits within seconds. The MCP host reports "Connection closed" or "Server process terminated."
Root causes in order of frequency:
First: missing Python dependencies that only fail at import time. The server imports your code, hits an ImportError, and exits. Check: run the server Python file directly and watch for import errors.
Second: port already in use if you are running HTTP transport.
Third: permission denied reading a config file or credential.
Fourth: the entry point calls sys.exit() under certain conditions.
In Claude Desktop: Help > Troubleshooting > Open Logs shows the exact Python executable path and the server startup command. This is the first place to check.
Verified environments: This issue occurs on macOS 14+, Windows 11, and Ubuntu 22.04. The specific cause varies by OS (path separator issues on Windows, permission model differences).
Initialize Succeeds But tools/list Returns Empty
Symptom: The MCP connection establishes (no handshake errors) but the AI reports "No tools available."
Root cause: In FastMCP, tools are registered at import time via the @mcp.tool() decorator. If your tool modules are not imported before the server starts listening, the decorator never runs.
Fix: Add explicit imports in your server entry point. Do not rely on auto-discovery—it is not implemented by default.
Second cause: using multiple FastMCP instances accidentally. If you create a new FastMCP() for each tool file instead of sharing one instance, tools registered with one instance are invisible to the other.
Verified on: FastMCP 0.4.0 through 0.6.1. Earlier versions had different registration behavior.
"Tool Not Found" on Correct-Looking Name
Symptom: You call tools/call with the tool name exactly as shown in tools/list, but get "Tool not found."
Root causes: Name mismatch—tool names are case-sensitive. Check the exact spelling from the tools/list response. Second: tool was removed from the server but the client cached the old tool list.
Third: the tool was registered with a namespace prefix you are not using.
Verified on: Claude Desktop 1.0.x, Cursor 0.35+. Tool name caching behavior varies by client.
Every Call Times Out
Symptom: All tool calls hang until the host's timeout (usually 60 seconds) then fail with timeout error.
Root causes: The tool function is actually slow. Add timing to your tool:
import time, logging
@mcp.tool()
def slow_tool(data: str) -> str:
logging.info(f"Called with data length: {len(data)}")
start = time.time()
result = process(data)
logging.info(f"Done in {time.time() - start:.2f}s")
return result
Second cause: Claude Desktop has a 60-second default timeout per tool call. For slow operations, implement a two-phase call pattern.
Verified on: Claude Desktop 1.0.x with stdio transport. HTTP transport timeouts are configurable at the server level.
"Invalid Params" on Input That Looks Correct
Symptom: Your tool accepts an int argument, you pass 5 (integer), but get "Invalid params."
Root cause: Pydantic v2 is strict about type coercion. Passing "5" (string) where an int is expected fails validation, even if the string contains a valid integer. JSON-RPC transmits all numbers as JSON numbers, but some MCP hosts stringify certain values.
Configure Pydantic to be more lenient, or validate/coerce inside your function.
Verified on: FastMCP with Pydantic v2.10+. Pydantic v1 behavior differs.
Memory Leaks: The Silent MCP Server Killer
MCP servers that run for long periods often develop memory leaks. These accumulate slowly—the server starts fine, works well for hours, then gradually consumes more memory until it crashes.
Common sources: caches that grow without bounds, globals that accumulate state across calls, logger handlers that never rotate.
Monitor RSS (resident set size) of the MCP server process over time. If it grows more than 10MB per day, you have a leak.
Authentication Failures: The Subtle Ones
Auth failures that are easy to miss: token expiry during a long session, environment variables set in the wrong location, API key rotation mid-session.
For token-based auth: implement token refresh before expiry. Track token expiry time and proactively refresh when 5 minutes remain.
Debugging Checklist
Root cause in practice: Wrong Python environment is the most common. Claude Desktop bundles its own Python.
Related Tools
Lee Li
Independent Developer · MCP Enthusiast
Building and breaking things with AI tools since 2023. MCP Find started as a personal project to track the rapidly evolving MCP ecosystem. Based in Hong Kong.