Debugging
Source: MCP 89153404
Troubleshoot from the last successful step
A connection can fail while starting a process, parsing a message, negotiating a revision or executing a tool. Record the absolute executable, arguments, working directory, SDK package versions, actual protocol revision and last successful method. Keep only redacted error codes and correlation IDs; never attach credentials, a full environment dump or user files.
| Last visible result | Check first | What it tells you |
|---|---|---|
No process; ENOENT | Executable exists; GUI and shell PATH differ | Tool arguments cannot repair a process that never started |
| Immediate process exit | Run the same command, inspect stderr and exit status; use absolute config paths | A successful terminal run does not establish the host’s cwd |
stdout starts with Server starting... | Startup banners and dependency initialization output | A JSON-RPC parsing failure is not a version mismatch |
| Discovery works; a call fails | Protocol error, isError tool result, timeout or closed connection | Treat input, application and transport failures separately |
| Legacy works; modern fails | Peer support for 2026-07-28, discovery and per-request _meta | An SDK package version is not a protocol revision |
Reproduce a clean and a polluted stdout
Copy inspector_smoke.py and sdk_server.py from the Inspector lab into a practice environment with mcp==2.3.0:
python3 inspector_smoke.py --call add --arg a=2 --arg b=3 --check-stdout -- python3 sdk_server.py stdio ok
python3 inspector_smoke.py --check-stdout -- python3 sdk_server.py stdio banner
python3 inspector_smoke.py --check-stdout -- python3 sdk_server.py stdio crashOn 2026-10-30, Inspector 2.12.0, Node 24.18.0 and Python 3.11.12 reproduced all three: the clean server discovered tools, returned 5 and passed stdout validation; the pre-start banner failed stdout validation; the exiting server failed connection. The banner explicitly flushes so buffering cannot hide it. Do not infer that every print corrupts the stream: this SDK redirects prints inside a running tool, while pre-start output still needs control.
For HTTP, compare with a successful discovery request: local stubs returning 401, 403, 404 or HTML with status 200 all failed MCP connection. These are different causes, and HTML 200 is not protocol success; see remote connections. The actual SDK also rejected an unsupported revision with -32022. Do not infer one particular missing _meta field from -32602 alone; inspect the request and error data.
This run did not open Claude Desktop or another host UI. Check the pinned source’s menus, shortcuts and platform statements against your installed client and its help. Models, real remote login, the weather API and every language SDK were outside this test.
Effective debugging is essential when developing MCP servers or integrating them with applications. This guide covers the debugging tools and approaches available in the MCP ecosystem.
Debugging tools overview
MCP provides several tools for debugging at different levels:
- MCP Inspector: interactive, transport-agnostic testing UI. Connect to stdio or Streamable HTTP servers, invoke tools, prompts, and resources, and watch the notification stream. This should be your first stop.
- Server logging: structured logs to stderr (stdio transport) or via
OpenTelemetry (all transports).
Logging over the protocol
(
notifications/message) is deprecated as of protocol version2026-07-28. - Client developer tools: most MCP clients expose logs and connection state. See Debugging in Claude Desktop below for one example, or consult your client’s documentation.
Implementing logging
Server-side logging
When building a server that uses the local stdio transport, all messages logged to stderr (standard error) will be captured by the host application automatically.
For servers using the Streamable HTTP transport, stderr is not captured by the client. Use your own server-side log aggregation or OpenTelemetry for logs, and standard HTTP tooling (curl, browser DevTools Network panel) to inspect requests and SSE streams.
notifications/message mechanism below is deprecated as of protocol
version 2026-07-28. It remains available during the deprecation window.For all transports, record what the server is doing as it runs:
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("reports")
@mcp.tool()
async def fetch_report(report_id: str) -> str:
"""Fetch a report by id."""
logger.info("Fetching report %s", report_id)
return f"Report {report_id} is ready."await server.sendLoggingMessage({
level: "info",
data: "Server started successfully",
});MCP defines eight
RFC 5424 severity levels
(debug through emergency). Clients opt in to log messages per request by
setting the
io.modelcontextprotocol/logLevel
field in the request’s _meta. Servers must not send notifications/message
for requests that omit this field.
Important events to log:
- Startup steps
- Resource access
- Tool execution
- Error conditions
- Performance metrics
Common issues
The examples below use Claude Desktop’s
claude_desktop_config.json; the same
principles apply to any stdio-based MCP client.
Working directory
When an MCP client launches a stdio server:
- The working directory for servers launched via the client’s config may be
undefined (like
/on macOS) since the client could be started from anywhere - Always use absolute paths in your configuration and
.envfiles to ensure reliable operation - For testing servers directly via command line, the working directory will be where you run the command
For example in claude_desktop_config.json, use:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/username/data"
]
}
}
}Instead of relative paths like ./data
Environment variables
MCP servers launched over stdio inherit only a limited subset of environment variables automatically (the exact set is platform-dependent).
To override the default variables or provide your own, you can specify an
env key in claude_desktop_config.json:
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": {
"MYAPP_API_KEY": "some_key"
}
}
}
}Server startup
Common startup problems:
Path Issues
- Incorrect server executable path
- Missing required files
- Permission problems
- Try using an absolute path for
command
Configuration Errors
- Invalid JSON syntax
- Missing required fields
- Type mismatches
Environment Problems
- Missing environment variables
- Incorrect variable values
- Permission restrictions
Connection problems
When servers fail to connect:
- Check client logs
- Verify server process is running
- Test standalone with Inspector
- Verify
protocol compatibility: call
server/discoverto see which protocol versions the server supports. AnUnsupportedProtocolVersionError(-32022) lists the server’s supported versions in itsdatafield - Check the
per-request
_metafields: every request must carryio.modelcontextprotocol/protocolVersionandio.modelcontextprotocol/clientCapabilities, and clients should also includeio.modelcontextprotocol/clientInfo. A request missing either required field is rejected with error-32602(Invalid params), the same code returned for many other malformed inputs. If the server needs a capability the request’sclientCapabilitiesdid not declare, such as elicitation, it returns aMissingRequiredClientCapabilityError(-32021) naming the missing capabilities. Inspect the request’s_metaand theserver/discoverresponse to verify both sides declared what you expect
Debugging in Claude Desktop
Claude Desktop is one of many MCP clients. It is available on macOS, Windows, and Linux.
Checking server status
Click the “Add files, connectors, and more” plus icon in the chat input, then hover over the Connectors menu to see connected servers and available tools.

Viewing logs
Log files are written to:
- macOS:
~/Library/Logs/Claude - Windows:
%APPDATA%\Claude\logs - Linux:
~/.config/Claude/logs
tail -n 20 -F ~/Library/Logs/Claude/mcp*.logtail -n 20 -F ~/.config/Claude/logs/mcp*.logtype "$env:AppData\Claude\logs\mcp*.log"The logs capture:
- Server connection events
- Configuration issues
- Runtime errors
- Message exchanges
Using Chrome DevTools
Access Chrome’s developer tools inside Claude Desktop to investigate client-side errors:
- Create a
developer_settings.jsonfile withallowDevToolsset to true:
echo '{"allowDevTools": true}' > ~/Library/Application\ Support/Claude/developer_settings.json'{"allowDevTools": true}' | Set-Content "$env:AppData\Claude\developer_settings.json"- Open DevTools:
Command-Option-I(macOS) orCtrl+Alt+I(Windows)
Note: You’ll see two DevTools windows:
- Main content window
- App title bar window
Use the Console panel to inspect client-side errors.
Use the Network panel to inspect:
- Message payloads
- Connection timing
Debugging workflow
Development cycle
Initial Development
- Use Inspector for basic testing
- Implement core functionality
- Add logging points
Integration Testing
- Test in your target MCP client
- Monitor logs
- Check error handling
Testing changes
To test changes efficiently:
- Configuration changes: Restart the MCP client
- Server code changes: Restart the client (for Claude Desktop, fully quit and reopen; closing the window is not enough)
- Quick iteration: Use Inspector during development
Best practices
Logging strategy
Structured Logging
- Use consistent formats
- Include context
- Add timestamps
- Track request IDs
Error Handling
- Log stack traces
- Include error context
- Track error patterns
- Monitor recovery
Performance Tracking
- Log operation timing
- Monitor resource usage
- Track message sizes
- Measure latency
Security considerations
When debugging:
Sensitive Data
- Sanitize logs
- Protect credentials
- Mask personal information
Access Control
- Verify permissions
- Check authentication
- Monitor access patterns
For a full treatment of MCP attack vectors and mitigations, see Security Best Practices.
Getting help
When encountering issues:
First Steps
- Check server logs
- Test with Inspector
- Review configuration
- Verify environment
Support Channels
Providing Information
- Log excerpts
- Configuration files
- Steps to reproduce
- Environment details
Next steps
MCP Inspector
Learn to use the MCP Inspector
Build an MCP server
Walk through building a server from scratch
Connect local servers
Full claude_desktop_config.json reference and troubleshooting