No bearer tokens to steal
Access tokens are bound to a P-256 key generated for each login (DPoP). A leaked token is useless without the key.
mcp-airlock is a local stdio bridge to remote, OAuth-protected Model Context Protocol servers. It discovers the authorization server, logs you in through your browser, binds every token to a key that never leaves your machine, and keeps you logged in, all invisible to your AI client.
Remote MCP servers protect their tools with OAuth, but many clients only speak stdio, and few OAuth clients use sender-constrained tokens. mcp-airlock closes that gap.
Access tokens are bound to a P-256 key generated for each login (DPoP). A leaked token is useless without the key.
The authorization server is discovered from the MCP server's protected resource metadata, as the MCP specification describes.
Tokens are refreshed silently, even before they expire. When a login is needed, requests wait and then resume.
Built against the specifications, and tested against a strict MCP 2026-07-28 server and a real Keycloak.
Forwards MCP 2026-07-28 clients (per-request _meta) and legacy initialize clients, each with the HTTP rules of its revision.
JSON and SSE responses, Mcp-Method / Mcp-Name headers, x-mcp-header mirroring, subscriptions/listen and cancellation by closing the stream.
Pushed Authorization Requests, PKCE S256, resource indicators, dpop_jkt, and RFC 9207 iss checks on the callback.
Silent and proactive refresh with DPoP-bound refresh tokens. A 403 insufficient_scope triggers a step-up login that keeps earlier scopes.
macOS Keychain, Windows Credential Manager, or the Linux Secret Service. Credentials are scoped per MCP server and bound to their issuer.
Network errors, HTTP errors and failed logins come back as JSON-RPC errors for the request. Authentication loops are detected, not repeated.
Your AI client starts mcp-airlock like any local MCP server. Everything else happens behind the stdio pipe.
Scroll the diagram sideways to see all of it.
401: requests pause in the airlock while mcp-airlock finds the authorization server through RFC 9728 and RFC 8414 metadata.state, iss).Three steps, assuming an MCP server protected by an OAuth provider such as Keycloak.
Download a binary from the releases page, or build it with Rust 1.88+:
cargo install --git https://github.com/ffalcinelli/mcp-airlock
Create a public client (e.g. mcp-airlock) with PAR, PKCE S256 and DPoP, and the redirect URI http://127.0.0.1:8082/callback. Client ID Metadata Documents work too.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"my-secure-server": {
"command": "/path/to/mcp-airlock",
"args": ["--remote-mcp-url", "https://mcp.example.com/mcp",
"--oidc-client-id", "mcp-airlock"]
}
}
}
Claude Code:
claude mcp add my-secure-server -- /path/to/mcp-airlock \
--remote-mcp-url https://mcp.example.com/mcp --oidc-client-id mcp-airlock
On the first request your browser opens the provider's login page. More clients, every option, and provider setup: setup guide.
_meta)initialize sessions)iss)mcp-airlock protects your credentials in transit and at rest, and only sends them where they belong.
state and iss.The local machine is trusted. Read the threat model, and report vulnerabilities privately.