Skip to main content

doorman

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.

Metadata

Release files for doorman-mcp 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for doorman-mcp 0.1.1
File Size Uploaded Provenance Actions
doorman_mcp-0.1.1.tar.gz 109.9 kB Without provenance Details for doorman_mcp-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for doorman-mcp 0.1.1
File Interpreter ABI Platform Actions
doorman_mcp-0.1.1-py3-none-any.whl Python 3 none any Details for doorman_mcp-0.1.1-py3-none-any.whl

Total release size: 115.2 kB

Release files / doorman_mcp-0.1.1.tar.gz

Download URL doorman_mcp-0.1.1.tar.gz
Size 109.9 kB
Tags Source
SHA-256 checksum
How to use checksums
252b0c1c252fa60a6f5736147736fbcc83d421f85d2555e17a79bd39e129c03f
BLAKE2b-256 checksum
How to use checksums
1807363b3ad4bba5c049e263d2ff1ec7cbfcf9a110558150490b538de426147e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / doorman_mcp-0.1.1-py3-none-any.whl

Download URL doorman_mcp-0.1.1-py3-none-any.whl
Size 5.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a51c634ad3b8b0988c9b0946f5c5439b55c39126ea0e211363343ea1c220e533
BLAKE2b-256 checksum
How to use checksums
dbe2628bb2fab2672d8150034cabb633e5a780419cea24ee619f2a3215ffef08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for doorman-mcp 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page