warrant
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@warrantsearch my notes for anything about the quarterly budget"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
warrant
A remote MCP server that acts as a proper OAuth resource server: every tool call is authenticated against an external identity provider, authorized per tool, and scoped to the caller's own data.
Status: work in progress.
The problem
Most MCP server examples run over stdio and trust whoever launched them. On a URL, every request comes from a client you don't control, carrying a token issued by an authorization server you don't run. Each request has to answer:
Is the token genuine? Signature against the issuer's published keys, issuer, expiry.
Was it issued for this server? A token minted for a different API is refused (audience). Otherwise any service that sees a user's token can replay it here.
Can it call this tool? Read and write are separate scopes; a read-only token can't create.
Whose data? Every query is filtered by the token's subject. There is no unscoped read path.
The server never issues tokens. Login, consent and client registration stay with the authorization server; this side only verifies.
Related MCP server: Note App MCP Server
What it does
client ── POST /mcp + Bearer ──▶ JwtVerifier ──▶ scope gate ──▶ tool ──▶ NoteStore
▲ JWKS, iss, tool → scope owner = SQLite
│ aud, exp │ token.sub
├── 401 + resource_metadata ◀── missing / invalid │
│ (discover the authorization server, log in) │
└── 403 insufficient_scope ◀────────────────────────┘
(re-authorize with the added scope, retry)Discovery — an unauthenticated request gets
401withWWW-Authenticate: Bearer resource_metadata=.... The protected resource metadata (RFC 9728) names the authorization server and the baseline scope,notes:read, so a client can log in without per-server configuration.Step-up — a call the token lacks scope for gets
403withWWW-Authenticate: Bearer error="insufficient_scope", scope="...", listing everything that operation needs. The client re-authorizes and retries, so write access is granted when first used, not at login.JwtVerifier (
auth.py) — validates JWT access tokens (RFC 9068) against the issuer's JWKS: signature,iss,aud,exp,sub. RS256 only. An unknown key ID triggers one JWKS refetch (key rotation), with a cooldown so forged key IDs can't make it hammer the issuer.Scope gate (
server.py) —TOOL_SCOPESmaps each tool to its scope. The HTTP gate reads the tool from the 2026-07-28Mcp-Nameheader, which the SDK rejects if it disagrees with the body. A handler-tier check repeats it for requests without the header, and fails closed on a tool missing from the map.NoteStore (
store.py) — SQLite. Every method takes the owner.
Tools
Tool | Scope | Notes |
|
| Case-insensitive substring; empty query lists the most recent. |
|
| Another user's note reads as not found. |
|
|
Every request also needs notes:read.
Explicit non-goals
Not an authorization server — no login, token issuance or client registration. Targets any OIDC provider that issues JWT access tokens.
Not a gateway — one server, its own tools.
Notes are a deliberately small domain; the auth layer is the point.
Protocol
Built on the official Python SDK (mcp 2.x) at MCP revision 2026-07-28:
stateless, no sessions, each request carries its own protocol version. The SDK
handles transport and the 401. Token verification, per-tool scopes, the
403 step-up challenge and per-user data scoping are here.
tests/test_oauth_flow.py runs the SDK's own OAuth client against the server
and a stub authorization server: discovery, a notes:read login, a 403 on
create_note, re-authorization for notes:read notes:write, and the retry.
Quickstart
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest -q
warrant --dev--dev needs no identity provider. It runs a local issuer (signs tokens and
serves its keys; not an authorization server) and prints a read token and a
read+write token for user dev. Pass one as a bearer header from any MCP
client, e.g. Claude Code:
claude mcp add --transport http warrant http://127.0.0.1:8000/mcp --header "Authorization: Bearer <token>"With the read token, create_note gets the 403 step-up challenge. A static
header can't re-authorize, so the call stops there.
Against an identity provider
The API (audience) identifier is the server's public /mcp URL, with
notes:read and notes:write defined as its scopes:
warrant --issuer https://YOUR_TENANT/ --resource-url http://localhost:8000/mcpThis server cannot be deployed
Maintenance
Related MCP Connectors
An authenticated remote MCP server for user-owned devices and one-shot capability invocation.
OAuth-protected, read-only-by-default MCP server for provenance-labeled QuillCaddie project memory.
The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.
- StytchOAuthdev.stytch.mcp
The Stytch MCP server is a reference implementation that demonstrates remote MCP server authentication and authorization using Stytch Connected Apps. It provides OAuth 2.1-compliant authorization (including PKCE), Dynamic Client Registration, and validates Stytch-issued access tokens to enable AI agents to securely interact with external services through permissioned access, supporting scopes like openid, email, profile, and manage:project_data.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA production-ready MCP server that authenticates agents via OAuth 2.1 Bearer tokens, validates JWTs with JWKS, enforces tool-level scopes and roles, and logs the full delegation chain.-
- FlicenseNot gradedqualityDmaintenanceMCP server for a JWT-authenticated note-taking API, exposing CRUD tools for notes.-
- AlicenseAqualityDmaintenanceA compact MCP server demonstrating explicit tool boundaries, least-privilege discovery, execution-time authorization, destructive-action confirmation, and metadata-only audit logs using a local note store.3MIT
- AlicenseNot gradedqualityBmaintenanceA personal note store exposed as an MCP server. Enables any MCP-speaking assistant to create, search, list, and categorize notes, with per-client bearer tokens for author attribution.129 npmMIT