Get started
Get startedbeta

Inspect an MCP server

beta

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:

bash
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:

bash
# 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?

bash
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:

bash
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:

bash
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:

bash
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:

bash
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:

bash
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."

bash
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?"

bash
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:

bash
# 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.

bash
# 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:

bash
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:

bash
# 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:

CodeMeaning
0ok
1usage
2connect / probe failed
3auth required
4unreachable
5the 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:

bash
# 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