
AI Tools Deep Dive
18 partsTL;DR
MCP servers are stdio-only black boxes. MCP Lens proxies the JSON-RPC stream, captures every frame, and serves a local inspector at localhost:4040.
Model Context Protocol is the connector format the entire agent ecosystem rallied behind. Claude Code uses it. Cursor uses it. Zed uses it. Most of the interesting integrations shipping in 2026 are MCP servers, not native plugins.
The transport everyone reaches for first is stdio. Spawn a subprocess, write newline-delimited JSON-RPC to its stdin, read responses from its stdout. Simple, portable, no port allocation, no auth dance. It is also completely opaque.
When something goes wrong in an MCP integration, your symptoms look like this. The host says the tool was called. The server logs nothing useful. The result is empty, or wrong, or the call hangs until the host times out. There is no devtools panel. There is no Network tab. The conversation between host and server is happening on file descriptors you cannot tap into without code changes on both sides.
I hit this wall four times in one week. A filesystem server returning paths that did not match what Claude thought it asked for. A custom search server quietly dropping the cursor argument because of a schema typo. A community server advertising a resources/list capability it never actually implemented. Every one of those bugs took an hour of squinting at logs to triage. None of them should have.
So I built a proxy.
MCP Lens sits between any MCP host and any stdio MCP server. The host thinks it is talking to the server. The server thinks it is talking to the host. In the middle, every JSON-RPC frame in both directions is timestamped, parsed, and appended to a JSONL log. Optionally, a tiny local web UI tails that log over server-sent events and renders the conversation as a two-pane timeline.
The pitch I keep coming back to is the obvious one. This is Wireshark for MCP. You cannot debug what you cannot see. MCP Lens makes the wire visible.
It does one thing. It captures stdio. That is the whole feature surface today, and the constraint is doing real work for the design.
The repo is private for now. Clone it, install, build.
pnpm install
pnpm build
The binary lives at dist/bin/mcp-lens.js and is exposed as mcp-lens if you npm link it. To wrap any MCP server, prepend the mcp-lens -- prefix to the command you would normally run:
mcp-lens --ui -- npx -y @modelcontextprotocol/server-filesystem /tmp
The double dash is load-bearing. Anything before it is a flag for MCP Lens. Anything after it is the real server command, spawned as a child process. MCP Lens pipes stdin and stdout bidirectionally, so the host above the proxy sees exactly the bytes the server emits, with no behavioural change.
Captures land in ./captures/session-<timestamp>.jsonl. Override with --out my-session.jsonl if you want a stable path. The format is one frame per line:
{
"ts": 1714329000123,
"dir": "client->server",
"raw": "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\"}",
"msg": { "jsonrpc": "2.0", "id": 1, "method": "initialize" }
}
raw is the exact bytes off the wire, msg is the parsed payload, dir tells you which side spoke. If a line is not valid JSON, msg is null and parseError carries the failure reason. That single detail has already paid for itself once: a server that was emitting a debug console.log to stdout corrupted its own JSON-RPC stream, and the parse error pointed at the offending line in seconds.
To wire it into Claude Code, edit your MCP config and replace the existing entry:
{
"command": "mcp-lens",
"args": ["--ui", "--", "npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
Restart the host. Everything still works. You now have a recording.
Get the weekly deep dive
Tutorials on Claude Code, AI agents, and dev tools - delivered free every week.
With --ui, MCP Lens boots a local server at http://localhost:4040. The page is intentionally boring. A frame list on the left, filterable by direction and free-text search. A detail pane on the right showing the full JSON-RPC payload with syntax highlighting. New frames stream in over SSE as the session continues, so you can watch a tool call happen as the host issues it.
The two filters that matter are dir:client->server and method:tools/call. Combine them and you have the exact list of every tool the host invoked, in order, with arguments. Click any frame and you see the matching response by id. That is roughly 80 percent of MCP debugging right there.
Three sessions from the last few days, all of them resolved in under five minutes once the wire was visible.
Wrong tool arguments. A custom GitHub search server kept returning empty arrays from inside Claude Code, but worked fine when I tested it manually. With MCP Lens running, I scrolled the timeline to the tools/call frame and saw the host had passed {"q": "..."} while the server's schema required {"query": "..."}. The host was silently coercing my prompt into the wrong argument name because the tool description had drifted from the schema. Fixed the description, restarted, gone.
Missing capability. A community-maintained MCP server advertised resources/list in its initialize response, then returned Method not found whenever the host actually called it. Without the proxy, this looked like the host being broken. With the proxy, the timeline made the contradiction obvious. The server's capabilities object was a copy-paste from a template, and the handler was never implemented. Filed an upstream issue with the JSONL attached.
Schema drift. This is the bug MCP Lens was born for. A self-hosted server changed its tools/call response shape from { content: [...] } to { result: { content: [...] } } between versions. The host kept showing empty tool results. Diffing two captures, one from the old version and one from the new, the structural change jumped out instantly. Until MCP Lens has built-in schema diff, jq is enough: jq -c 'select(.msg.method=="tools/call")' old.jsonl new.jsonl and your eye does the rest.
I am being deliberate about scope. MCP Lens does not, today, do any of the following.
Replay against a rebuilt server is not implemented. The capture format is replay-friendly by design, every frame has direction, raw bytes, and timestamp, but the harness to feed a captured client stream into a fresh server process is still a roadmap item. When it lands you will be able to rerun a bug-triggering session against a patched server without touching the host.
SSE and streamable-HTTP transports are not supported. Stdio only. Most MCP servers in the wild are still stdio, and tackling all three transports at once would have shipped nothing. The architecture is transport-pluggable, so HTTP transports are tractable, just not done.
Schema diff between two server versions, share-link export of a capture, and a tool-call timeline view with latency bars are all on the list. None exist yet. If you want any of them tomorrow, JSONL plus jq plus a few lines of Node will get you most of the way.
MCP Lens slots in next to a few other small tools I have been writing about this month. Promptlock makes the prompts you send to a model deterministic and reviewable. TraceTrail records full agent runs so you can rerun a session offline. Hookyard wires Claude Code hooks into pre and post events around your edits. MCP Lens covers the slice none of those touch: the bytes flowing between the host and the tools it actually uses.
If you are picking a stack for serious agent work in 2026, the comparison matrix is the right starting point. MCP Lens is not a model, not a framework, not a host. It is a debugger for the layer everyone forgot to build a debugger for.
Clone, build, wrap one MCP server, open localhost:4040, and watch your host talk. The first time you see a tool call you assumed was working actually fail in the timeline, you will understand why this thing exists.
Technical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.
Visual testing tool for Model Context Protocol servers. Like Postman for MCP - call tools, browse resources, and view...
View ToolLightweight CLI for discovering and calling MCP servers. Dynamic tool discovery reduces token consumption from 47K to 40...
View ToolCentralized manager for MCP servers. Connect once to localhost:37373 and access all your servers through a single endpoi...
View ToolRegistry and hosting platform for MCP servers. 6,000+ servers indexed. One-command install and configuration via CLI. Su...
View ToolConfigure model, effort, tools, MCP servers, and invocation scope.
Claude CodeConfigure Claude Code for maximum productivity -- CLAUDE.md, sub-agents, MCP servers, and autonomous workflows.
AI AgentsConfigure model, tools, MCP, skills, memory, and scoping.
Claude Code
Promptlock gives every prompt a 12-char content-addressable id and a diff-able artifact, turning silent prompt drift int...

Agent runs are opaque. TraceTrail turns a Claude Code JSONL into a public share link with a stepped timeline of messages...

Ten private tools shipped overnight - observability, skills, hooks, prompts, and evals - aimed at the agent infrastructu...

New tutorials, open-source projects, and deep dives on coding agents - delivered weekly.