Inspector
Inspectorbeta

Reach a protected server

beta
v0.1.0-beta.2

Find out why a server refused you, walk the OAuth discovery chain including the step that failed, get a token with dynamic registration and PKCE, or present an AAuth agent identity.

A refusal is not one problem. "No OAuth here" and "it advertises OAuth but its authorization server could not be read" look identical from a client, and have completely different fixes. The auth lab exists to tell them apart.

What came back, and why

bash
mcpg inspector auth https://gw.example/mcp

auth sends one deliberately credential-free request and reports:

  • the status and the WWW-Authenticate challenge;
  • every step of the RFC 9728 → RFC 8414 discovery walk, including the one that failed;
  • a one-line verdict naming the next action.

A half-walked chain reads as a half-walked chain. That is the whole point — it needs no connected session, because the case you care about is the one where connecting failed.

It also reports AAuth posture, which lives in a separate channel: AAuth-Requirement, Signature-Error, and the target's /.well-known/aauth-resource.json.

In the web UI this is the first diagnose tab; in the TUI, the diagnose screen.

Getting a token

Once auth has found an authorization server, login walks the rest:

bash
mcpg inspector login https://gw.example/mcp

It registers a client dynamically (RFC 7591 — which is how MCP clients work, since you cannot pre-register everywhere), opens a browser for an authorization-code grant with PKCE, catches the redirect on loopback, and prints the access token on stdout. Pass it straight back:

bash
TOKEN="$(mcpg inspector login https://gw.example/mcp)"
mcpg inspector list https://gw.example/mcp tools --bearer "$TOKEN"

Useful flags:

FlagWhat it does
--client-idUse a client you registered yourself instead of registering one
--scopeOverride what to ask for; the default is whatever the challenge named
--no-browserPrint the URL instead of opening one — for SSH sessions

The token is audience-bound to this server via RFC 8707 resource indicators, so it is not replayable at another resource that trusts the same authorization server.

AAuth: an agent identity

AAuth gives an agent a portable cryptographic identity — aauth:local@domain bound to an Ed25519 key — and signs every request with it, so a captured credential is useless without the key. mcpg verifies it through the dev.mcpg.identity.aauth plugin; the inspector can present it.

There is no registration step. Trust is domain control plus a published key, so getting an identity means generating one and serving two static documents:

bash
mcpg inspector aauth-keygen \
  --agent aauth:inspector@yourdomain.example \
  --publish ./site

That writes ./site/.well-known/aauth-agent.json and ./site/.well-known/jwks.json, and prints the private seed. Serve the two documents under https://yourdomain.example, then sign with:

bash
mcpg inspector list https://gw.example/mcp tools \
  --aauth-key "$MCPG_INSPECTOR_AAUTH_KEY" \
  --aauth-agent aauth:inspector@yourdomain.example \
  --aauth-issuer https://yourdomain.example

--aauth-key reads MCPG_INSPECTOR_AAUTH_KEY, so the seed need not appear in a process listing. If you already have an agent token from an agent provider, pass it with --aauth-token and the token's own sub names the agent.

The inspector implements the identity-based access mode — the agent token is the credential — which is the mode mcpg verifies. The modes that require a person server and a human approval are reported by auth but not driven.

Two details that decide whether it works

  • Content-Digest is signed by default. Every MCP call is POST /mcp, so without it the signature would say nothing about which call was made.
  • EdDSA vs Ed25519. The JOSE alg is the fully-specified Ed25519. The polymorphic EdDSA is forbidden by the draft and refused by mcpg, so there is no switch for it. Do not confuse it with the RFC 9421 alg inside Signature-Input, a different registry spelled lowercase ed25519 — this is the most common interop failure in AAuth.

Keeping credentials off the command line

A command line is readable by every process on the box. Where a credential is involved, the inspector takes it from the environment instead:

  • MCPG_INSPECTOR_AAUTH_KEY for the AAuth seed;
  • MCPG_INSPECTOR_TOKEN when attaching a TUI to a running inspector;
  • the gateway's own token when it supervises a sidecar, which is why --inspector needs nothing pasted.

Next steps