What is MCP and a resource server?
If you already know MCP and OAuth resource servers, skip this and go to How AuthSec protects your MCP server.
This page is the background you need before the rest of the docs make sense.
MCP in 60 seconds
MCP stands for Model Context Protocol. It's the protocol AI clients like Claude Desktop, Codex, and Cursor use to talk to external services. Anthropic published the spec; the ecosystem now has hundreds of MCP servers.
An MCP server is an HTTP service that speaks MCP. It exposes:
- Tools the AI can call — "create a GitHub issue", "query the customer database", "send a Slack message".
- Resources the AI can read — files, records, anything.
- Prompts the AI can use as templates.
The AI client (Claude Desktop, etc.) discovers what an MCP server exposes by calling tools/list, then invokes specific tools as the user works.
So when someone says "I built a GitHub MCP server," they mean: an HTTP service exposing tools like list_repos, create_pr, merge_pr — callable by any MCP-aware AI client.
Why MCP needs authentication
The moment an MCP server exposes anything beyond read-only public data, you need authentication. Two reasons:
- Different users have different access. Alice can merge PRs in
acme/website; Bob can only read. - Different AI clients ask for different scope. Claude Desktop with a personal account is not the same trust level as a CI-driven agent running unattended.
You don't want the same MCP server returning the same things to everyone who points an AI at it.
Why MCP uses OAuth
Two choices for adding auth: invent your own (token in a header you make up, custom challenge protocol, etc.) or use OAuth, which every AI client already speaks.
OAuth wins because:
- AI clients know it already. Claude Desktop, Cursor, Codex all implement the OAuth flow. You don't teach them anything.
- It separates the AI client from the user. The user logs in once and consents to scopes; the AI client gets a token and uses it. Compromise the token, you revoke just that token — not the user's password.
- It gives you scopes. Fine-grained per-tool access (you can write PRs but not delete the repo) is a solved problem in OAuth land.
The MCP spec defers to OAuth 2.1 (the modern OAuth profile) for authentication. AuthSec implements all the OAuth machinery so you don't have to.
What's a "resource server"?
In OAuth terminology your MCP server (or any HTTP service you're protecting) is the resource server. It's the service that holds the resources — the actual tools, data, business logic — and that needs to check tokens.
There are three roles in any OAuth flow:
| OAuth role | What it does | In AuthSec |
|---|---|---|
| Authorization server | Issues tokens. Runs the login / consent flow. | AuthSec |
| Resource server | Holds the resources. Validates incoming tokens. | Your MCP server / API / agent |
| Client | The thing making the request on the user's behalf. | The AI client (Claude Desktop, etc.) |
So when you read "register a resource server" in older OAuth docs, that's exactly what we mean by register an Application in AuthSec. We use "Application" in the UI because it's a less technical word — your MCP server, your API, your AI agent are all the same thing in the OAuth-resource-server sense, and they're all just "applications you want to protect" from the operator's point of view.
Resource URI
When AuthSec mints a token for a specific Application, the token's aud (audience) claim is set to the Application's Resource URI — composed as <public base url><protected path>. So an MCP server registered with:
- Public base URL:
https://mcp.acme.example - Protected path:
/mcp
Has Resource URI: https://mcp.acme.example/mcp
This binding is what stops a token issued for your MCP server from working against someone else's MCP server. See confused-deputy attacks for why this matters.
Why /mcp?
By convention, MCP servers expose their JSON-RPC handler at the path /mcp. AI clients are usually configured with the base URL of the server (e.g. https://mcp.acme.example) and append /mcp to find the handler. You can technically use any path — but if you pick something other than /mcp, every AI client connecting to your server has to know it. Stick to /mcp unless you have a reason.
Putting it together
You're building an MCP server. The shape of the world:
+----------------+ +----------------+ +----------------+
| AI Client | ----> | Your MCP svr | <-----> | AuthSec |
| (Claude, etc.) | | (resource svr) | | (auth svr) |
+----------------+ +----------------+ +----------------+
^ | |
| | introspect / validate |
+-------------------------+--------------------------+
user logs in once, here, gets a token
- User opens an AI client and points it at your MCP server.
- AI client makes a request, gets
401with a pointer to AuthSec. - AI client redirects the user to AuthSec to log in and consent to scopes.
- User logs in, approves the scopes, gets sent back to the AI client with a token.
- AI client retries the request with
Authorization: Bearer …. - Your MCP server (with the AuthSec SDK mounted) validates the token against AuthSec, checks scope, runs the tool, returns the result.
Steps 1–4 happen once per user per AI client. Step 5–6 happen every request after that. You write your tools. AuthSec handles everything else.
Related
- How AuthSec protects your MCP server — the 5-check flow on every request
- Register an application — start protecting your first one
- Scope design for MCP tools — how to model per-tool access
- Troubleshoot OAuth tokens — when something's denying when it shouldn't