Skip to content

kerlenton/mcpsnoop

Repository files navigation

mcpsnoop

Wireshark for MCP. A transparent proxy that shows every real tool call between your AI client and your MCP servers, live in your terminal.

CI Go Reference MIT

mcpsnoop demo

The problem

The official MCP Inspector connects as its own client, so it never sees what your client (Cursor, Claude Code, Codex) actually sends your server. A breakpoint only fires once a request arrives, so it can't show the call the model never made, or made with the wrong arguments. When a tool silently isn't called, capabilities don't line up, or a call just hangs, you're left digging through logs and guessing.

mcpsnoop sits in the real data path instead. Wrap your server command with it and watch every JSON-RPC frame live, as your real client and server talk.

Quick start

See it right away, with nothing to set up.

mcpsnoop demo

To use it for real, wrap your server in your client's MCP config.

{
  "mcpServers": {
    "my-server": {
      "command": "mcpsnoop",
      "args": ["--", "node", "build/index.js"]
    }
  }
}

Everything after -- is the command that normally launches your server. Swap in whatever you already use, like python server.py, npx -y @scope/server, or a compiled binary. Then use your client as usual and open the UI.

mcpsnoop

No flags, no socket paths, no startup order to remember. The shim and the UI find each other on their own, and the UI backfills past sessions from disk.

For a streamable-HTTP server, run mcpsnoop as a reverse proxy.

mcpsnoop http --target http://localhost:3000/mcp --listen :7000

No server of your own? Try it for real against a published test server, driven by your own client. To inspect a session after it happened, see review past sessions from logs.

How it compares

MCP Inspector mcpsnoop
Sees your real client and server traffic no yes
Flags slow and hung calls no yes
Flags stray output that corrupts the stream no yes
Flags malformed JSON-RPC frames no yes
Interactive terminal UI no yes
Zero-config, no flags or ordering no yes
Capability inspector partial yes
Replay a captured call no yes
Session export (json / html / text / otlp) no yes
Single binary, no runtime deps no yes

Install

Go

go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest

Homebrew

brew install kerlenton/mcpsnoop/mcpsnoop

Prebuilt binaries for every platform are on the Releases page.

How it works

mcpsnoop sits in the pipe between your AI client and your MCP servers, copying every JSON-RPC frame to a live terminal UI

mcpsnoop is two roles in one binary. mcpsnoop -- <server> is the transparent shim your client spawns, forwarding bytes verbatim while shipping a copy of every frame to mcpsnoop with no arguments, the hub and TUI. They pair through a well-known socket and on-disk logs, so neither has to start first.

Because it sits in the actual pipe, not off to the side like the Inspector, it sees exactly what your real client and server say to each other, whatever the server is written in.

Keybindings

Key Action Key Action
enter inspect / drill in / filter
esc back : command
j / k move r replay a call
g / G top / bottom c capabilities
ctrl-f / ctrl-b page y copy
shift+column sort e export
p pause ctrl-d delete session
f follow ? help

Press ? in the app for the full list.

Filtering the stream

Press / in a session and combine space-separated tokens, ANDed. Plain text matches the method, tool, id, and payload.

Token Filters by Example
tool: tool name tool:search
method: JSON-RPC method method:tools/call
id: request id id:7
dir: direction (c2s, s2c) dir:s2c
kind: frame type (req, resp, notify, stderr, invalid) kind:invalid
status: call outcome (ok, error, slow, pending, bad, warn) status:slow

Stack tokens to get specific.

tool:search status:slow           # slow calls to one search tool
method:tools/call status:error    # tool calls that failed
dir:s2c kind:req                  # server-initiated requests (sampling, roots)

Exporting sessions

Turn any captured session into a portable file.

mcpsnoop export -T json|html|text|otlp [-o file|-] [session-id|log.jsonl]
Format What you get
json correlated calls, durations, status, tool-level isError, capabilities, and raw frames
html a self-contained browser file with search and collapsible JSON
text a pretty plain-text dump
otlp OTLP JSON with a trace per session and a span per correlated call
mcpsnoop export -T html -o out.html       # an HTML file to open in a browser
mcpsnoop export -T text server.py-48213   # a specific session, as text
mcpsnoop export -T json | jq              # the newest session, piped to jq
mcpsnoop export -T otlp -o trace.json     # import into an OTLP-compatible tracing backend

Omit -o to write to stdout, and omit the session to take the newest. In the TUI, press e to export the selected session as HTML, or run :export json|html|text|otlp [path] from command mode.

Watching from another machine

Keep capture local to the machine where the traffic happens and use SSH for the network hop, so mcpsnoop never needs a remote transport of its own.

Live view

Run the TUI on your workstation and forward the remote machine's mcpsnoop socket back to it. The socket path follows MCPSNOOP_HOME, XDG_STATE_HOME, and the remote home, defaulting to ~/.local/state/mcpsnoop/hub.sock.

# on your workstation, start the TUI
mcpsnoop

# create the remote socket directory once
ssh remote-user@remote-host 'mkdir -p ~/.local/state/mcpsnoop'

# print the tunnel command, then run the printed ssh -R line
mcpsnoop remote remote-user@remote-host

# on the remote host, wrap your server as usual
mcpsnoop -- node build/index.js

If the remote uses a non-default home or MCPSNOOP_HOME, pass it explicitly.

mcpsnoop remote --remote-home /Users/remote-user remote-user@remote-host
mcpsnoop remote --remote-mcpsnoop-home /srv/mcpsnoop remote-user@remote-host

Post-mortem

Stream a remote session straight into the TUI over SSH, no local copy needed.

ssh remote-user@remote-host 'cat ~/.local/state/mcpsnoop/sessions/session.jsonl' | mcpsnoop open -

To keep a local copy instead, scp the logs into your sessions directory and run the TUI as normal.

# copy the remote logs into your local sessions directory
mkdir -p ~/.local/state/mcpsnoop/sessions
scp remote-user@remote-host:'~/.local/state/mcpsnoop/sessions/*.jsonl' \
  ~/.local/state/mcpsnoop/sessions/

# open the TUI, it backfills the copied sessions
mcpsnoop

Security

mcpsnoop runs the server command you wrap, so only wrap servers you trust, and run untrusted ones in a container. It never executes anything you didn't put in your client config.

Captured frames can include prompts, tool arguments, credentials, and tool results. If payloads can carry secrets, opt in to redaction to scrub the observed trace copies while the proxied bytes still pass through unchanged. Key-based redaction replaces whole values under matching JSON object keys. Value-based redaction applies regular expressions to observed string values, stderr text, and non-JSON text frames. Both modes are best effort. Regexes can miss secrets, overmatch harmless text, or fail to see transformed or encoded values.

# built-in preset of common secret keys
mcpsnoop --redact-secrets -- node build/index.js

# or name your own keys
mcpsnoop --redact-key token,api_key,password -- node build/index.js

# scrub obvious token-shaped values outside known keys
mcpsnoop --redact-value 'sk-[A-Za-z0-9]+' -- node build/index.js

# combine the layers in http mode
mcpsnoop http --target http://localhost:3000/mcp --redact-secrets --redact-value 'Bearer\s+\S+'

For remote workflows, use SSH tunnelling or SSH file transfer so transport auth, encryption, host verification, key rotation, and audit policy stay in your existing SSH setup.

Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md for the details.

License

MIT

About

Wireshark for MCP. A transparent proxy that shows every real tool call between your AI client and your MCP servers, live in your terminal.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

245 stars

Watchers

2 watching

Forks

Packages

 
 
 

Contributors