authenticated, and nothing about the secret itself.
Bearer tokens
--token is shorthand for --header 'Authorization: Bearer <token>'. When
the flag is absent, mcpscore reads MCPSCORE_TOKEN from the environment. That
is the form for CI and for any shell where history is a concern:
API keys and other headers
--header sends any header and repeats:
Authorization header wins over --token and MCPSCORE_TOKEN.
Only an Authorization credential sets authenticated: true in the report.
Other headers are sent but make no claim that the audit ran behind the gate.
Browser OAuth
--oauth runs the authorization code flow with PKCE, as the
MCP authorization spec
describes, and holds the token in memory only. It needs the authorization
server to support dynamic client registration (RFC 7591). When it doesn’t,
register an app once and pass its ID:
http://127.0.0.1:<port>/callback. RFC 8252 requires authorization servers to
accept any port on loopback, but if yours demands the exact registered URI,
pin the port you registered with --callback-port.
What a partial audit scores
Without a credential, an auth-gated server is still worth a look. The observable surface is real quality:- Auth posture: the 401 carries a proper
WWW-Authenticatechallenge, RFC 9728 protected-resource metadata is served, and the authorization servers it names are HTTPS-only with PKCE enforced. - TLS and transport behavior.
partial: true with a partial_reason, and the score line
says PARTIAL with the check count on purpose. 24/27 on its own pastes into
a chat as a near-perfect result. from 10 of 78 checks is what makes it
honest.
A partial score covers fewer checks than a full audit, so the two are not
comparable.
--fail-under always fails on a partial audit for that reason.
Pass a credential before gating CI on a threshold.In CI
Store the token as a secret and export it asMCPSCORE_TOKEN. Nothing else
changes. With the GitHub Action:
When it fails
PARTIAL score although you passed a header
- Cause: the header was not
Authorization, or the server rejected the credential and answered 401 anyway. - Fix: check the header name and that the token is current. Only an
Authorizationcredential is treated as authenticating.
Gate failed — --fail-under 80: this was a partial audit (exit 3)
- Cause: the audit ran without a credential, and a partial score cannot demonstrate a threshold.
- Fix: pass a credential, or drop
--fail-underfor that run.
--oauth stops with a registration error (exit 1)
- Cause: the authorization server does not offer dynamic client registration.
- Fix: register an OAuth app yourself and pass
--client-id.
- Cause: the authorization server insists on the exact registered URI, including the port.
- Fix: pin the port you registered with
--callback-port.
What’s next
GitHub Action
Gate pull requests on quality, gated servers included
Rules reference
The auth-posture rules, with their spec and RFC citations