Doorman
FreeNot checkedOne-line OAuth for self-hosted MCP servers. Fail-closed by default.
About
One-line OAuth for self-hosted MCP servers. Fail-closed by default.
README
One-line OAuth for self-hosted MCP servers.
53% of self-hosted API services ship with static API keys. Only 8.5% implement proper OAuth. For MCP servers exposed to AI agents and human clients alike, that gap is not a configuration choice: it is a vulnerability. Doorman closes it in one line.
Before / After
Before: 28 lines of boilerplate every time
import os
from fastmcp import FastMCP
from fastmcp.server.auth.providers.github import GitHubProvider
mcp = FastMCP("My Server")
# Manually validate every required credential
client_id = os.environ.get("GITHUB_CLIENT_ID")
if not client_id:
raise ValueError("GITHUB_CLIENT_ID is required")
client_secret = os.environ.get("GITHUB_CLIENT_SECRET")
if not client_secret:
raise ValueError("GITHUB_CLIENT_SECRET is required")
jwt_secret = os.environ.get("DOORMAN_JWT_SECRET")
if not jwt_secret:
raise ValueError("DOORMAN_JWT_SECRET is required")
mcp.auth = GitHubProvider(
client_id=client_id,
client_secret=client_secret,
base_url=os.environ.get("DOORMAN_BASE_URL", "http://127.0.0.1:8000"),
required_scopes=["read:user", "user:email"],
allowed_client_redirect_uris=["http://localhost:*", "http://127.0.0.1:*"],
jwt_signing_key=jwt_secret,
require_authorization_consent=False,
)
After: one line
import doorman
doorman.protect(mcp, github=True)
Quickstart
1. Install
pip install doorman-mcp
2. Set environment variables
Generate a strong JWT secret:
python -c "import secrets; print(secrets.token_urlsafe(48))"
Then export all required variables for your shell:
macOS / Linux (bash/zsh):
export GITHUB_CLIENT_ID=your_client_id
export GITHUB_CLIENT_SECRET=your_client_secret
export DOORMAN_JWT_SECRET=paste_the_generated_secret_here
export DOORMAN_BASE_URL=http://127.0.0.1:8000
Windows (PowerShell):
$env:GITHUB_CLIENT_ID = "your_client_id"
$env:GITHUB_CLIENT_SECRET = "your_client_secret"
$env:DOORMAN_JWT_SECRET = "paste_the_generated_secret_here"
$env:DOORMAN_BASE_URL = "http://127.0.0.1:8000"
Variables set this way last only for the current terminal session. For real deployments use a secrets manager or a gitignored .env file; never commit credentials.
3. Create a GitHub OAuth App
In GitHub → Settings → Developer settings → OAuth Apps → New OAuth App:
- Homepage URL:
http://127.0.0.1:8000 - Authorization callback URL:
http://127.0.0.1:8000/auth/callback
4. Wire doorman into your server
from fastmcp import FastMCP
import doorman
mcp = FastMCP("My Server")
doorman.protect(mcp, github=True)
@mcp.tool()
def hello() -> str:
return "authenticated!"
mcp.run()
5. Run and connect
python my_server.py
Any MCP client that supports OAuth 2.0 can now connect. The client is redirected to GitHub, authenticates, and receives a short-lived JWT: no static keys, no copy-paste credentials.
Fail-closed by design
Doorman's contract: if auth cannot be configured, the server refuses to start.
- Missing
GITHUB_CLIENT_ID?ValueError; the server does not start. - Missing
DOORMAN_JWT_SECRET?ValueError; the server does not start. - No provider specified at all?
ValueError; the server does not start.
There is exactly one escape hatch:
doorman.protect(mcp, allow_unauthenticated=True)
This emits a loud UserWarning and bypasses all auth. It is intended for local development only and must be opted into by name; you cannot accidentally end up in an unprotected state.
Built on FastMCP
Doorman is a thin configuration layer on top of FastMCP's first-class OAuth primitives. It does not replace or wrap FastMCP; it reads your environment, validates credentials, and calls GitHubProvider with safe defaults. All MCP protocol handling, session management, and transport concerns remain in FastMCP.
License
MIT: see LICENSE.
Installing Doorman
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/manshahH/doorman-mcpFAQ
Is Doorman MCP free?
Yes, Doorman MCP is free — one-click install via Unyly at no cost.
Does Doorman need an API key?
No, Doorman runs without API keys or environment variables.
Is Doorman hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Doorman in Claude Desktop, Claude Code or Cursor?
Open Doorman on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Doorman with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
