A comprehensive guide to debugging Model Context Protocol (MCP) integrations
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.
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 version 2026-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.
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.
Local MCP servers should not log messages to stdout (standard out), as this
will interfere with protocol operation.
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.
The 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 loggingfrom mcp.server import MCPServerlogger = 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:
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:
Verify
protocol compatibility: call
server/discover to see which
protocol versions the server supports. An
UnsupportedProtocolVersionError (-32022) lists the server’s supported
versions in its data field
Check the
per-request _meta fields:
every request must carry io.modelcontextprotocol/protocolVersion and
io.modelcontextprotocol/clientCapabilities, and clients should also
include io.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’s clientCapabilities did not declare, such as
elicitation, it returns a
MissingRequiredClientCapabilityError (-32021) naming the missing
capabilities. Inspect the request’s _meta and the
server/discover response to
verify both sides declared what you expect
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.