MCP Inspector: how to debug and test your MCP server
When a tool you wrote doesn't show up in Claude, the MCP Inspector is the first thing I reach for. It's the official tool for testing MCP servers, and it answers the one question that matters before anything else: did your tools actually register? A malformed schema can make a server start cleanly and expose zero tools, with no error anywhere. Here's how to run the Inspector, what each panel is for, and the silent failures it catches.
What the MCP Inspector is
The MCP Inspector is the official interactive tool from the Model Context Protocol project for testing and debugging MCP servers. You point it at your server's run command and it gives you a browser UI to list and call tools, inspect resources and prompts, and watch the raw protocol messages go back and forth. It's a client that does nothing but show you exactly what your server exposes.
That last part is why it matters. When you connect a server to Claude Desktop or Claude Code and a tool
doesn't appear, the client tells you almost nothing. The Inspector sits in the same seat the model
would, speaks the same protocol, and shows you the truth: the tool list, the schemas, the errors, the
notifications. If the Inspector can't see your tool, neither can Claude, and now you know that in
seconds instead of guessing at a config file. The project lives at
github.com/modelcontextprotocol/inspector.
How to run it
Run it with npx and pass your server's command as arguments. There's nothing to install.
It starts a local UI at http://localhost:6274 and a proxy that talks to your server over
stdio.
The bare command launches the UI with no server attached, so you'd connect one from the form. More useful is to hand it your server command directly. For a Python server, that's the same command you'd put in a client config:
npx @modelcontextprotocol/inspector python server.py
Most real servers need credentials or arguments. Pass environment variables with -e, and
use -- to separate the Inspector's own flags from the ones meant for your server:
npx @modelcontextprotocol/inspector \
-e SHOPIFY_DOMAIN=my-store.myshopify.com \
-e SHOPIFY_ACCESS_TOKEN=shpat_xxx \
-- python server.py --verbose
On launch it prints a session token and tries to open your browser with that token already filled in.
The token is auth for the local proxy, so the page won't connect without it. If you open the UI by hand,
copy the token from the terminal. There's a DANGEROUSLY_OMIT_AUTH escape hatch, and the
name is the documentation: leave it alone unless you have a specific reason.
6274 and the proxy on 6277. If
something else owns those ports, set CLIENT_PORT and SERVER_PORT in the
environment before the command. Two ports, not one, trips people up the first time.
What each panel does
The Inspector has five areas: a server connection pane, a Resources tab, a Prompts tab, a Tools tab, and a Notifications pane. The Tools tab is where you'll spend most of your time, and the Notifications pane is where you'll find out why something broke.
Each one maps to a capability your server can expose, so the UI is a direct mirror of the protocol:
| Panel | What it shows |
|---|---|
| Server connection | Pick the transport and, for local servers, edit the command and environment before connecting. |
| Tools | Every registered tool, its input schema, and a form to call it with custom arguments and see the result. |
| Resources | Available resources with their MIME types and descriptions, plus content inspection and subscription testing. |
| Prompts | Prompt templates with their arguments, so you can fill them in and preview the generated messages. |
| Notifications | Logs and notifications the server emits. This is your error console. |
The Tools tab does the thing a unit test can't: it calls your tool through the actual protocol, with the schema the model would see, and shows you the raw result. If an argument is typed wrong in your schema, the form makes it obvious, because the field it generates won't match what your function expects.
The first check: did your tools register?
Open the Tools tab and count. If your server should expose six tools and the list shows zero, the server is running but registered nothing, and that's almost always a schema problem, not a connection problem. This is the single most valuable check the Inspector does, because this failure is silent everywhere else.
We hit this for real. A tool used a Zod transform in its schema, and the transform broke registration in a way that threw no error: the server booted, connected, and exposed an empty tool list. In the client it looked like the server "wasn't working." In the Inspector it took ten seconds to see the count was zero, and from there the cause was a short hop. Swapping the transform for a preprocess step fixed it. Without the Inspector we'd have been reading config files looking for a problem that wasn't in the config at all.
This is why I treat the tool count as the first signal, before I test any individual call. A server that connects tells you the transport works. It tells you nothing about whether your tools survived schema generation. The Inspector separates those two questions, and most "my MCP server doesn't work" reports are really the second one.
The bugs it catches
The Inspector is built for the failures that produce no stack trace: zero tools registered, a schema the client can't parse, a tool that throws only when called with real arguments, and auth errors that look like an empty server. These are the ones that waste an afternoon if you debug them by squinting at a client.
Four show up again and again:
- Zero tools registered. The server starts, the list is empty. Covered above, and it's the most common one by a wide margin.
- A malformed input schema. The tool appears but the form is wrong, or calling it returns a protocol error instead of a result. The Tools tab shows the schema the client actually received, which is often not the one you think you wrote.
- A tool that throws on a real call. It registers fine and fails only when invoked, usually because the underlying API call errors. The Tools tab runs the real call and the Notifications pane shows the error your function raised.
- An auth or environment failure. A missing token makes a server look empty or makes every call fail identically. Because you set the environment right in the connection pane, you can change one variable and reconnect to isolate it.
None of these throw an error in the client. That's the whole reason the tool exists. The protocol allows a server to come up healthy and expose nothing, so "it connected" and "it works" are different claims, and only one of them is easy to check by hand.
CLI mode for scripts and CI
The Inspector also runs headless with --cli, which is what you want in continuous
integration. You can list tools or call one from the command line and assert on the output, no browser
involved.
Listing tools from the CLI is the automated version of the zero-tools check. Run it in CI and fail the build if the count is wrong:
npx @modelcontextprotocol/inspector --cli python server.py --method tools/list
You can call a specific tool too, passing arguments as key-value pairs:
npx @modelcontextprotocol/inspector --cli python server.py \
--method tools/call --tool-name greet --tool-arg name=world
The CLI mode covers the same methods as the UI: tools/list, tools/call,
resources/list, and prompts/list. I keep a tools/list assertion
in CI for every server we run, because the schema bug that registers zero tools is exactly the kind of
thing that slips through a green test suite and only surfaces when a client connects.
A debugging workflow that works
Connect, count the tools, then call the broken one and read the Notifications pane. That order isolates the failure fast: connection first, registration second, the individual call last. Most problems announce themselves at step two.
The sequence I use, in order:
- Launch the Inspector with your real run command and environment. If it can't connect at all, the problem is the command or the transport, and you've ruled out everything downstream.
- Open the Tools tab and count. Zero means a registration or schema failure. The right count means your tools survived, and you can move on to behavior.
- Call the tool that's misbehaving with real arguments. The form uses your actual schema, so a wrong field type shows up here.
- Read the Notifications pane. Server-side errors and logs land here. This is usually where the real cause is printed in plain text.
- Change one thing and reconnect. Edit an environment variable in the connection pane, reconnect, and re-test. One variable at a time keeps the signal clean.
This is also the right time to learn the Inspector, before you need it. If you're about to build an MCP server in Python, run the Inspector against the minimal version on day one, while the surface is small enough that any change you make is easy to attribute. By the time the server exposes a dozen tools and reads three credentials, the Inspector is the difference between a ten-second diagnosis and an afternoon.
The protocol is designed to fail quietly: a server can be healthy and useless at the same time. The Inspector is the tool that makes that state visible. Count the tools first, and most of your MCP debugging is already done. If you want to put a server like this to work across real client accounts, that production layer is what we build at Scalably.
Pavle Lazic is the founder of Scalably, where he builds and runs multi-tenant Claude agent platforms in production for real businesses. He writes about the Claude Agent SDK, MCP servers, and what it actually takes to put AI agents to work. See the platform.