DEV Community

Cover image for Debugging MCP Tool Calls Sucks: Reticle Is “Wireshark for MCP”
LabtTerminal
LabtTerminal

Posted on

Debugging MCP Tool Calls Sucks: Reticle Is “Wireshark for MCP”

Repo: https://github.com/LabTerminal/mcp-reticle

MCP is powerful, but debugging it is painfully blind. Reticle gives you DevTools-style visibility into MCP JSON-RPC traffic, latency, stderr/crashes, and session recording.

If you’ve ever watched an agent “successfully” call a tool… and still end up with the wrong outcome, you’ve felt the MCP debugging pain.

MCP (Model Context Protocol) unlocks a clean way to wire agents to tools, but the day-to-day experience can be brutal because the truth is hidden in the transport. The client UI shows a friendly summary. Your server logs show some of what happened. And the actual JSON-RPC request/response stream—the thing you need to debug—is usually invisible.

So you do what we all do:

  • add logging (again),
  • re-run the same prompt 20 times,
  • stare at “Connection failed” or “Internal error” with no context,
  • and pray your agent doesn’t decide to “helpfully” retry forever.

Let’s talk about why MCP debugging feels cursed… and how to fix it.


Why MCP debugging hurts more than it should

1) Your agent UI hides the real traffic

Most MCP clients are designed to reduce noise, which is great until you need the raw request that actually went over the wire:

  • which method was called?
  • what params were sent?
  • did the client cancel?
  • did the server respond with an error object?
  • did the response ID even match the request ID?

When the UI abstracts the protocol, you’re debugging vibes—not facts.

2) A huge amount of MCP traffic isn’t “proxy-able”

A ton of MCP usage is local process ↔ local process over stdio (stdin/stdout). That means:

  • no HTTP
  • no TCP port
  • nothing for your usual network proxy to intercept

Even the official tools are often clients, not transparent interceptors. You can end up debugging a different execution path than your actual agent is taking.

3) stderr is where the truth goes to die

Many MCP servers (especially Python/Node ones) will dump the real error to stderr:

  • stack traces
  • dependency failures
  • auth/config mistakes
  • parse errors

But your client often won’t show stderr. So you see “tool failed” with zero details.

4) Concurrency makes correlation a nightmare

Agents call tools concurrently. JSON-RPC responses come back out of order. Retries happen. Cancels happen.

If you can’t correlate request ↔ response instantly, you can’t answer basic questions like:

  • “Which tool call caused this error?”
  • “Which request took 2.5s?”
  • “Why did this tool return empty data?”

5) Latency gets blamed on the wrong thing

When an agent feels slow, you need to know:

  • is the LLM thinking?
  • is the tool slow?
  • is the transport slow?
  • is the server hanging?

If you can’t see per-call latency, you’ll optimize the wrong layer.

6) Payload bloat silently wrecks reliability (and cost)

Sometimes the “bug” is just:

  • a massive resource payload,
  • repeated tool outputs,
  • or runaway context growth.

But without visibility, you won’t catch it until things time out, crash, or become expensive.

7) Transport differences create weird, inconsistent failures

MCP supports multiple transports (stdio, Streamable HTTP, etc.). A tool might “work” in one setup and fail mysteriously in another.

If you want sanity, you need a single lens across transports.


Enter Reticle: DevTools-style visibility for MCP

Reticle is a proxy + UI that intercepts MCP JSON-RPC traffic in real time—so you can see what your agent sees.

Think: Wireshark, but MCP-aware.

What Reticle gives you (without hand-rolled logging wrappers):

  • Inspect raw JSON-RPC messages (requests / notifications / responses)
  • Correlate request ↔ response instantly (even with concurrency)
  • Profile latency + token estimates (spot slow or bloated calls fast)
  • Capture server stderr + crashes (stop losing stack traces)
  • Record sessions + export logs (share a trace instead of “try again with logs on”)

And it’s built to be lightweight: designed for microsecond-level overhead, so it doesn’t change the behavior you’re trying to observe.

Supported transports include: stdio, Streamable HTTP, WebSocket, HTTP/SSE.


5-minute quick start

1) Install (pick one)

# npm
npm install -g mcp-reticle

# pip
pip install mcp-reticle

# homebrew
brew install labterminal/mcp-reticle/mcp-reticle
Enter fullscreen mode Exit fullscreen mode

2) Wrap any stdio MCP server

Replace your MCP server command with:

mcp-reticle run --name <name> -- <your server command...>
Enter fullscreen mode Exit fullscreen mode

Example (wrapping the filesystem server):

mcp-reticle run --name filesystem -- npx -y @modelcontextprotocol/server-filesystem /Users/me/work
Enter fullscreen mode Exit fullscreen mode

If you’re using a Claude Desktop-style config, your MCP entry becomes:

{
  "mcpServers": {
    "filesystem": {
      "command": "mcp-reticle",
      "args": ["run", "--name", "filesystem", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/Users/me/work"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

3) Launch the UI

mcp-reticle ui
Enter fullscreen mode Exit fullscreen mode

Optional: log-only mode (great for CI or quick triage)

mcp-reticle run --log -- npx -y @modelcontextprotocol/server-memory
Enter fullscreen mode Exit fullscreen mode

Optional: proxy an HTTP-based MCP server

mcp-reticle proxy --name api --upstream http://localhost:8080 --listen 3001
Enter fullscreen mode Exit fullscreen mode

How I Use Reticle to Debug “Impossible” MCP Bugs

Here’s a workflow that has saved me hours when debugging MCP-based agents.

My Typical Debug Flow

  1. Wrap the MCP server with Reticle

    Use Reticle as a transparent wrapper (stdio or HTTP proxy). No code changes, no custom logging.

  2. Reproduce the failure once

    Don’t enable verbose logs everywhere. One clean reproduction is enough.

  3. Open the Reticle UI

    This is where the truth lives.

  4. Filter by errors and slow calls

    Immediately narrow down to:

    • failed JSON-RPC calls
    • unusually slow tool invocations
  5. Inspect the exact request / response pair

    Click into the event and look at:

    • method name
    • params shape
    • error object (if any)
    • timing / latency
  6. Check stderr if the server crashed

    Reticle captures stderr separately.

    This is usually where the real bug is hiding (stack traces, config errors, panics).

  7. Export the session if you need help

    Instead of saying “it fails sometimes,” export the session/logs and send the artifact to a teammate.


Why This Works

It’s the difference between:

“It broke. Not sure why.”

and:

“The client sent malformed params to tools/call at 22:14:02.

The server threw a stack trace on stderr.

Also this call is 2.6s slower than the rest.”

That level of clarity changes everything.


Security Note (Important)

Reticle can capture:

  • tool inputs and outputs
  • full JSON-RPC payloads
  • server stderr (including stack traces)

That’s exactly what makes it powerful — and also what makes recordings sensitive.

Treat exported sessions and logs like you would:

  • production logs
  • auth headers
  • prompts containing private data
  • customer content

If you’re working with sensitive environments, build a habit of:

  • redacting before sharing
  • or avoiding recording entirely in those contexts

Try It and Tell Me What You Want Next

If you’re building:

  • MCP servers
  • MCP clients
  • agent frameworks
  • or agent tooling

Repo: https://github.com/LabTerminal/mcp-reticle

What I’d love to hear from you:

  • edge cases you hit in real MCP integrations
  • which clients deserve first-class support
  • what exports or integrations matter most (CI, traces, audits, etc.)

If MCP is going to be the “USB-C for tools”, we need the equivalent of DevTools and Wireshark — not printf debugging and vibes.

Reticle is my attempt to make MCP debugging… not suck.

Top comments (0)