MP-201a · Module 3
Monitoring & Debugging
3 min read
MCP servers fail silently. The client sends a request, the server crashes, and the LLM gets a transport error with no diagnostic information. Structured logging is not optional — it is the only way you will know what happened. Log every tool call with its name, arguments (sanitized), execution time, and result status (success/error). Write logs to stderr for stdio servers or to a logging service for HTTP servers. Include a request ID in every log line so you can correlate entries across a single tool execution.
The MCP Inspector is your primary debugging tool during development. Run it with npx @modelcontextprotocol/inspector to get an interactive UI that connects to your server, lists all tools and resources, and lets you call them with custom inputs while showing the raw JSON-RPC messages in both directions. For production debugging, capture the JSON-RPC traffic by wrapping your transport in a logging proxy — log every message before passing it to the SDK. This gives you a complete replay of the conversation between client and server.
import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
// Structured logging wrapper for tool calls
function withLogging(
server: Server,
handler: (request: unknown) => Promise<unknown>
) {
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const callStart = Date.now();
const toolName = request.params.name;
const requestId = crypto.randomUUID().slice(0, 8);
// Log the call (stderr for stdio servers)
console.error(JSON.stringify({
event: "tool_call",
requestId,
tool: toolName,
args: request.params.arguments,
timestamp: new Date().toISOString(),
}));
try {
const result = await handler(request);
console.error(JSON.stringify({
event: "tool_result",
requestId,
tool: toolName,
durationMs: Date.now() - callStart,
}));
return result;
} catch (err) {
console.error(JSON.stringify({
event: "tool_error",
requestId,
tool: toolName,
error: (err as Error).message,
durationMs: Date.now() - callStart,
}));
throw err;
}
});
}
- Add structured logging Wrap every tool handler with a logging function that captures tool name, arguments, duration, and result status. Use JSON format so logs are parseable by monitoring tools.
- Set up MCP Inspector Run `npx @modelcontextprotocol/inspector` and connect to your server. Test every tool with valid inputs, invalid inputs, and edge cases. Check the raw JSON-RPC panel for protocol issues.
- Monitor in production For HTTP servers, export metrics: tool call count, error rate, and p95 latency per tool. Alert on error rate spikes — a tool that starts failing 50% of the time is worse than a tool that does not exist.