Repository navigation
Releases: ffalcinelli/mcp-airlock
Releases · ffalcinelli/mcp-airlock
Release list
Release v0.0.1
First release. The project was developed as mcp-passport and renamed to mcp-airlock before release: the binary, library, MCP_AIRLOCK_* environment variables, default client ID, keychain entries and log directory all use the new name.
Added
- Transparent stdio ↔ HTTP proxy for MCP clients that cannot do OAuth themselves, with a dedicated stdout writer so concurrent responses never interleave.
- FAPI 2.0 authorization: PAR + PKCE S256 + DPoP, following the MCP 2026-07-28 authorization rules:
- authorization servers must advertise PKCE S256 (
code_challenge_methods_supported); - scope selection from the challenge or
scopes_supported, with scope union on step-up; - RFC 9207
issvalidation, and immediate failure onerror=responses; - Client ID Metadata Documents as client IDs;
dpop_jktin PAR requests, and DPoP nonces from both the authorization server and the MCP server;offline_accessonly with--oidc-offline-access.
- authorization servers must advertise PKCE S256 (
- Discovery: RFC 9728 protected resource metadata, then RFC 8414 / OIDC metadata, with
resourceand exactissuervalidation. A configured--oidc-discovery-urltakes precedence over the server'sresource_metadata. Servers that serve AS metadata as their resource metadata keep working, with a warning. - The airlock: a
401or403 insufficient_scopesuspends outgoing requests while re-authentication runs, then resumes them. It is driven by a credential generation: concurrent rejections share one login, a silent refresh is tried first, and a fresh token rejected right away is reported as a loop instead of opening another browser login. - Tokens: silent refresh with DPoP-bound refresh tokens, also proactively before expiry.
- Credential storage in the OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service with a kernel-keyring cache), scoped per MCP server and bound to the issuer that granted them.
- MCP 2026-07-28, dual-era:
- modern and legacy clients are both forwarded with the rules of their era;
- the
MCP-Protocol-Version(per message),Mcp-MethodandMcp-Nameheaders, with the base64 sentinel encoding;--mcp-protocol-versionis only a fallback; x-mcp-header→Mcp-Param-*mirroring, invalid-tool filtering and a HeaderMismatch retry;- stdio
notifications/cancelledcloses the request's response stream; subscriptions/listenpassthrough;- no GET stream or session ids for modern servers.
- Streamable HTTP:
Accept: application/json, text/event-stream;- SSE responses to POSTs,
202 Accepted, JSON-RPC error bodies of non-2xx replies; - for legacy servers: session expiry (404),
Last-Event-IDresumption, and a GET stream (--remote-sse-url, defaulting to--remote-mcp-url) that stops cleanly on 405.
- Failed requests get a JSON-RPC error instead of leaving the client waiting; invalid JSON gets a parse error.
- Flags:
--auth-timeout-secs,--allow-insecure-http,--oidc-issuer,--oidc-offline-access,--log-dir, and the existing OIDC/MCP settings, all also settable throughMCP_AIRLOCK_*environment variables. Proxy::call()andrun_with_vault()for library use.- Release binaries for Linux (x86_64, aarch64), macOS (x86_64, aarch64) and Windows (x86_64), with SHA-256 checksums.
- A landing page on GitHub Pages, next to the versioned API docs.
- Tests: a strict dual-era MCP 2026-07-28 test server and conformance suite, an end-to-end suite against Keycloak 26.8.0 with headless Chrome, and benchmarks of the request hot paths.
Security
- The MCP server, discovery URL and AS endpoints must use HTTPS except on loopback; plain HTTP elsewhere needs
--allow-insecure-http. - The
resource_metadataSSRF check compares full origins (scheme, host and port). - Refresh tokens are never sent to another authorization server.
- The login callback listens on loopback only (the redirect URL must be a loopback
httpURL with a port), and checksstateandiss. - A failed login never replaces the stored DPoP key.
- Logs go to a private (
0700) per-user directory that may not be a symlink or owned by another user. - TLS uses rustls with the operating system's trust store.