11 Minutes
MCP Debugging: How to Fix Broken MCP Servers and Tools
Fix Bugs Faster! Log Collection Made Easy
Model Context Protocol allows AI models like Claude to communicate with the outside world. But MCP debugging has been one of our steepest learning curves at Bugfender. Several different layers need to work together at the same time and if one thing breaks, it can scupper the whole workflow.
That’s why we’re here today. To pass on hard-won knowledge, so you can jump the curve. You’ll learn how to use both Anthropic’s official MCP debugging tool and Claude Code, and leave with solutions for the problems that take down MCP integrations most often. Things like:
- Servers that do not start.
- Tools that do not appear in the AI client.
- Agent behavior that changes after MCP context is added.
You’ll leave with a sophisticated knowledge of MCP debugging and the ability to scale your skills with the protocol, as the new multi-vendor standard takes shape.
What MCP debugging is
MCP is the communication layer between AI models and external data sources.
This bridge enables the model to read files, pull facts and control browsers. But it also creates a leaky seam between a probabilistic language model and deterministic external applications. Problems can easily creep into the cracks.
MCP debugging patrols this point of failure and diagnoses failures between an MCP client and an MCP server.
To be clear though: it’s very different to debugging your application’s business logic, which deals with what your code does with data. MCP debugging deals with whether your client and server can talk to one another at all: the connection, the message exchange, the protocol handshakes.
MCP Inspector: the primary MCP debugging tool
When Anthropic released MCP in November 2024, developers had to rely on a stressy mish-mash of hacks and patches: reading raw stdout/stderr logs and manually crafting JSON-RPC messages.
In early 2025 Anthropic unveiled the **MCP Inspector** to fix this problem. The inspector (released as a @modelcontextprotocol/inspector npm package) gives you a browser-based interface to
- Connect to any server.
- Invoke tools.
- Browse resources.
- Watch the notification stream in real time.
It’s important to start with the MCP Inspector before touching any logs or config files. It surfaces connection and tool errors immediately, without requiring a full client setup.
Getting started with MCP Inspector
How to run the Inspector with npx
For a quick UI check, you can simply start the MCP Inspector by itself:
npx @modelcontextprotocol/inspector
This opens the Inspector UI and proxy server locally. From there, you can connect to a running MCP server and test tools, resources, prompts, and notifications.
To inspect a local stdio server directly, pass the server command after the Inspector package:
npx @modelcontextprotocol/inspector node build/index.js
Here, node build/index.js is only an example server command. Replace it with the command that starts your MCP server.
To pass environment variables or extra server arguments, keep the Inspector command first, then add the server startup details:
npx @modelcontextprotocol/inspector -e API_KEY=your-key node build/index.js arg1
UI mode vs CLI mode
The Inspector gives you two extremely useful options for testing the MCP server. UI mode opens a visual browser-based interface while CLI mode works through the command line.
| UI mode | CLI mode |
|---|---|
| Best for interactive debugging and manual testing | Best for repeatable checks and automation |
| Visual interface for inspecting tool responses | Terminal output designed for scripts and pipelines |
| Useful while actively developing MCP servers | Useful for CI, regression checks, and fast validation |
| Easier for exploring prompts, resources, and notifications | Easier for scripted tools/list and tools/call workflows |
| Better for debugging transport or capability issues visually | Better for AI coding assistant feedback loops |
Remember to use CLI mode with the --cli flag when you need a scriptable command:
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
How to read MCP server logs
The Inspector is great for active trouble-shooting when you need an answer immediately. Server logs add another layer on top by providing passive, continuous monitoring.
The logs capture initialization events, runtime errors, and message exchanges that the Inspector UI does not always surface in full detail.
Server-side logging with stderr
For stdio-based MCP servers, we write all debug output to stderr, not stdout. The host application captures stderr automatically.
Stdout breaks the protocol. MCP uses stdout as the message channel between client and server. Anything written to stdout that is not a valid MCP message corrupts the stream.
In Node.js, we use console.error() instead of console.log() for debug output. In Python, we write to sys.stderr explicitly.
Sending log notifications to the client
An important flag here: For Streamable HTTP servers, stderr is not captured by the MCP client. It’s best to use notifications/message to send structured logs through the MCP connection instead.
In Python:
await ctx.session.send_log_message(
level="info",
data="Tool executed successfully"
)
In TypeScript, it’s important to check whether the server class exposes a logging helper or requires you to send the notifications/message notification manually.
MCP supports eight severity levels following RFC 5424, from debug to emergency. Clients can adjust the minimum log level at runtime via logging/setLevel.
Log file location by client
| Client | Log path |
|---|---|
| Claude Desktop (macOS) | ~/Library/Logs/Claude/mcp*.log |
| Claude Desktop (Windows) | %APPDATA%\Claude\logs\mcp*.log |
For other clients, check the client’s own documentation for MCP log output paths.
Common MCP server errors and how to fix them
Most MCP server failures fall into a few repeatable categories. Identifying which category you fall into will spare you a lot (and we mean a lot) of time fixing.
| Problem | Most likely cause |
|---|---|
| Server does not appear | Invalid config, wrong executable path, or missing build files |
| Server appears but no tools show | Capability negotiation or tool registration failure |
| Tool appears but fails when called | Input schema, parameter, or response format mismatch |
| Inspector cannot connect | Transport, startup, or protocol compatibility problem |
| Logs are missing | Wrong logging channel or unsupported client log output |
Now let’s look at each of these issues in detail.
Server initialization failures
Initialization errors happen before the MCP client has even interacted with the server – before any tools, resources or prompts. The connection is never made at all.
If you think your issue falls into this category, check these three areas first:
- Executable path: use an absolute path in your config, not a relative one like
./build/index.js. - Missing files: confirm all required build artifacts exist before launching.
- JSON syntax: invalid
claude_desktop_config.jsonsilently prevents servers from loading. Validate the file before restarting.
Connection and transport problems
This time the server process starts but the client cannot connect. If you’ve encountered this problem, run the following workflow:
- Check the client logs for the exact error.
- Verify the server process is actually running.
- Test in isolation with the Inspector.
- Confirm protocol version compatibility between client and server.
- Inspect the
initializeexchange for capability mismatches.
Tool schema and response errors
Tool schema errors happen when the server connects, but the client cannot call the tool correctly or cannot understand the response.
Check three things first:
- Input schema: confirm required parameters, types, and defaults match what the client sends.
- Tool response shape: return valid structured content the client can parse.
- JSON-RPC payloads: inspect
tools/listandtools/callin the MCP Inspector to catch malformed requests or responses.
If the tool appears in the client but fails when called, the issue is often the schema, parameters, or response format.
Tool selection and agent behavior problems
Some MCP issues do not fall neatly into transport or schema failures. The AI client may connect successfully but choose the wrong tool, ignore tools entirely, or misuse parameters.
This usually happens because:
- Tool descriptions are ambiguous.
- Multiple tools overlap in purpose.
- Responses contain excessive context.
- Capability descriptions are unclear.
When debugging this type of issue, inspect both the tool schema and the natural-language descriptions exposed during the initialize exchange.
Environment variable issues
MCP servers launched over stdio inherit only a limited subset of environment variables by design.
This is intended to prevent accidental leakage of sensitive credentials to servers that don’t need them. But it can cause problems when your server depends on variables outside this subset, like API keys or config values.
In this case, you should pass the variables explicitly via the env key in your client config:
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": { "MYAPP_API_KEY": "some_key" }
}
}
}
And remember: never assume environment variables are available automatically. Often they won’t be.
Working directory misconfigurations
When a client launches a stdio server, the working directory can be undefined. On macOS it often defaults to /. When this happens, any relative path in your config or .env file will fail silently.
Always use absolute paths for file references, executables, and configuration values. This applies to both your server code and your client config file.
How to debug MCP servers in Claude Code
MCP Inspector deliberately bypasses the AI model. It’s a raw client that talks straight to your server and it’s great for isolating protocol bugs. But it can’t tell you how Claude will actually interpret your tool.
Since your tool’s docstrings and parameter descriptions are literally the instructions the model reads to decide how to call it, debugging in Claude Code shows you the real behavior.
- Does Claude pick the right tool?
- Does it pass sensible arguments?
- Does it use the result correctly or simply respond to a manually crafted request?
The effective use of Claude Code will expose several debugging entry points directly in your editor.
Here are three essential steps to achieve this.
Check server status and available tools
In Claude Code, open the MCP server panel to see which servers are connected and which tools are registered. A server that appears in the list, but shows no tools, has connected successfully but failed during capability negotiation.
Use this view as your first check after any config change. It confirms whether the server process started and whether the initialize exchange completed correctly. This simple step will catch a whole heap of issues.
Restart and reload MCP servers
Configuration changes do not take effect until the MCP client restarts. In Claude Code, you can restart individual MCP servers without restarting the full editor.
For code changes to your server, a full client restart is usually safer because partial restarts may not reload server binaries.
Use verbose logging in Claude Code
Enable verbose MCP logging in Claude Code’s settings to capture the full message exchange between client and server. This output includes the raw initialize request and response, which is essential for diagnosing capability mismatch errors.
Pair this with stderr logging in your server to get both sides of the conversation in one debugging session.
MCP debugging best practices
Whether you’re using MCP Inspector, Claude Code or a combination of both, the following tips should greatly streamline and optimize your workflow. These practices apply across all MCP server types and transports.
- Log at initialization. The most common failures happen before the first tool call. Log every initialization step explicitly so you know exactly where the server stopped.
- Use absolute paths everywhere. Relative paths in config files are the single most common source of MCP initialization failures. Treat this as a hard rule, not a suggestion.
- Test with the Inspector before the client. The Inspector isolates the server completely. If a tool works in the Inspector but not in Claude Code, the problem is in the client config, not the server.
- Sanitize logs in production. Debug logs often contain API keys, tokens, and user data. Strip sensitive values before any log reaches an external system.
- Keep the initialize exchange in scope. Error
-32602and most capability errors surface during the initialize handshake. Always inspect that exchange first when diagnosing connection failures.
And if you want to really level up, try adding a remote logging tool to your MCP stack. This will allow you to maintain persistent runtime logging across environments, so your server produces the same structured logs whether it’s running locally, in a staging environment, or in production.
Our own logging tool is designed to achieve exactly this. We’ve got a whole post on how to integrate Bugfender with MCP, which you can read here.
Frequently asked questions
How do I debug an MCP server without the Inspector?
Write debug output to stderr (stdio transport) or use notifications/message (HTTP transport), then read the log files your client writes. For Claude Desktop, logs are at ~/Library/Logs/Claude/mcp*.log on macOS. This approach is slower than the Inspector but works in any environment.
Why is my MCP server not connecting to the client?
The most common causes are an incorrect executable path, a JSON syntax error in the config file, or missing environment variables. Start by checking the client logs, then test the server in isolation using the MCP Inspector to confirm whether the issue is in the server or the config.
Can I use console.log() to debug an MCP server?
No, not for stdio servers. MCP uses stdout as the protocol message channel, so anything written to stdout that is not a valid MCP message corrupts the stream. Use console.error() in Node.js or write to sys.stderr in Python instead.
What does MCP error -32602 mean?
Error -32602 is the standard JSON-RPC “Invalid params” code. In MCP, it most commonly appears when a server sends a sampling or elicitation request to a client that has not declared that capability. Inspect the initialize exchange to confirm what capabilities both sides declared.
How do I test MCP tools without a full client?
Use the MCP Inspector in UI mode to invoke tools directly with custom parameters and see the full response. For scripted testing, use CLI mode with the --method tools/call flag. Neither requires a running MCP client like Claude Code or Claude Desktop.
Expect The Unexpected!
Debug Faster With Bugfender