Every MCP server goes through the same question before anyone installs it: does it actually answer? The MCP Inspector is the official way to find out. You point it at a server, it connects the way a real client would, and you see every tool, resource and prompt the server offers, with a form to call each one.
Most guides still describe version 1, with its two ports and proxy token. Version 2 is now the latest release on npm, and enough changed that v1 instructions mislead. We ran everything below on 14 November 2026 with Inspector 2.15.0 on macOS: the web UI, the command line against the official server-everything test server, and a protected Streamable HTTP server we built in our Next.js MCP guide.
Three ways to run it
| Mode | Command | Use it for |
|---|---|---|
| Web UI | npx @modelcontextprotocol/inspector |
Exploring a server by hand: list tools, fill in arguments, read results |
| CLI | npx @modelcontextprotocol/inspector --cli ... |
Scripts, tests and CI: JSON output and exit codes |
| Terminal UI | npx @modelcontextprotocol/inspector --tui |
The same exploring as the web UI, without a browser |
The mode flag comes right after the package name. A fourth entry point, mcpdo, is experimental: it connects once and runs many commands through a local daemon.
What changed in version 2
If you have used the Inspector before, this table saves an hour:
| Version 1 | Version 2 | |
|---|---|---|
| Ports | UI on 6274, proxy on 6277 | One server on 6274; MCP Apps sandbox on 6275 |
| Token variable | MCP_PROXY_AUTH_TOKEN |
MCP_INSPECTOR_API_TOKEN (old name still read, deprecated) |
| Config file | --config read and written |
--config read-only; --catalog is the writable list, default ~/.mcp-inspector/mcp.json |
| Saved servers | Browser storage | The catalog file, shared by web, CLI and TUI |
| Secrets | Browser | OS keychain, or ~/.mcp-inspector/secrets.json where there is none |
| Tool error in CLI | Exit code 0 | Exit code 5 |
| OAuth in CLI | No | Yes |
| Bind to all interfaces | Allowed | Refused unless DANGEROUSLY_BIND_ALL_INTERFACES=true |
| Node.js | 22.7.5 or later | ^22.23.4, ^24.22.1 or >=26.12.1 |
| npm tag | v1-latest (1.0.5) |
latest (2.15.0) |
The four separate npm packages of v1 (inspector-client, inspector-server, inspector-cli) are frozen at 1.0.1 and deprecated. Everything is in @modelcontextprotocol/inspector now.
One trap we hit on day one: npx reused a cached 2.13.0 even though 2.15.0 was out. Use @latest when you want the current release:
npx -y @modelcontextprotocol/inspector@latest
The web UI
Start it with no arguments to choose a server in the browser, or with your server's command to connect straight away:
npx @modelcontextprotocol/inspector node build/index.js
For a Python server, put the uvx or uv run command there instead. On our machine the launcher printed:
MCP Inspector Web is up and running at:
http://127.0.0.1:6274?MCP_INSPECTOR_API_TOKEN=<token>
Sandbox (MCP Apps): http://127.0.0.1:6275/sandbox
Secrets: OS keychain
Open that link with the token in it. The token is new for every launch, and the browser sends it on every call to the Inspector's own API. Without it, the page cannot talk to the backend. That token is the fix for the 2025 vulnerability described further down, so do not turn it off unless you know why.
We checked what was listening while it ran: 127.0.0.1 on ports 6274, 6275 and 6278. Nothing on all interfaces, and nothing on the old 6277.
In the UI, connect to the server, open the tools list, pick a tool, fill in the generated form and run it. The result panel shows exactly what a client would receive, including isError and structured content. Resources and prompts have their own lists. For remote servers, enter the URL, pick Streamable HTTP, and add headers or OAuth settings per server; v2 removed v1's single bearer-token field in the sidebar.
If port 6274 is taken, set CLIENT_PORT, and MCP_SANDBOX_PORT for the sandbox.
The CLI: what we ran
The command line does everything the UI does and prints JSON, which makes it the better tool once you know what you want to check.
List the tools of a stdio server:
npx @modelcontextprotocol/inspector --cli npx -y @modelcontextprotocol/server-everything --method tools/list --format json
Against server-everything, the official test server, this returned 17 tools, from echo and get-sum to trigger-long-running-operation. Call one with arguments as JSON:
npx @modelcontextprotocol/inspector --cli npx -y @modelcontextprotocol/server-everything --method tools/call --tool-name get-sum --tool-args-json '{"a":2,"b":3}' --format json
The output was one line:
{"result":{"content":[{"type":"text","text":"The sum of 2 and 3 is 5."}]}}
For a remote server, give the URL and the transport. Our protected test server needed a bearer token, passed as a header:
npx @modelcontextprotocol/inspector --cli --transport http --server-url http://localhost:3417/api/mcp --header "Authorization: Bearer <token>" --method tools/list --format json
The transport is only guessed for URLs that end in /mcp (Streamable HTTP) or /sse (the old SSE transport). For any other path, pass --transport yourself; v1 quietly defaulted to SSE, which caused a lot of confusing failures.
Other methods follow the same shape: resources/list, resources/read, prompts/list, prompts/get, and in v2 also initialize, servers/list and servers/show.
Exit codes
This is where v2 is most useful for automation. Each kind of failure has its own code, and the error comes as JSON on stderr. These are the ones we triggered:
| Code | Meaning | What we did | What it printed |
|---|---|---|---|
| 0 | Success | Called get-sum |
The result |
| 3 | Authentication failed or required | Called our protected server with no token | {"error":{"code":"auth_required",...}} |
| 4 | Server unreachable | Pointed at a closed port | {"error":{"code":"unreachable","message":"fetch failed","cause":"bad port"}} |
| 5 | Tool error or tool not found | Called a tool named nope |
{"error":{"code":"tool_not_found","message":"Tool 'nope' not found on server."}} |
The documented list also has 1 for usage errors, 2 when a tool has no MCP App, 6 for schema portability problems under --strict, 11 when the server rate-limits with HTTP 429, and 12 when the OAuth guard refuses a URL.
The auth case is worth a closer look. With no token, the CLI did not just fail: it tried to start an interactive OAuth sign-in and stopped because there was no terminal to show it in. In a pipeline that is what you want, and --stored-auth-only makes it fail fast without trying.
Using it in CI
Put a smoke test in front of every release of your server. With --format json and jq, a missing tool fails the build:
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list --format json | jq -e '.result.tools | map(.name) | index("search_posts")'
jq -e exits non-zero when the tool is missing, and the Inspector's own exit code catches the rest: a crash at start-up is 1 or 4, a tool that throws is 5. That covers the failures that matter before a user ever sees them: the server does not start, a tool vanished in a refactor, or a tool errors on valid input.
For servers behind OAuth, sign in once on a developer machine, then run CI with --use-stored-auth or --stored-auth-only, so nothing waits for a browser.
Config files and the catalog
v2 reads the same mcpServers JSON that Claude Desktop, Cursor and most clients use, so you can test exactly what users will run:
npx @modelcontextprotocol/inspector --cli --config ./mcp.json --server everything --method tools/list
Two rules changed. --config is now read-only and fails if the file does not exist. And --server, which picks one entry from the file, works only under --cli; the web UI loads every entry.
The catalog is the Inspector's own writable list, at ~/.mcp-inspector/mcp.json unless MCP_CATALOG_PATH says otherwise. Servers you add in the web UI are saved there, and the CLI and TUI see them too. Per-server settings such as requestTimeout, the new connectionTimeout, roots and OAuth also live there.
When the Inspector cannot connect
| Symptom | Likely cause | Fix |
|---|---|---|
| A stdio server connects, then the session dies | The server prints logs to stdout | Log to stderr; over stdio, stdout is for protocol messages only |
unreachable, exit 4 |
Wrong port or path, server not running | Run the server on its own first, check the URL |
| Remote server fails with a strange protocol error | Wrong transport guessed | Pass --transport http for paths that do not end in /mcp |
auth_required, exit 3 |
Token or OAuth needed | --header "Authorization: Bearer ...", or sign in once and use stored auth |
| The UI loads but every action fails | Opened without the token in the URL | Use the full link the launcher printed |
| An old version runs | npx cache |
@latest, or clear the npx cache |
| Port 6274 in use | Another Inspector still running | Stop it, or set CLIENT_PORT |
| Engine warning on install | Node.js older than the patched release | Upgrade Node; it ran on our 26.7.0, but the floor is 26.12.1 |
Security: what happened, and what to keep on
In June 2025, CVE-2025-49596 was published against the Inspector, rated 9.4, critical. Versions before 0.14.1 ran a local proxy that accepted requests without authentication. A malicious website could reach it from the developer's browser, including through DNS rebinding, and make it start processes on the machine. Version 0.14.1 added a per-launch session token and checks on the request origin.
Version 2 keeps those protections and tightens them:
- It listens on 127.0.0.1 only. Binding to
0.0.0.0or::is refused unless you setDANGEROUSLY_BIND_ALL_INTERFACES=true. - The per-launch token is required.
DANGEROUSLY_OMIT_AUTHturns it off only for the exact valuestrueor1; in v1 any non-empty value did. - OAuth tokens, client secrets and environment values for stdio servers go to the OS keychain. Where no keychain exists they go to
~/.mcp-inspector/secrets.json, which is not encrypted unless you supply a key, so keep that file out of shared machines and backups.
Three habits follow from this. Do not run Inspector releases from before 0.14.1, which some old tutorials still pin. Do not expose the Inspector on a network, and when you run it in Docker, keep 127.0.0.1: in front of the published port. And remember that connecting the Inspector to a server runs that server with your permissions, the same as installing it in a client. Read the code of a server you do not know before you connect it, or check its report: every server in the HostedMCP directory has automated checks on its repository, packages and tool descriptions.
For the wider picture of what can go wrong between clients and servers, see MCP security.