← Back to Blog
tutorialdebuggingtroubleshooting

Debugging MCP Tools: Logs, Traces, and Common Pitfalls

Debug MCP servers effectively — stdio logging, structured errors, common mistakes, and diagnostic strategies.

·3 min read·xapable

Debugging MCP Tools: Logs, Traces, and Common Pitfalls

MCP servers run on stdio — no console to watch. Debugging requires different strategies. This guide covers them all.

The Stdio Challenge

MCP servers communicate via stdin/stdout with the client. console.log() goes to stdout and breaks the protocol.

Rule #1: Log to stderr

// ❌ WRONG — breaks MCP protocol
console.log("User requested weather for London");

// ✅ RIGHT — goes to stderr, visible in logs
console.error("User requested weather for London");

All MCP clients capture stderr for debugging. Use it.

Structured Logging

Go beyond console.error:

function log(level, message, data = {}) {
  const entry = {
    timestamp: new Date().toISOString(),
    level,
    message,
    ...data
  };
  console.error(JSON.stringify(entry));
}

// Usage
log("info", "Tool called", {
  tool: "get_weather",
  args: { city: "London" }
});
// → {"timestamp":"2026-07-07T10:00:00Z","level":"info","message":"Tool called","tool":"get_weather","args":{"city":"London"}}

Viewing Logs

Claude Desktop

Help → Developer → MCP Logs

Cursor

Settings → MCP → Click server → View Logs

Windsurf

~/.windsurf/logs/mcp.log

Manual (any client)

Since the server runs as a child process, redirect stderr:

node index.js 2> debug.log

Common Pitfalls & Fixes

1. "Tool not found"

Symptom: Agent says it can't find your tool.

Diagnosis:

// Add diagnostic logging to tools/list
server.setRequestHandler("tools/list", async () => {
  log("debug", "tools/list called", { toolCount: TOOLS.length });
  return { tools: TOOLS };
});

Fix: Check that tools/list returns the correct structure and tools/call handles the tool name.

2. "Connection closed unexpectedly"

Symptom: Client disconnects after startup.

Diagnosis: The server likely crashed.

process.on("uncaughtException", (err) => {
  log("fatal", "Uncaught exception", { error: err.message, stack: err.stack });
  process.exit(1);
});

process.on("unhandledRejection", (reason) => {
  log("fatal", "Unhandled rejection", { reason: String(reason) });
  process.exit(1);
});

3. Empty Response

Symptom: Tool runs but agent sees no output.

Diagnosis: Check the response format.

// ❌ Wrong — missing content wrapper
return { text: "Hello" };

// ✅ Correct
return { content: [{ type: "text", text: "Hello" }] };

4. Schema Mismatch

Symptom: Agent passes wrong argument types.

Diagnosis: Validate your inputSchema.

// Add validation in tools/call
function validateArgs(schema, args) {
  if (schema.required) {
    for (const field of schema.required) {
      if (!(field in args)) {
        throw new Error(`Missing required field: ${field}`);
      }
    }
  }
}

Debugging Checklist

When your tool doesn't work:

  1. console.error for all logging (not console.log)
  2. ✅ Server starts without errors (node index.js in terminal)
  3. tools/list returns valid JSON
  4. tools/call handles the tool name
  5. ✅ Response follows { content: [{ type, text }] } format
  6. ✅ Error messages are clear and structured
  7. ✅ Environment variables are set correctly
  8. ✅ Check client-specific logs

Interactive Debugging

For deep issues, use Node.js inspector:

node --inspect index.js

Then open chrome://inspect in Chrome. Set breakpoints in your tool handlers.

Debug Mode Flag

Add a debug mode to your server:

const DEBUG = process.env.MCP_DEBUG === "true";

function debug(...args) {
  if (DEBUG) console.error("[DEBUG]", ...args);
}

// In tools/call:
debug("Handling tool:", name, "with args:", args);

Enable with: MCP_DEBUG=true in your client config env vars.

Debugging MCP tools takes practice, but with stderr logging and structured error handling, you'll catch issues fast.

#MCP #Tutorial #Debugging #mcpm #DevTools