Skip to content

docs(mcp_zero_trust): add MCP zero trust auth guide#23918

Merged
ishaan-jaff merged 2 commits intomainfrom
docs/mcp-zero-trust
Mar 18, 2026
Merged

docs(mcp_zero_trust): add MCP zero trust auth guide#23918
ishaan-jaff merged 2 commits intomainfrom
docs/mcp-zero-trust

Conversation

@ishaan-jaff
Copy link
Copy Markdown
Contributor

Relevant issues

Companion docs for #23897 (MCPJWTSigner guardrail).

Pre-Submission checklist

  • Doc-only change — no code modified
  • Hero image included

Type

  • Bug fix
  • New feature
  • Documentation / non-code change

Changes

Adds docs/my-website/docs/mcp_zero_trust.md — use-case-driven guide for the MCPJWTSigner guardrail:

  • Basic setup (sign every tool call with zero client-side changes)
  • Thread IdP identity into MCP JWTs (access_token_discovery_uri, end_user_claim_sources)
  • Block callers missing required attributes (required_claims, optional_claims)
  • Add custom metadata to every JWT (add_claims, set_claims, remove_claims)
  • AWS Bedrock AgentCore Gateway two-token model (channel_token_audience, channel_token_ttl)
  • Control which scopes go into the JWT (allowed_scopes)
  • Debug JWT rejections (debug_headers)
  • JWT claims reference table + limitations section

Adds hero image (docs/my-website/img/mcp_zero_trust_gateway.png).

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Mar 18, 2026 0:37am

Request Review

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq bot commented Mar 18, 2026

Merging this PR will not alter performance

✅ 16 untouched benchmarks


Comparing docs/mcp-zero-trust (a7e261c) with main (ac0de1d)

Open in CodSpeed

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 18, 2026

Greptile Summary

This PR adds a new documentation page (docs/my-website/docs/mcp_zero_trust.md) and hero image for the MCPJWTSigner guardrail, providing a comprehensive use-case-driven guide for zero-trust MCP authentication via RS256 JWTs.

The guide covers the full feature surface — basic setup, IdP identity threading, required/optional claim enforcement, custom claim injection, AWS Bedrock AgentCore Gateway's two-token model, scope control, and debug tooling. The structure is clean and the examples are practical.

Issues found:

  • Unused imports: Tabs and TabItem are imported at lines 1–2 but never used in the document. These should be removed.
  • Debug header missing aud: The x-litellm-mcp-debug example header does not include aud, yet the accompanying verification guidance explicitly tells users to check aud. This creates a gap — users cannot diagnose audience mismatches via debug_headers.
  • Scope inconsistency: The "least-privilege" default scope table lists mcp:tools/call as part of the "List tools" scope, which contradicts the least-privilege framing and may reflect a documentation error.

Confidence Score: 4/5

  • Safe to merge — documentation-only change with minor accuracy issues that should be addressed.
  • No code is modified; risk is limited to documentation accuracy. The unused imports and the aud/scope inconsistencies are low-severity but could mislead operators during debugging.
  • docs/my-website/docs/mcp_zero_trust.md — verify debug header format and default scope list against the implementation in feat(guardrails): MCPJWTSigner - built-in guardrail for zero trust MCP auth #23897.

Important Files Changed

Filename Overview
docs/my-website/docs/mcp_zero_trust.md New use-case-driven guide for MCPJWTSigner; contains unused Tabs/TabItem imports, a debug-header example missing the aud claim despite telling users to check it, and a potentially misleading "least-privilege" scope list that grants mcp:tools/call on list-tools operations.
docs/my-website/static/img/mcp_zero_trust_gateway.png Hero image for the new MCP zero trust guide; binary asset, no issues.

Sequence Diagram

sequenceDiagram
    participant Client
    participant LiteLLM as LiteLLM Proxy
    participant IdP as Corporate IdP
    participant MCPServer as MCP Server

    Client->>LiteLLM: Tool call request + Bearer token (IdP or API key)
    LiteLLM->>IdP: Validate incoming token (JWKS / introspection)
    IdP-->>LiteLLM: Token claims (sub, email, groups, ...)
    Note over LiteLLM: MCPJWTSigner guardrail<br/>1. Check required_claims<br/>2. Build outbound JWT<br/>   (add/set/remove claims)<br/>3. Sign RS256 JWT
    LiteLLM->>MCPServer: Tool call + Authorization: Bearer <signed-JWT>
    MCPServer->>LiteLLM: GET /.well-known/jwks.json
    LiteLLM-->>MCPServer: JWKS (RSA public key)
    MCPServer-->>MCPServer: Verify JWT signature, iss, aud, exp
    MCPServer-->>LiteLLM: Tool result
    LiteLLM-->>Client: Response
Loading

Last reviewed commit: "fix(docs): move hero..."

@@ -0,0 +1,294 @@
import Tabs from '@theme/Tabs';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 New doc missing from sidebar navigation

mcp_zero_trust is not listed in docs/my-website/sidebars.js. Without this entry the page is only reachable via direct URL; it won't appear in the /mcp category alongside the other MCP guides.

Add it to the sidebar in sidebars.js:

{
  type: "category",
  label: "/mcp - Model Context Protocol",
  items: [
    "mcp",
    "mcp_usage",
    "mcp_openapi",
    "mcp_oauth",
    "mcp_aws_sigv4",
+   "mcp_zero_trust",
    "mcp_public_internet",
    "mcp_semantic_filter",
    "mcp_control",
    "mcp_cost",
    "mcp_guardrail",
    "mcp_troubleshoot",
  ]
},

Comment on lines +238 to +239
- "mcp:tools/list"
- "mcp:admin"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 debug_headers warning should be more prominent

The note about disabling debug_headers in production is easy to miss at the end of a paragraph. Because this header leaks signed claim metadata (including sub, iss, email, etc.) to any observer of the HTTP response, it deserves a dedicated admonition block, e.g.:

:::danger Production risk
`debug_headers: true` adds `x-litellm-mcp-debug` to every response. This header exposes JWT claim metadata (including `sub`, `email`, `iss`) to any party that can read HTTP responses. **Always disable this in production.**
:::

Comment on lines +1 to +2
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unused imports — Tabs and TabItem never referenced

Tabs and TabItem are imported at the top of the file, but neither component appears anywhere in the document. These are dead imports that can cause ESLint/MDX lint warnings and should be removed.

Suggested change
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

(Remove both import lines entirely — the page uses no tab components.)

Comment on lines +262 to +265
x-litellm-mcp-debug: v=1; kid=a3f1b2c4d5e6f708; [email protected]; iss=https://my-litellm.example.com; exp=1712345678; scope=mcp:tools/call mcp:tools/get_weather:call
```

Check that `kid` matches what the MCP server fetched from JWKS, `iss`/`aud` match your server's expected values, and `exp` hasn't passed. Disable in production — the header leaks claim metadata.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 aud absent from debug header example but referenced in verification guidance

Line 265 tells users to "Check that iss/aud match your server's expected values," yet the example x-litellm-mcp-debug header on line 262 does not include aud:

x-litellm-mcp-debug: v=1; kid=a3f1b2c4d5e6f708; [email protected]; iss=https://my-litellm.example.com; exp=1712345678; scope=mcp:tools/call mcp:tools/get_weather:call

If the implementation genuinely omits aud from the debug header, users won't be able to use debug_headers to diagnose audience mismatches — which is one of the most common JWT rejection causes. Either:

  • Update the example to include aud, e.g. aud=mcp-resource, or
  • Remove the reference to checking aud from the verification guidance on line 265, since the debug header won't expose it.

Comment on lines +222 to +224
By default LiteLLM generates least-privilege scopes per request:
- Tool call → `mcp:tools/call mcp:tools/{name}:call`
- List tools → `mcp:tools/call mcp:tools/list`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 "List tools" default scope includes mcp:tools/call — likely a copy-paste error

The default scope table shows:

- Tool call → `mcp:tools/call mcp:tools/{name}:call`
- List tools → `mcp:tools/call mcp:tools/list`

The "list tools" scope includes mcp:tools/call, which is semantically meant for calling tools, not listing them. A least-privilege scope for listing would be only mcp:tools/list. Including the call scope on a list operation grants broader permissions than needed and contradicts the "least-privilege" claim made in the opening sentence of this section.

If the implementation genuinely issues mcp:tools/call for list operations, this warrants a clarifying note; otherwise it looks like a documentation error.

@ishaan-jaff ishaan-jaff merged commit fc315ab into main Mar 18, 2026
38 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant