Skip to content

mcp-svid-auth

Proof of concept. An AI agent authenticates to MCP servers with its SPIFFE workload identity instead of a static API key.

Proof of concept

Not production software. Do not deploy it to protect real data. See Security model.

Problem

MCP client configs often hold long-lived static keys:

{ "env": { "NOTES_API_KEY": "sk-live-..." } }
Issue with static keys Effect
Long-lived A leaked key works until someone rotates it by hand
Not bound to a workload Any process that reads the file can use it
Not bound to a server One key often opens several servers
No per-caller identity Audit logs cannot say which agent acted

What this POC proves

Claim Where
An agent gets a short-lived access token using only its JWT-SVID authz.py, draft-ietf-oauth-spiffe-client-auth
Tokens are bound to one MCP server via the RFC 8707 resource parameter authz.py, policy.py
A token issued for server A is rejected by server B mcp_server.py, test_token_for_a_is_rejected_by_b
Scopes are enforced per tool, with a 403 insufficient_scope challenge. Tools without a declared scope are denied. ToolScopeGuard, build_mcp
Every decision is written as one JSON audit line with the SPIFFE ID audit.py
The MCP server never forwards the incoming token mcp_server.py makes no outbound call with it
A stdio MCP server can start with a refreshed short-lived token instead of a static key stdio_wrapper.py

Standards targeted

Full list: References.

Where to go next

Page Content
Quickstart Install, offline checks, the SPIRE demo
Architecture Components and the token flow
Demo scenarios The four scenarios and their results
Security model Threat model, checks, non-goals, known gaps
stdio wrapper Short-lived tokens for local stdio MCP servers
Configuration CLI flags and the policy file

License

Apache-2.0. Copyright 2026 Tanya Babitskaya. See LICENSE and NOTICE.