Inspecting a server with mcp dev
The MCP Inspector is a developer tool that connects to a server and shows its tools, resources and prompts, so you see what a server offers before any model does.
Last updated: 28 Sep, 2026 · MCP 2.2
You have built a server and called it from code. Before you connect a server to a host, you want to see what it exposes and try a tool by hand. MCP gives you two ways to do that: the Inspector web app launched by mcp dev, and the same listing calls from your own code.
The mcp dev command
mcp dev loads your server file and opens the Inspector, a local web app, in your browser. There you pick a tool, fill its arguments in a form, and read the result, with no host and no model involved. It needs the [cli] extra from the setup lesson and Node.js for the web app, so it is shown here as a command rather than captured output.
mcp dev shop.pyThe page lists the server's tools, resources and prompts, and lets you call each one and watch the JSON-RPC messages go back and forth. It is the MCP counterpart of a run transcript: a window on what the server did.
Listing a server in code
The same four listing calls the Inspector makes are methods on the in-memory client. They run keyless, with no browser, so they belong in a small script you can keep.
tools = await client.list_tools()
resources = await client.list_resources()
templates = await client.list_resource_templates()
prompts = await client.list_prompts()Inspecting the shop server in code
Run the four listings against the server as it stands after the last lesson: one tool, with no resources or prompts yet.
import asyncio
from mcp import Client
from shop import mcp
async def main():
async with Client(mcp) as client:
tools = await client.list_tools()
print("tools:", [t.name for t in tools.tools])
resources = await client.list_resources()
print("resources:", [str(r.uri) for r in resources.resources])
templates = await client.list_resource_templates()
print("templates:", [t.uri_template for t in templates.resource_templates])
prompts = await client.list_prompts()
print("prompts:", [p.name for p in prompts.prompts])
asyncio.run(main())What the listing shows now
- tools holds
lookup_order, the one tool registered so far. - resources and templates are empty until Resources: data an application loads and Resource templates: one function for many URIs add them.
- prompts is empty until Prompts: templates a user picks adds one. Run this script again after those lessons and the same four lines fill in.
Reading one tool's schema
Listing gives more than names. Each tool carries its description and input schema, the same fields a host reads to decide when and how to call it.
import asyncio
from mcp import Client
from shop import mcp
async def main():
async with Client(mcp) as client:
tools = await client.list_tools()
for tool in tools.tools:
print(tool.name, "-", tool.description)
print(" args:", list(tool.input_schema["properties"]))
asyncio.run(main())The Inspector vs listing in code
| mcp dev Inspector | Listing in code | |
|---|---|---|
| Runs where | A web app in your browser | In a Python script |
| Needs | The [cli] extra and Node.js | The mcp package only |
| Best for | Poking a server by hand | A repeatable check you save |
| Calls a tool | Through a form you fill | With call_tool |
When to inspect a server
- Right after adding a tool, to confirm its name, description and arguments are what you meant.
- Before connecting a server to Claude Code or another host, to see what that host will be offered.
- When a host cannot see a tool, to check whether the server lists it at all.
mcp dev loads your server file, so an error while importing it means the Inspector shows nothing until you fix the import. The in-memory listing fails the same way, which is why running it as a script catches the problem early.Related
- Previous: Client: connecting and calling a tool
- Next: Tool arguments: descriptions, limits and choices
- Reference: MCP Inspector
- Add a
count_orders() -> inttool toshop.pyand run the listing again. - Run
mcp dev shop.pyif you have the[cli]extra and Node, and calllookup_orderfrom the form. - Break an import in
shop.py: mistypeMCPServer, run the listing, and read the error.
Every expert started right here.