Large Language ModelsGenerate imagesGenerate videos
MCP Inspector npx and CLI: How to Test an MCP Server
MCP Inspector v2 plays the client so you can test an MCP server on its own. This article shows how to launch it with npx, pass arguments and environment variables, use a config file, call tools from the CLI with JSON arguments, read exit codes, run checks in CI with jq, and fix stdout and transport errors.
An MCP server can start without a single error and still be useless. The process is running, the log is quiet, and the client you plug it into shows an empty tool list or a vague "failed to connect" message. Before you blame the client, test the server on its own. MCP Inspector is the Model Context Protocol project's own tool for that job: it plays the role of the client, performs the handshake, and lets you list and call everything your server exposes. This article shows how to launch it with npx, how to drive it from the CLI, how to read its exit codes, and how to fix the errors that waste the most time.
💡 Version check: Most tutorials online describe Inspector v1. The latest release on npm at the time of writing is 2.9.0, and v2 changed ports, environment variables, flags and exit codes. Every command below follows the v2 documentation.
What MCP Inspector Does
Inspector is an MCP client built for debugging. It starts your server (stdio) or connects to it (HTTP or SSE), runs the initialize handshake, and shows you exactly what comes back. There is no language model in the loop, so when something fails you know the fault sits in the server or the connection, not in prompt behavior.
The Handshake It Checks
The first call, initialize, proves that the server speaks MCP. The reply carries four things worth reading line by line:
serverInfo: the name and version your server reports.
protocolVersion: the protocol revision both sides agreed on.
capabilities: which features exist, such as tools, resources and prompts.
instructions: optional text the server hands to clients.
If capabilities has no tools entry, no client will ever show a tool, however many you registered in code. That single check explains a large share of "my tools don't appear" reports.
Web UI, CLI, and TUI
One package, three front ends. The mode flag must come first, right after the package name.
Mode
Command
Best for
Web UI
npx @modelcontextprotocol/inspector
Poking at a server by hand
CLI
npx @modelcontextprotocol/inspector --cli
Scripts, quick checks, CI
TUI
npx @modelcontextprotocol/inspector --tui
Staying inside the terminal
Use the web UI while you build, and the CLI when you need an answer you can repeat.
Launch It With npx
There is nothing to install. npx downloads the package, runs it, and passes everything after the package name to the server you want to test. A sensible first run takes one line and one minute.
Node Version and Ports
v2 needs Node.js 22.19.0 or newer. Run node --version before anything else, because an older runtime is the first thing to rule out.
Port and variable changes bite people who follow older posts, so here is the short comparison:
Setting
Inspector v1
Inspector v2
Node.js
22.7.5 or newer
22.19.0 or newer
Web UI port
6274
6274
Proxy port
6277
Removed, there is no proxy
Auth token variable
MCP_PROXY_AUTH_TOKEN
MCP_INSPECTOR_API_TOKEN (old name still works as a fallback)
Config file
--config, read only
--config (read only) or --catalog (writable)
Tool arguments
--tool-arg
--tool-arg and --tool-args-json
Failing tool call
The shell chain kept going
Exit code 5 stops it
Change the web UI port with CLIENT_PORT, a fixed integer between 1 and 65535. v2 also reserves 6275 for the MCP Apps sandbox and 6278 for the app-origin server, so keep both free.
A TypeScript server without a build step works the same way, for example npx @modelcontextprotocol/inspector tsx src/index.ts. Most projects wrap the line in an npm script so the whole team runs the same command:
💡 The double dash flips meaning. In web and TUI mode, everything after -- goes to your server. In CLI mode, everything before -- is the target and everything after it is an Inspector option. In CLI mode the server command must also come first: --cli --method tools/list node build/index.js silently drops the target.
The Token Behind the UI
v2 creates a random API token on every launch and requires it on every /api/* route. A page opened without it is rejected. Set MCP_INSPECTOR_API_TOKEN yourself if you want a stable value, and relaunch if a tab complains, because the old token died with the old process.
The web server binds to 127.0.0.1 by default through HOST. Opening it to other interfaces takes an explicit DANGEROUSLY_BIND_ALL_INTERFACES, and DANGEROUSLY_OMIT_AUTH=true switches the token check off entirely. Inspector starts local processes on your behalf, so treat the token like a password and keep both overrides out of shared machines.
Use a Config File
Typing the command gets old once a server needs three arguments and two environment variables. Put them in a file and select the server by name. Two flags exist, and they exclude each other:
Flag
Written by Inspector
If the file is missing
--config <path>
No, read only
Error
--catalog <path>
Yes, editable in the web UI
Created and seeded
The default catalog lives at ~/.mcp-inspector/mcp.json. Neither flag can be combined with an ad-hoc target on the same command line.
Keep command and each item of args as separate entries. Inspector spawns them directly instead of joining them into one string, which preserves argument boundaries when a path contains spaces.
--server only selects a server in CLI mode. The web client warns and ignores it when you load a file, and the TUI rejects it as an unknown option.
Test an MCP Server From the CLI
CLI mode skips the browser and prints the reply on stdout, which makes it the right tool for quick checks and for anything you want to automate. Every command has the same shape: the target first, then --method, then whatever that method needs.
List Tools First
Always start by asking what the server thinks it offers:
Swap the method for resources/list or prompts/list to check the other two features. A remote server needs an address and a transport, and a bearer token if it is protected:
Compare the names in the output with what your client expects. A tool that is registered as generateImage but requested as generate_image is a classic, and it only takes one command to spot.
Call a Tool With JSON Arguments
npx @modelcontextprotocol/inspector --cli node build/index.js \
--method tools/call \
--tool-name generate_image \
--tool-args-json '{"prompt":"a ceramic mug on an oak desk, soft window light","aspect_ratio":"16:9"}'
--tool-args-json takes one JSON object and applies no coercion, so numbers stay numbers and booleans stay booleans. For a quick test, --tool-arg prompt="a red door" is shorter, but its values are parsed as JSON when they are valid, so a string that looks like a number becomes a number. When types matter, use the JSON form.
💡 Windows note: Windows PowerShell 5.1 strips the inner double quotes of JSON passed to native programs. Escape each one with a backslash, or fall back to --tool-arg for short values.
Read the Exit Codes
The CLI reports the outcome in its exit code, so a script never has to scrape text to know what happened.
Code
Meaning
0
Success
1
Usage error or unexpected failure
2
No MCP App found (--app-info probe)
3
Authentication required
4
Server unreachable: DNS, timeout or refused connection
5
Tool returned isError: true, or the tool was not found
6
Schema portability error with --strict
Code 5 matters most for testing. A tool that fails cleanly now fails the command, so inspector --cli ... && next-step stops where v1 would have carried on. Connections give up after 15 seconds by default for ad-hoc runs, and --connect-timeout <ms> raises that limit when your server loads a database or a model at startup.
Run Inspector Checks in CI
A useful smoke test asserts four things: the server connects, the tool exists, a valid call succeeds, and an invalid call fails. Four commands, no browser, and a broken release never reaches users.
Pin the Version
Pin an exact version in CI, never a range such as @2.x, because flags and exit codes changed between major releases:
Add --format json and the CLI prints one JSON object with a result field, ready for jq. Two traps are worth knowing. Never merge stderr into stdout with 2>&1 while parsing, because diagnostics land inside the JSON. And capture the exit status before piping, because a pipeline reports the status of its last command, which hides a failed CLI behind a happy jq.
#!/usr/bin/env bash
set -u
INSPECT="npx --yes @modelcontextprotocol/inspector@2.9.0 --cli node build/index.js"
# 1. The handshake works
$INSPECT --method initialize --format json > init.json || exit 1
# 2. The tool exists (status captured before the pipe)
tools=$($INSPECT --method tools/list --format json); code=$?
[ "$code" -eq 0 ] || { echo "tools/list failed with $code"; exit "$code"; }
echo "$tools" | jq -e '.result.tools | map(.name) | index("generate_image")' > /dev/null || exit 1
# 3. A valid call succeeds
$INSPECT --method tools/call --tool-name list_models --tool-args-json '{}' \
--format json > call.json || exit 1
# 4. An invalid call fails
if $INSPECT --method tools/call --tool-name generate_image --tool-args-json '{}' \
> /dev/null 2>&1; then
echo "tool accepted empty input"; exit 1
fi
The fourth check is the one people skip. A server that accepts a missing prompt and returns a blank image will pass every positive test you write.
Fix the Errors You Will See
Most failures fall into a handful of patterns. Match the symptom first, then read the section that explains it.
Symptom
Likely cause
Fix
Exit code 4, connection timeout
The server crashed on start or boots slowly
Run the server command alone, then raise --connect-timeout
Handshake dies with parse errors
Something printed to stdout
Send logs to stderr
Transport error on a URL
The path does not end in /mcp or /sse
Add --transport http or --transport sse
Exit code 3
The server wants a token or sign-in
Pass --header, and use --stored-auth-only in CI
Exit code 5
Tool error, or a wrong tool name
Run tools/list and copy the exact name
UI rejects the page
Stale API token
Relaunch Inspector to get a fresh one
Stdout Pollution on Stdio
The stdio transport carries its JSON-RPC messages on stdout, and the protocol says a server must not write anything there that is not a valid MCP message. One stray console.log, a startup banner, or a dependency printing a warning corrupts the stream. The handshake then fails with parse errors or simply hangs.
Fix it by sending every log line to stderr (console.error in Node, sys.stderr in Python). To hunt the culprit, run the server command by itself: a healthy stdio server prints nothing until a client speaks to it.
Transport Not Detected
v2 no longer guesses. It infers the transport only when the URL path ends in /mcp or /sse, and anything else needs the flag spelled out:
When an error message means nothing to you, paste the stderr output and your tool schema into Claude Sonnet 5 or GPT 5.6 Sol and ask for the three likeliest causes. Both read stack traces well, and you still verify the answer with Inspector.
Testing an Image Generation Server
Servers that make media behave differently under test. Calls are slow, they can cost money, and the work usually runs in the background. PicassoIA's developer API shows the pattern clearly. It is Replicate-style: you create a prediction with POST /v1/models/{owner}/{name}/predictions on https://api.picassoia.com/v1, authenticate with a bearer token, poll GET /v1/predictions/{id}, and read the result when it finishes.
At the time of writing, the API and the MCP connection expose the same four models: PicassoIA Image, PicassoIA Image Editor Pro, PicassoIA Video and Seedance 2.5 Lite. An account allows 5 concurrent predictions, shared across tokens and MCP connections, with prompts of up to 4,000 characters.
💡 Test serially. A loop of tool calls in one Inspector session can fill all five slots and starve your real client. Run image tests one call at a time.
Async Tools Need a Status Tool
A tool that starts a job should return an ID within seconds, and a second tool should report progress. Test both halves on their own:
The start call returns quickly with an ID instead of holding the connection open for minutes.
The status call accepts that ID and reports a progress state and a final state.
A failed job comes back as a result with isError: true, not as a call that hangs.
A bad ID produces exit code 5, not a crash of the server process.
The output URL answers with status 200 and an image content type when you fetch it.
That last check is the cheapest one, and it catches the failure readers notice first: a broken image on a published page.
Make Your First Image Next
You now have a way to prove that a server works before anyone depends on it. The same habit pays off on the creative side: run a small test, read the result, and change one thing at a time.
Open Picasso IA and try the loop yourself. Write a one-sentence prompt in PicassoIA Image, refine the result with PicassoIA Image Editor Pro, then bring the still to life with PicassoIA Video. Change the lens, the light or the subject between runs and compare the outputs side by side. Five commands from this article are worth keeping next to your terminal:
--method initialize to confirm the handshake.
--method tools/list to confirm the tool names.
--method tools/call --tool-args-json to confirm the behavior.