Here is a non-exhaustive list of things that are now MCP tools in my daily workflow: NotebookLM notebooks. Google Sheets. A Playwright browser. Datadog dashboards. MongoDB queries. Jira and Confluence. kubectl. Who needs a babysitter, when I can connect my tamagotchi to an LLM over USB-C.
Every one of these integrations was built iteratively, tested live, and debugged from inside the same AI conversation that uses them. I liked the idea of exposing things as tools to AI the moment I heard it. Then you can abstract away a lot of the predictable and complex parts like injecting a cluster name into a kubectl command. But the problem is, it is pretty tricky to build that many tools each with their own individual needs.
That is why I have constructed a mcp server that can be used to connect to any mcp server. It was inspired by mcp-inspector initially, so I named it mcp-inspector-as-mcp-server. It's 400 lines of TypeScript and the MCP SDK is its only dependency. It is a simple tool but it really changed my mental model of tool building.
"One tool to test them all"
MCP is a good protocol with a terrible development experience.
Because MCP is a relatively new protocol with multiple transports, and JSON-RPC among them is a particularly problematic one to debug, it can be quite frustrating to develop an mcp server over the regular mcp-inspector through trial and error. In the age of AI, I want to be able to let my AI assistant loose on the broken draft, give it the response body I am going for, and have it iterate over the code until the nuts and bolts are set up correctly for it to run.
The idea is simple enough to fit in a sentence: make the MCP Inspector itself an MCP server, so your AI assistant can inspect and test other MCP servers from inside the conversation where it's going to use them.
This enables you to have the agent connect to a server, list and call the tools and observe the error messages within the context of a single chat.
You: "Connect to the new pricing MCP server and test the rate lookup tool"
Claude: [calls insp_connect] -> session established
[calls insp_tools_list] -> 14 tools found
[calls insp_tools_call: get_rate] -> works, returns rate object
[calls insp_tools_call: get_rate with bad input] -> 500, missing field validation
"Rate lookup works but crashes on missing fields. Want me to fix the server?"
That is essentially the entire development loop without a context switch.
Sessions that survive
Similar to ye olde HTTP calls, MCP tool calls themselves are stateless, but the server behind may or may not be. That's why the tool is designed with sessions so that servers where tool calls mutate the state can also be tested. insp_connect returns a session_id that subsequent calls reuse, with a 30-minute idle TTL and automatic garbage collection handling the lifecycle.
The same tools also work without a session ID for quick one-off inspections, so both stateful debugging and ephemeral checks go through the same interface.
The event buffer
Every session wraps its transport in a tracing layer that captures all traffic into a ring buffer of 1000 events. JSON-RPC messages in and out, notifications, errors, all in order.
[calls insp_read_events with session_id, types: ["error"]]
-> 3 errors in last 5 minutes:
1. "Invalid params: expected string for 'shipmentId', got number"
2. "Timeout after 30s on get_shipment_360"
3. "Connection reset during batch operation"
This turns "it doesn't work" into a timeline of exactly what went wrong. The ring buffer keeps memory bounded even in long sessions since oldest events drop when it fills, so you lose ancient history but never run out of memory.
The implementation required solving a timing bug in the MCP SDK: the Protocol class sets handler callbacks after calling transport.start(), which means any wrappers you set in start() get overwritten. The fix was using JavaScript getters and setters to intercept handler assignment dynamically. The SDK sets the handler, our setter wraps it with tracing, and forwards the wrapped version. Clean, no SDK patches required.
Steering from the outside
This bit is low key pretty chill:
When an AI assistant is testing an MCP server, sometimes you want to nudge it without interrupting the conversation flow. Try the error path. Focus on that timeout. Skip auth, I'll fix it later.
The inspector has a steering mechanism. A simple FIFO queue per session. You inject a message, either through the insp_inject_steering tool or via a tiny HTTP API on port 9847. It gets delivered on the next tool response as a second content block.
# From your terminal, while the AI is working:
./mcp-steer "skip the auth tests, focus on rate compilation"
The AI's next tool call comes back with two blocks: the actual result, and your steering message prefixed with a lightning bolt. If you remembered that "oh you need to call the rate update before you reprice the line items," you do not need to interrupt the agent and type this. You can simply inject the steering message.
Although my initial instinct was to overdesign with websockets and streaming, I ended up going simple when it comes to steering. Queue up, drain on next call. The simplicity is the point. Steering doesn't need to be real-time. It needs to be reliable and not add complexity to the MCP protocol itself.
Why this matters beyond debugging
Once you have a tool that can connect to any MCP server with full observability, iterative integration becomes possible almost for free.
You get the rough draft together, tell the AI "a success response should look like this," and let it loop. Test, find the bug, fix, restart, repeat.
And because the inspector handles all three MCP transports (stdio for local processes, SSE for remote servers, streamable HTTP), it actually covers majority of the possible use cases in its niche. Local dev server, remote environment behind an API, or if you're into suffering, even SSE.
This is what made the absurd integration list at the top of this article possible. Each of those was an afternoon of iterative development with the inspector keeping the feedback loop tight. The inspector removes the overhead that makes "just slap an MCP layer on it" feel daunting.
The meta-tooling thesis
As tool ecosystems grow you inevitably need tools about tools. MCP, though flawed, seems to have become the norm as it was intended to be from the beginning, and in the same way you need a debugger for your code and an inspector for your network requests, you need an inspector for your tool layer.
If you're building MCP servers, this is something I'd absolutely recommend. While far from being a silver bullet, it very reliably solves one specific and very common problem.
400 lines. One dependency. Give it a go. E-mail me if you like it. I will definitely get back 60% of the time.