mcp

MCP token audience and resource mismatch: why you 401 after login

If remote MCP Connect finishes the browser login and then every tool call still returns 401 (often invalid_token), the usual cause is the token itself: it was issued for a different audience or resource than the one your MCP server checks. MCP authorization guidance has clients name the target server with the OAuth resource parameter (RFC 8707), and servers must only accept tokens meant for them. If the strings don’t match exactly, login succeeds and every call fails. This page covers that post-login check — not discovery. Trailing slash, host form, and environment drift are enough to break an otherwise successful login.

Symptom card

  • Browser login completes and Connect reports success.
  • `tools/list` or the first tool call returns 401, sometimes with `WWW-Authenticate: Bearer error="invalid_token"`.
  • Reconnecting repeats the same loop.
  • Inspector shows a token was issued, so the authorization server (AS) isn't the problem. The server is rejecting a token that isn't addressed to it.

Discovery (how the client finds the resource identifier) lives in Protected Resource Metadata in plain English. This page stays on the post-login audience check.

How the resource gets bound to the token

  1. Your server's PRM advertises its resource identifier.
  2. The client sends that identifier as `resource` on the authorize and token requests.
  3. The AS issues a token bound to it, typically through the `aud` claim on a JWT or through introspection.
  4. Your server validates the audience against its own canonical identifier before it serves anything.

A mismatch at any of these steps causes the 401.

Canonical URL pitfalls

  • Trailing slash: `https://api.example.com/mcp` and `https://api.example.com/mcp/` are different strings.
  • Host form: apex vs `www`, mixed case, or an internal hostname behind a proxy.
  • Port and path: a `:443` written out explicitly, or `/mcp` vs `/v1/mcp`.
  • Environment drift: a staging resource in the AS config and a prod URL in PRM, or the other way round.
  • AS defaults: some authorization servers ignore `resource` unless it's enabled and fall back to a generic audience. Check your AS docs instead of assuming.

Pick one canonical identifier, publish it in PRM, configure the AS to accept it, and compare against that same string on the server.

Checking it without leaking anything

Run the flow in MCP Inspector. If the access token is a JWT, decode it locally and read `aud`. Otherwise use your AS's introspection endpoint. Compare the value with what your server expects. Never paste live tokens into chats, tickets, or AI assistants.

Where the kit fits

The MCP Starter Kit ($27) ships a remote MCP layout with challenge, PRM, and audience validation wired to a single canonical identifier, so Cursor and Claude Connect don't fall into this loop. Soft path: start at /free; Cheat Sheet for the skim checklist mindset; kit when you want the auth-ready layout.

Soft next step

Lock one canonical resource identifier, then compare `aud` against it with Inspector. Soft ladder: /free, then the MCP Starter Kit ($27). Related: OAuth pillar, auth checklist, PRM in plain English.

FAQ

Why does my MCP server 401 after OAuth login succeeds?+

Most often the token was minted for a different audience or resource than the one your server validates. Login worked; the server is rejecting a token that isn’t for it.

What is the `resource` parameter in MCP OAuth?+

It names the protected resource the client wants a token for, so the authorization server can bind the token to that resource. It should match the resource identifier your PRM publishes.

What should the token audience be for a remote MCP server?+

Your MCP server’s canonical resource identifier, the same string your PRM advertises and your server checks. Pick one canonical form and use it everywhere.

Does trailing slash or host case break audience matching?+

It can. Many validators compare strings exactly, so /mcp vs /mcp/ or a different host form can fail. Normalize to one canonical identifier.

How do I check the token audience with MCP Inspector?+

Complete the auth flow in Inspector, then decode the access token (if it’s a JWT) or check your AS introspection, and compare its audience to the resource your server expects.

Is audience validation required or optional?+

Treat it as required. Without it, your server could accept tokens minted for other services, which is exactly what MCP’s auth guidance warns against.

Get the free starter

Value first, then a kit when you are ready. No fake urgency. Start with Harness Desk Starter at /free.