AI access

Let AI clients use your MCP server, with only the access people approve

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
A scope says what kind of action a client may take. Your tool still returns only the records that belong to the person.

How it works

From the first call to a checked tool

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.

  1. The client finds you

    Your MCP server answers with its metadata, which names your sign in service and the scopes to ask for.

  2. The person approves

    They sign in on your pages and see the app, where it sends them back and each permission it wants.

  3. A token for one server

    The client gets a short lived token that only your MCP server accepts, with only what the person holds and allowed.

  4. Every tool call checked

    The SDK checks the token and the scopes each tool needs. Your code still decides which records the person can touch.

Consent

People stay in control

  • Each permission in plain words

    The consent screen shows the app, the account, where it sends them back and each permission, using the descriptions you wrote.

  • Consent that asks only for what's new

    When a tool needs more, the client asks again for just the new permissions, which join the existing grant.

  • Connected apps on the account page

    People see every app they allowed and disconnect any of them. You can block an app for everyone.

Clear refusals

Every refusal says what to do next

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.

Terminal
  • $ 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"

Setup

Check your server from the dashboard

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

What AI access includes

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.

Scopes per tool

Declare the scopes each tool needs with @auth.tool(...). A token missing one gets a 403 that names them.

Consent and step up

People approve each permission, and a client that needs more asks again for just the new ones.

Connected apps

People disconnect apps from their account page, and you can block an app for everyone on your service.

Clients identify themselves

AI clients use Client ID Metadata Documents, and older ones can register themselves. Each one is labeled on the consent screen.

Keys for clients without OAuth

A client that can't do OAuth can use an API key the person creates, limited to the permissions they choose.

Questions

About AI access

Which AI clients can connect to my MCP server?

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.

Can a client do more than the person allows?

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.

How do people take access away?

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.

Does it work with the official MCP Python SDK?

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.

My MCP server isn't written in Python. Can I still use it?

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.

Open your MCP server to AI clients

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.