Command Palette

Search for a command to run...

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

Oauth Starter

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

A minimal remote MCP server with OAuth 2.1 resource-server authorization, built against the 2026-07-28 spec revision. Tested.

GitHubEmbed

Описание

A minimal remote MCP server with OAuth 2.1 resource-server authorization, built against the 2026-07-28 spec revision. Tested.

README

A minimal remote MCP server that actually requires authorization — built against the 2026-07-28 spec revision, with OAuth 2.1 resource-server semantics wired up and tested.

tests python license

Most public MCP examples run unauthenticated on stdio, which is fine on your laptop and useless the moment the server is a URL someone else's Claude connects to. This is the other half: a server that answers 401 with a discovery pointer, validates the token it gets back, and refuses tokens that were minted for somebody else.


Why this exists

The MCP authorization profile moved on 2026-07-28 (previous revision: 2025-11-25), and most tutorials still describe the older world. Three changes matter if you are writing a connector now:

Change What it means for your server
Stateless core The initialize/initialized handshake and the Mcp-Session-Id header are gone. Each request carries its own protocol version and client identity in _meta. Your server scales behind a plain round-robin load balancer with no shared session store.
Dynamic Client Registration deprecated DCR (RFC 7591) is retained only for backwards compatibility. New work should assume Client ID Metadata Documents — the client's client_id is an HTTPS URL pointing at its own metadata. That is your authorization server's problem, not this server's, but it should steer which AS you pick.
Issuer validation (RFC 9207) Clients must validate the iss returned on the authorization response before redeeming the code. Your AS should emit iss and advertise authorization_response_iss_parameter_supported.

Verified against mcp 2.2.0, where mcp.types.LATEST_PROTOCOL_VERSION == "2026-07-28".

The one rule you cannot skip

MCP servers MUST validate that access tokens were issued specifically for them as the intended audience, according to RFC 8707 Section 2. — MCP 2026-07-28, Token Handling

A signed, unexpired, entirely legitimate token issued for another resource server must be rejected here. Accept it and your server becomes a replay target: anyone holding a token for any other service on the same authorization server can drive your tools. That is the confused-deputy problem, and it is one audience= argument away from being a real breach.

This repo enforces it twice — once in verifier.py via jwt.decode(..., audience=...), and again through validate_token_resource=True in the bearer middleware. There is a test for it: test_token_for_another_audience_is_rejected.

What the SDK leaves to you

mcp 2.2.0 publishes the RFC 9728 metadata document and emits a 401 with error, error_description and resource_metadata — but not the RFC 6750 scope parameter, which the spec says servers SHOULD send. Without it a client falls back to scopes_supported from the metadata document, costing an extra round trip on every cold start.

challenge.py is a small ASGI wrapper that appends it:

WWW-Authenticate: Bearer error="invalid_token", error_description="Authentication required",
                  resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource/mcp",
                  scope="notes:read notes:write"

The flow

sequenceDiagram
    participant C as MCP Client
    participant M as This server<br/>(resource server)
    participant A as Authorization Server

    C->>M: POST /mcp (no token)
    M-->>C: 401 + WWW-Authenticate:<br/>Bearer resource_metadata="...", scope="notes:read"
    C->>M: GET /.well-known/oauth-protected-resource/mcp
    M-->>C: { resource, authorization_servers, scopes_supported }
    C->>A: Discover metadata, then authorize (PKCE + resource=<canonical URI>)
    A-->>C: Access token, aud = this server
    C->>M: POST /mcp + Authorization: Bearer ...
    M->>M: Verify signature, iss, aud, exp
    M-->>C: Tool result

Quickstart

git clone https://github.com/specter-systems/mcp-oauth-starter
cd mcp-oauth-starter
pip install -e ".[dev]"

cp .env.example .env      # then edit it — see the table below
set -a && source .env && set +a
mcp-oauth-starter         # serves on http://127.0.0.1:8000/mcp

Confirm the discovery document and the challenge before you connect a client:

curl -s localhost:8000/.well-known/oauth-protected-resource/mcp | jq
curl -si -X POST localhost:8000/mcp \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | head -12

You should get a 401 whose WWW-Authenticate header names the metadata URL. If you get a 200, your server is unprotected — stop and fix that before deploying anything.

Configuration

Variable Required Notes
MCP_RESOURCE_URL yes The canonical URI of this server (RFC 8707 §2), exactly as clients send it in resource. https, no fragment, no trailing slash. A mismatch here is the single most common cause of "my token keeps getting rejected".
MCP_AUTH_ISSUER yes Issuer identifier of your authorization server. Must equal the iss claim byte-for-byte.
MCP_JWKS_URL yes Usually jwks_uri from {issuer}/.well-known/oauth-authorization-server. Keys are cached and refetched on an unknown kid, so rotation needs no redeploy.
MCP_REQUIRED_SCOPES no Space-separated. Advertised as scopes_supported and in the challenge. Keep it to the minimum for basic functionality and ask for more per tool.
MCP_ALGORITHMS no Defaults to RS256. none is refused at construction.
HOST / PORT no Defaults to 127.0.0.1:8000.

Scopes

MCP_REQUIRED_SCOPES gates the whole server. Individual tools can ask for more — write_note calls require_scope("notes:write") — which is what you want when one connector exposes both reads and writes and you would rather not hand every caller write access.

Per the spec, return all scopes needed for an operation in a single 403 challenge. Challenging for one missing scope at a time forces repeated authorization round-trips and makes the connector feel broken.

Tests

pytest -q

Covers audience rejection, issuer rejection, expiry, missing aud, malformed tokens, the scope / scp claim shapes that Okta and Entra disagree about, the RFC 9728 discovery document, the shape of the 401 challenge, and the scope parameter added on top of it.

What this is not

  • Not an authorization server. It does not issue tokens. Point it at one you run or buy.
  • Not a production connector. It is the auth scaffolding with three illustrative tools; the business logic is yours.
  • Not opaque-token ready. It assumes JWTs. For opaque tokens, swap verify_token for an RFC 7662 introspection call and cache the result.

License

MIT — see LICENSE.


Built by Specter Systems — Claude MCP connectors, Python data pipelines and outreach automation. Doha, Qatar; working remotely.

from github.com/specter-systems/mcp-oauth-starter

Установить Oauth Starter в Claude Desktop, Claude Code, Cursor

Рекомендуется · одна команда, все IDE
unyly install oauth-starter

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

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

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

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

claude mcp add oauth-starter -- uvx --from git+https://github.com/specter-systems/mcp-oauth-starter mcp-oauth-starter

Пошаговые гайды: как установить Oauth Starter

FAQ

Oauth Starter MCP бесплатный?

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

Нужен ли API-ключ для Oauth Starter?

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

Oauth Starter — hosted или self-hosted?

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

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

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

Похожие MCP

Fetch

Web content fetching and conversion for efficient LLM usage.

автор: Community

Roblox Studio

Enables AI coding tools to control Roblox Studio for workspace exploration, instance manipulation, and script management. It provides tools for playtesting, sce

paralovавтор: paralov

AWS KB Retrieval

Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.

modelcontextprotocolавтор: modelcontextprotocol

Spring AI MCP Server

Provides auto-configuration for setting up an MCP server in Spring Boot applications.

автор: Community

llm-analysis-assistant

A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also

xuzexin-hzавтор: xuzexin-hz

MCP-Agent

A simple, composable framework to build agents using Model Context Protocol by [LastMile AI](https://www.lastmileai.dev)

lastmile-aiавтор: lastmile-ai

Spring AI MCP Client

Provides auto-configuration for MCP client functionality in Spring Boot applications.

автор: Community

mcp.natoma.ai

A Hosted MCP Platform to discover, install, manage and deploy MCP servers by [Natoma Labs](https://www.natoma.ai)

автор: Community

MCPHub

Website to list high quality MCP servers and reviews by real users. Also provide online chatbot for popular LLM models with MCP server support.

автор: Community

MCP Servers Rating and User Reviews

Website to rate MCP servers, write authentic user reviews, and [search engine for agent & mcp](http://www.deepnlp.org/search/agent)

автор: Community

Compare Oauth Starter with

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

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

Автор?

Embed-бейдж для README

Похожее

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