Inspect an MCP server
Debug any MCP server with the built-in inspector — a web UI, a terminal UI and a scriptable CLI over one engine, pre-wired when you run it against a gateway.
An MCP server that "doesn't work" is almost never one failure. It is a tool that isn't listed, a call that comes back refused, a schema the client fills in wrong, or a frame that never arrives. Each of those has a different answer, and none of them is visible from the client side.
mcpg inspector is how you look. One binary, three faces over the same
engine — a web UI, a terminal UI, and one-shot CLI verbs for scripts and CI.
It works against any MCP server, not just an mcpg gateway: point it at a
URL, a stdio: command line, or a recording.
Beta. The surface is complete and covered by end-to-end tests, but it is pre-1.0 and flags may still change. The full flag reference lives at
mcpg inspector.
The fastest path
If you are already running a gateway, add one flag:
mcpg --config server.yml --inspector
The gateway supervises an inspector alongside itself and prints a URL with a token. It comes up already connected to that gateway — no target to add, no credential to paste. The inspector dies with the gateway and never outlives it.
Standalone, against anything — --target is repeatable, so you can line
several servers up side by side:
# a server over HTTP
mcpg inspector serve --target http://127.0.0.1:8787/mcp
# a server you launch yourself, over stdio
mcpg inspector serve --target 'stdio:npx -y @modelcontextprotocol/server-everything'
Prefer a terminal — or working over SSH?
mcpg inspector tui --target http://127.0.0.1:8787/mcp
The TUI can also drive a running inspector rather than dialing its own targets, which is how you get a terminal onto a gateway-supervised session:
mcpg inspector tui --attach 'http://127.0.0.1:7846/?token=…'
The TUI covers the same surfaces as the web UI. tab moves between screens,
j/k selects, c connects, a edits arguments, enter runs whatever the
screen is about, and ? lists every key.
Installing it
mcpg-inspector is part of the CLI suite, so most people already have it —
install.sh fetches the whole suite by default:
curl -fsSL https://raw.githubusercontent.com/mcpg-dev/source-code/main/install.sh | sh
# or just this one binary
curl -fsSL https://raw.githubusercontent.com/mcpg-dev/source-code/main/install.sh \
| sh -s -- --bin mcpg-inspector
Through a package manager instead. The npm package is @mcpg-dev/mcpg and
carries every CLI in the suite as a bin; the PyPI distribution is
mcpg-cli:
npx -p @mcpg-dev/mcpg mcpg-inspector --help # npm
pip install mcpg-cli && mcpg-inspector --help # PyPI
brew tap mcpg-dev/mcpg https://github.com/mcpg-dev/source-code
brew install mcpg-inspector
Prebuilt binaries exist for x86_64 and aarch64 Linux (glibc and musl), Apple Silicon, and x86_64 Windows, plus an x86_64 Windows .zip.
See Install MCPG for the other paths.
Four questions it answers
"My tool isn't there."
List what the server actually advertises, rather than what you believe it advertises:
mcpg inspector list http://127.0.0.1:8787/mcp tools --json | jq '.tools[].name'
If the tool is genuinely missing and the server is an mcpg gateway, the next question is whether the thing behind it came up:
mcpg inspector gateway http://127.0.0.1:8787/mcp
That reads the gateway's own runtime snapshot — readiness, and which plugins
loaded in what state. A binding can resolve perfectly in config and still
serve nothing because the plugin behind it started degraded; over MCP all
you see is a missing tool. In the web UI it is the third diagnose tab; in
the TUI, g on the diagnose screen. All three lead with what is wrong — a
gateway running twelve healthy plugins lists none of them.
An empty tool list with no error usually means something else: you are anonymous, and the trust floor is hiding everything. That is working as intended — see Authorization.
"The server said no."
mcpg inspector auth https://gw.example/mcp
The auth lab makes a deliberately credential-free request and reports what
came back: the status, the WWW-Authenticate challenge, and the OAuth
discovery it can reach from there. It needs no connected session, because
the case you care about is the one where connecting failed.
To actually get a token, mcpg inspector login https://gw.example/mcp runs
the full OAuth flow — PKCE, dynamic client registration if the server offers
it — and hands the session back to the inspector.
"Is my server actually conformant?"
mcpg inspector check http://127.0.0.1:8787/mcp
The portable checks assert transport rules a normal client call papers over, so they build their own requests. Checks that do not apply to the negotiated revision are skipped, not failed.
Two more probes, both scriptable:
# how long does one tool take? min / p50 / p90 / p99, sequential
mcpg inspector bench http://127.0.0.1:8787/mcp dev.mock.echo -n 50
# what does it do with input its own schema forbids?
mcpg inspector fuzz http://127.0.0.1:8787/mcp
fuzz derives its cases from each tool's inputSchema — a missing required
property, the wrong type, an oversized string — and flags anything that
accepts what the schema forbids or refuses what it allows. It only calls
tools that declare readOnlyHint: true; everything else is skipped by name,
because these are real calls and the tool that forgot to annotate itself is
often the one that moves something.
"What did the wire actually say?"
Every face has a wire view showing raw JSON-RPC frames in both directions, including the malformed ones a typed client would drop. That is usually where a "mysterious" failure stops being mysterious.
# dump frames to stderr while running any verb
mcpg inspector call http://127.0.0.1:8787/mcp dev.mock.echo --args '{"text":"hi"}' --wire
Both protocol revisions
The inspector speaks 2025-11-25 and 2026-07-28 because it uses the gateway's own wire types and MCP client — the same code, extracted into shared crates. The inspector and the gateway cannot disagree about a revision.
It probes and negotiates by default; pin one when you want to test a specific wire:
mcpg inspector list https://gw.example/mcp tools --protocol-version 2025-11-25
See Protocol versions for what differs.
Sharing a session
An exchange can be exported as a recording — a single file — and replayed later with the server gone:
# in the web UI: "export recording"; in the TUI: `w`, which writes
# mcpg-inspector-<target>-<timestamp>.jsonl into the working directory
mcpg inspector serve --target recording:./session.jsonl
# the one-shot verbs replay too
mcpg inspector list recording:./session.jsonl tools --json
A recording answers only what the original session actually asked. Replay a call the recording never saw and it says so by name rather than inventing a result — so list the surfaces you want before exporting, or the replay is thinner than you expect.
Credentials never reach the file: tokens and credential-shaped arguments are redacted at write time. This is how you attach a reproduction to a bug report without also attaching your gateway.
Scripting and CI
Every one-shot verb takes --json and prints its result document as the only
thing on stdout, so exit codes are a contract:
| Code | Meaning |
|---|---|
0 | ok |
1 | usage |
2 | connect / probe failed |
3 | auth required |
4 | unreachable |
5 | the operation failed, or the report found something |
That last one is what makes these useful as gates. diff exits 5 when a
capability snapshot drifts, fuzz when a server accepts what it said it
would not, gateway when a plugin is loaded but not active:
# fail a PR when the tool surface changes
mcpg inspector snapshot https://gw.example/mcp --json > baseline.json
mcpg inspector diff https://gw.example/mcp --against baseline.json --mode strict
MCP Apps
A tool that ships a ui:// app (SEP-1865) is rendered in the web UI inside a
sandboxed frame with no allow-same-origin, under a CSP built from the
axes the app itself declared over a default-src 'none' floor. Every call the
app asks the host to make is shown — including the ones the host refuses. See
MCP Apps.
What it does not keep
Nothing is persisted. Sessions and history live in memory for as long as the process does; a recording is a file you chose to write. The hosted instance runs the same way, which is what keeps it database-free.
Next steps
mcpg inspectorreference — every verb and flag.- Quickstart — boot a gateway to point it at.
- Authorization — why an anonymous caller sees an empty server.