Discovery and metadata
The SDK serves your server's protected resource metadata, so clients find your sign in service and the scopes to ask for.
AI access
An AI client can connect to your MCP server and act for one of your users. People sign in on your pages and approve each permission, and the client gets a token that only your server accepts.
from fastapi import FastAPI
from mcp.server.mcpserver import MCPServer
from microauth_fastapi import McpAuth, current_identity
mcp = MCPServer("Invoices", log_level="WARNING")
auth = McpAuth(scopes=["invoices:read"]) # reads MICROAUTH_ISSUER and MICROAUTH_RESOURCE
INVOICES: list[dict] = []
@mcp.tool()
@auth.tool("invoices:read")
def list_invoices() -> list[dict]:
me = current_identity().sub
return [invoice for invoice in INVOICES if invoice["owner"] == me]
@mcp.tool()
@auth.tool("invoices:write")
def create_invoice(customer: str, amount_cents: int) -> dict: ...
app = FastAPI()
auth.mount(app, mcp) # serves /mcp and its metadata next to your other routes
from fastapi import FastAPI
from mcp.server.mcpserver import MCPServer
from microauth_fastapi import McpAuth, current_identity
mcp = MCPServer("Invoices", log_level="WARNING")
auth = McpAuth(scopes=["invoices:read"], api_keys=True) # also reads the server credentials
@mcp.tool()
@auth.tool("invoices:read")
def whoami() -> dict:
me = current_identity()
return {"user": me.sub, "via": me.via, "key": me.key_id}
app = FastAPI()
auth.mount(app, mcp)
How it works
MicroAuth follows the MCP authorization spec, so clients that support it connect without any setup on their side. You keep your tools and your data.
Your MCP server answers with its metadata, which names your sign in service and the scopes to ask for.
They sign in on your pages and see the app, where it sends them back and each permission it wants.
The client gets a short lived token that only your MCP server accepts, with only what the person holds and allowed.
The SDK checks the token and the scopes each tool needs. Your code still decides which records the person can touch.
The consent screen shows the app, the account, where it sends them back and each permission, using the descriptions you wrote.
When a tool needs more, the client asks again for just the new permissions, which join the existing grant.
People see every app they allowed and disconnect any of them. You can block an app for everyone.
A request without a valid token gets a 401 that points to your server's metadata. A tool call missing a scope gets a 403 that names every scope the tool needs, so the client asks the person once.
Refusals also carry a JSON-RPC error body with the reason, so clients can show the person what went wrong.
$ curl -X POST https://app.example.com/mcp
401WWW-Authenticate: Bearer resource_metadata="https://app.example.com/.well-known/oauth-protected-resource/mcp", scope="invoices:read"
# a token holding invoices:read calls list_invoices
200{"result":{"content":[...]}}
# the same token calls create_invoice
403WWW-Authenticate: Bearer error="insufficient_scope", scope="invoices:read invoices:write"
Turn on apps people connect, register your MCP server with its URL and the permissions its tools need, and protect it with McpAuth.
Then click Check MCP server. MicroAuth fetches your server's metadata, confirms it names your sign in service and the server's URL, and warns when a request without a token doesn't get a 401 that points to it.
Features
The SDK serves your server's protected resource metadata, so clients find your sign in service and the scopes to ask for.
Declare the scopes each tool needs with @auth.tool(...). A token missing one gets a 403 that names them.
People approve each permission, and a client that needs more asks again for just the new ones.
People disconnect apps from their account page, and you can block an app for everyone on your service.
AI clients use Client ID Metadata Documents, and older ones can register themselves. Each one is labeled on the consent screen.
A client that can't do OAuth can use an API key the person creates, limited to the permissions they choose.
Questions
Clients that follow the MCP authorization spec. They identify themselves with a Client ID Metadata Document, or register themselves when they are older. Apps people connect are turned on per service, on the plans that include them.
No. The client only gets permissions the person holds and approved, in a token for your MCP server alone. Scopes don't decide which records a tool may touch, so your tools still check that a record belongs to the person.
On their account page, people see every app they allowed and can disconnect it. A disconnected app can't refresh its tokens, and the access token it already has works until it expires, 10 minutes at most.
Yes. McpAuth mounts your MCP server in your FastAPI app, next to your other routes. If you prefer the MCP SDK's own auth settings, MicroAuthTokenVerifier plugs into them and checks tokens the same way.
Yes. Serve protected resource metadata that names your sign in service, answer requests without a valid token with a 401 that points to it, and check access tokens with the published signing keys. The docs walk through each step.
Create a sign in service for your MCP server, protect it with a few lines of FastAPI and click Check MCP server. Your users decide what each client can do.