---
title: "Accept only tokens issued for your MCP · Agent Wranglers"
url: https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/mcp-token-audience-no-passthrough
id: AGT-38
level: Required
risk: takeover
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1282
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Accept only tokens issued for your MCP server and never pass them on

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Delegated access and consent](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: AGT-38
- Level: Required
- Chapter: [Delegated access and consent](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent.md)
- Rule: Check every access token's signature, issuer, expiry and audience before an MCP request runs. Refuse a token whose `aud` does not name this server with 401. Never forward the client's token to another API.
- Check: Send a valid token from your own authorization server issued for `https://other.example.com`. The server answers 401 and runs no tool. A traced test tool that calls an upstream API sends it a different token from the one the client sent.
- Risk: An account or system taken over
- Spec version: MCP 2026-07-28
- Review by: 2027-04-30
- How: A token issued for another service, even by your own authorization server, must not open yours. Otherwise any service that sees your users' tokens can replay them at you. When a tool calls an upstream API, use a separate token for that API, from the person's own grant with it or from token exchange. A passed-on token makes the upstream API trust a token it never meant to accept, and hides who acted from its logs. Answer an invalid or expired token with 401 and a missing scope with 403. Exchanged tokens never widen rights, as [Never widen an agent's rights when you exchange its token](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/no-permission-amplification.md) says. The attack procedure is in [Run the AI feature checks](https://agentwranglers.se/playbook/adversarial-testing/ai-agents-and-models/ai-checks.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import { createRemoteJWKSet, jwtVerify } from 'jose';
const ISSUER = 'https://auth.example.com';
const RESOURCE = 'https://mcp.example.com/mcp';
const keys = createRemoteJWKSet(new URL(`${ISSUER}/jwks.json`));

export async function verifiedClaims(bearer) {
  try {
    const { payload } = await jwtVerify(bearer, keys, { issuer: ISSUER, audience: RESOURCE });
    return payload;
  } catch {
    return null;
  }
}
```

### Python example

```python
import jwt

ISSUER = "https://auth.example.com"
RESOURCE = "https://mcp.example.com/mcp"
keys = jwt.PyJWKClient(f"{ISSUER}/jwks.json")

def verified_claims(bearer: str) -> dict | None:
    try:
        key = keys.get_signing_key_from_jwt(bearer).key
        return jwt.decode(bearer, key, algorithms=["RS256", "ES256"], issuer=ISSUER, audience=RESOURCE)
    except jwt.PyJWTError:
        return None
```

## Sources

- [MCP authorization security considerations (audience and passthrough)](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/security-considerations)
- [RFC 8707 (Resource Indicators for OAuth 2.0)](https://www.rfc-editor.org/rfc/rfc8707)
- [RFC 9068 (JWT Profile for OAuth 2.0 Access Tokens)](https://www.rfc-editor.org/rfc/rfc9068)

## Related rules

- AGT-7 [Never widen an agent's rights when you exchange its token](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/no-permission-amplification.md) in Agents as users
- AGT-33 [Send the issuer with every authorization response](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/issuer-in-authorization-response.md) in Agents as users
- SEC-118 [Run the AI feature checks](https://agentwranglers.se/playbook/adversarial-testing/ai-agents-and-models/ai-checks.md) in Adversarial testing
- AGT-39 [Bind every token to one MCP server with resource indicators](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/resource-indicators.md) in Agents as users

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/mcp-token-audience-no-passthrough">Agent Wranglers agents as users playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Publish protected resource metadata for every MCP server that needs sign-in](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/mcp-protected-resource-metadata.md)
- Next: [Bind every token to one MCP server with resource indicators](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent/resource-indicators.md)
- [Delegated access and consent](https://agentwranglers.se/playbook/agents-as-users/delegated-access-and-consent.md)
