Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Auth Server

БесплатноНе проверен

A proof-of-concept MCP server implementing OAuth 2.1 authorization with CIMD client registration and PKCE, demonstrating protected resource access and step-up a

GitHubEmbed

Описание

A proof-of-concept MCP server implementing OAuth 2.1 authorization with CIMD client registration and PKCE, demonstrating protected resource access and step-up authentication.

README

A local, runnable proof of concept of the MCP Authorization spec (2025-11-25).

It demonstrates, end to end:

  • an MCP server acting as a proper OAuth 2.1 resource server — publishes RFC 9728 Protected Resource Metadata, validates audience-bound access tokens, and enforces scope on a protected tool;
  • a one-command MCP client that discovers the authorization server, registers via Client ID Metadata Documents (CIMD), runs the full OAuth 2.1 + PKCE handshake (including a step-up re-authorization), and calls the protected tool;
  • a minimal custom OAuth 2.1 authorization server behind the MCP server.

Why a custom authorization server?

CIMD is draft-ietf-oauth-client-id-metadata-document-00. No off-the-shelf OSS or SaaS authorization server supports it yet, so using one would still require writing a CIMD shim. A small custom AS gives full, correct CIMD support and lets the whole thing run locally as a single command.

Quick start

uv venv && uv pip install -e ".[dev]"   # one-time setup
./scripts/run.sh                          # or: uv run python -m mcp_auth.demo

run.sh starts the authorization server and the resource server, then runs the client, which prints a step-by-step trace of the handshake and the protected tool's result, e.g.:

[1] Discovery
  401 challenge -> resource_metadata=...
  PRM: resource=http://localhost:8001/mcp as=['http://localhost:9000/'] scopes=['mcp:connect']
  AS metadata discovered at http://localhost:9000/.well-known/oauth-authorization-server
[2] Authorization (CIMD + PKCE) for base scope
[3] Call unprotected tool 'whoami'
[4] Call protected tool 'get_weather' (expect insufficient scope)
[5] Step-up re-authorization for the extra scope
[6] Retry 'get_weather' with stepped-up token
=== Success: full CIMD + OAuth 2.1 + step-up flow completed ===

Architecture

src/mcp_auth/
  config.py              shared ports, URLs, scopes, token TTL
  keys.py                authorization-server RSA signing key + JWKS export
  auth_server/           custom OAuth 2.1 authorization server (Starlette)
    app.py               AS metadata, /authorize, /token, /jwks
    cimd.py              fetch + validate Client ID Metadata Documents
    store.py             single-use authorization-code store
    tokens.py            RS256 JWT minting (aud=resource) + PKCE S256 verify
  resource_server/       FastMCP server as an OAuth 2.1 resource server
    server.py            FastMCP app + whoami + protected get_weather tool
    verifier.py          JWT verifier: signature, issuer, expiry, audience
  client/                one-command CIMD-driven MCP client
    metadata.py          the client's CIMD document + a server that hosts it
    flow.py              401 -> PRM -> AS discovery -> PKCE authorize -> token
    run.py               full journey incl. step-up
  demo.py                orchestrator (single command)

Default ports: authorization server :9000, resource server :8001, client CIMD host :3000. The canonical resource URI (the token audience) is http://localhost:8001/mcp.

How the flow maps to the spec

Spec requirement Where
RFC 9728 Protected Resource Metadata FastMCP, auto-served at /.well-known/oauth-protected-resource/mcp
401 + WWW-Authenticate with resource_metadata FastMCP RequireAuthMiddleware
RFC 8414 AS metadata incl. code_challenge_methods_supported, client_id_metadata_document_supported auth_server/app.py
CIMD: fetch client doc, validate client_id == URL, validate redirect_uri auth_server/cimd.py
Authorization code + PKCE S256 auth_server/app.py, client/flow.py
RFC 8707 resource parameter in auth + token requests client/flow.py
Audience-bound tokens; resource server validates aud auth_server/tokens.py, resource_server/verifier.py
Scope enforcement + insufficient_scope + step-up resource_server/server.py, client/run.py

Tests

uv run pytest

Covers AS/PRM metadata shape, CIMD validation (mismatched client_id, unlisted redirect URI, missing fields, SSRF host), PKCE and token claims, audience/expiry rejection in the verifier, and a full single-command end-to-end run.

Deliberate deviations from the spec (because this is a local PoC)

These are the conscious trade-offs that let the PoC run fully locally with one command. Each would be tightened for a real deployment:

  • HTTP on localhost instead of HTTPS. The spec mandates HTTPS for AS endpoints and the CIMD client_id URL; localhost redirect URIs are already spec-permitted. The MCP SDK's AnyHttpUrl accepts http, so no patching is needed.
  • Headless auto-approved consent. The AS authenticates a fixed demo subject and issues a code without a browser prompt, so the client reads the redirect directly (no callback listener). A real AS would authenticate the user and show a consent screen.
  • In-memory, process-local state (signing key, authorization codes). No persistence, no refresh-token rotation.
  • SSRF guard is a localhost allowlist for CIMD fetches, sufficient for local use; a real AS needs a stricter trust policy per the CIMD draft's security considerations.

Out of scope

  • infra/terraform/ (anticipated by .gitignore) — a local PoC needs no cloud infra.
  • Multi-user login UI, Dynamic Client Registration (CIMD is used instead), persistent storage.

from github.com/dawa/mcp_auth_server

Установить Auth Server в Claude Desktop, Claude Code, Cursor

Рекомендуется · одна команда, все IDE
unyly install mcp-auth-server

Ставит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.

Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh

Или настроить вручную

Выполни в терминале:

claude mcp add mcp-auth-server -- uvx --from git+https://github.com/dawa/mcp_auth_server mcp-auth-server

FAQ

Auth Server MCP бесплатный?

Да, Auth Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Auth Server?

Нет, Auth Server работает без API-ключей и переменных окружения.

Auth Server — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Auth Server в Claude Desktop, Claude Code или Cursor?

Открой Auth Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Auth Server with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development