Remote MCP Server with OAuth: What It Takes to Build
Building a remote MCP server with OAuth: protected resource metadata, resource indicators, audience-checked tokens, no token passthrough, and well-scoped tools.
A remote MCP server with OAuth is an HTTP endpoint that lets assistants such as ChatGPT, Claude, and Cursor call your product's tools for a signed-in user. Building one properly takes four things: protected resource metadata so clients find your authorization server, tokens bound to your server, an audience check on every request, and a small set of well-scoped tools.
TL;DR: Follow the current MCP authorization spec (revision 2026-07-28, checked 21 October 2026). Serve RFC 9728 metadata, return 401 with a pointer to it, accept only tokens issued for your server, never forward the client's token upstream, and expose a few read-first tools scoped to the user. Workers suits the thin HTTP layer.
NoteTube has one: a remote MCP server on Cloudflare Workers with OAuth, protected-resource metadata, and audience-checked tokens, so ChatGPT, Claude, and Cursor can query a student's notes. This post walks through the parts using the spec's own rules. The spec revises often, so every requirement below links to the revision we checked.
What is a remote MCP server?
A remote MCP server is a Model Context Protocol server that runs on your infrastructure and serves many users over HTTP, instead of running on one person's computer. It exposes tools (actions the assistant can call), resources (data it can read), and prompts. The assistant's built-in MCP client discovers what the server offers and calls it.
The protocol itself uses JSON-RPC 2.0 messages between hosts, clients, and servers (MCP specification). Authorization is optional in the spec, but the spec says HTTP-based implementations should follow its authorization rules, while local stdio servers should take credentials from the environment instead (MCP authorization, 2026-07-28). In practice, a remote server that touches user data needs OAuth.
Local or remote: which do your users need?
If your users aren't developers, remote is the only realistic choice. Nobody's accountant is editing a JSON config file to install a local process. A local server suits developer tools and local files; a remote one suits SaaS products whose customers just want to click "connect" in their assistant.
| Local MCP server | Remote MCP server | |
|---|---|---|
| Runs | On the user's computer | On your infrastructure |
| Users | One, technical enough to install it | Anyone with an account |
| Auth | Credentials from the environment | OAuth sign-in per user |
| Best for | Developer tools, local files | SaaS products and their customers |
How does the remote MCP server OAuth flow work?
The flow builds on OAuth 2.1 and three published standards. The assistant hits your server without a token, gets pointed to your metadata, signs the user in at your authorization server, and comes back with a token issued for your server only. Here are the steps as the 2026-07-28 revision describes them:
- The user adds your server's URL in their assistant.
- The assistant calls the server without a token and gets
401 Unauthorized. - The 401 carries a
resource_metadataURL in theWWW-Authenticateheader, or the client falls back to a well-known URL. MCP servers must implement RFC 9728, OAuth 2.0 Protected Resource Metadata, whose default path is/.well-known/oauth-protected-resource. - That metadata names your authorization server in
authorization_servers. The assistant fetches the authorization server's own metadata to learn its endpoints. - The assistant sends the user to sign in, using PKCE and a
resourceparameter that names your server, as defined in RFC 8707, Resource Indicators for OAuth 2.0. - The assistant gets an access token and sends it in the
Authorization: Bearerheader on every request. Tokens must never go in the query string. - Your server validates the token, including its audience, and handles the call.
The server can also put a scope value in the 401 challenge, so the assistant asks only for what's needed. Start small. You can always challenge for more later with a 403 and insufficient_scope.
Why are audience checks not optional?
Audience checks stop a token issued for some other service from being replayed against yours. The spec says MCP servers must validate that tokens were issued specifically for them, must reject tokens that don't name them as the audience, and "MUST NOT accept or transit any other tokens" (MCP authorization, 2026-07-28).
That last phrase also bans token passthrough. If your MCP server calls your own internal API or a third-party API, it uses a separate token for that call. It doesn't forward the one the assistant sent. The spec's security guide lists why: passthrough skips the downstream service's rate limits and checks, and it wrecks your audit trail, because logs show the wrong caller (MCP security best practices).
NoteTube's MCP server checks the token audience on every request. The same separation runs through the rest of NoteTube: the AI provider keys live only in a separate FastAPI service, and no client ever sees them. The reasons are in how we keep AI API keys out of clients. An MCP client is just one more client.
How do assistants register as OAuth clients?
An assistant needs a client identity at your authorization server before the flow starts. The 2026-07-28 revision gives three ways: Client ID Metadata Documents, pre-registration, and Dynamic Client Registration. Client ID Metadata Documents are the recommended path, and Dynamic Client Registration is now marked deprecated.
With a Client ID Metadata Document, the client's ID is an HTTPS URL that hosts a JSON document with its name and redirect URIs. Your authorization server fetches it, checks that the client_id in the document matches the URL exactly, and validates redirect URIs against it. Fetching URLs supplied by strangers is a server-side request forgery risk, so restrict what that fetch can reach.
The spec keeps Dynamic Client Registration "for backwards compatibility with authorization servers that do not support Client ID Metadata Documents" (MCP authorization, 2026-07-28). Check what each assistant you care about supports today; client support moves faster than blog posts.
The same revision also asks authorization servers to include an iss parameter in authorization responses (RFC 9207), so clients can confirm which server answered. If you run your own authorization server, add it now.
How should you design the tools?
Design tools for an AI reader. The model picks tools by name and description, so a few clear tools beat twenty narrow endpoints. Then scope every call to the signed-in user on the server, exactly as your API already does.
- Few, clear tools. A "search notes" tool and a "get note" tool beat a wall of endpoints. Each description should say what the tool does and when to use it.
- Typed inputs. Define input schemas tightly. Cap result sizes, and paginate.
- Read before write. Ship read-only tools first. Add tools that change data only with a clear need, and name them so the user can't miss what they do.
- Scope everything to the user. Every call runs as the token's user and sees only their data. Our post on multi-tenant vector search covers that for retrieval.
- Return checkable text. Include titles, dates, and links back to your product, so the user can verify the source.
For NoteTube, querying a student's notes is the same retrieval the product already runs for its own chat. The MCP server is a new door into an existing system, not a new system, which is how we'd approach any product's first MCP server.
Why run a remote MCP server on Cloudflare Workers?
A remote MCP server is mostly short HTTP requests, OAuth redirects, and calls into your existing backend. That fits a serverless edge platform: nothing to keep running, global by default, billed per request. NoteTube's server runs on Workers, and we cover the platform on our Cloudflare Workers page.
Cloudflare's guide deploys remote MCP servers over the Streamable HTTP transport and recommends the stateless createMcpHandler() API for new servers. It also shows an OAuthProvider wrapper that handles sign-in and token issuing, connectable to any OAuth 2.0 provider (Cloudflare remote MCP guide).
Heavy work, like retrieval over a large index, stays in your main backend. The Worker calls it with its own service credentials, which is exactly the separate-token rule from earlier.
Do you need an API before an MCP server?
It helps a lot. An MCP server is a thin layer over operations your product already has. If those operations live in a clean, authenticated API, each tool maps onto one or two calls. If they're tangled into web pages, you'll build the API anyway, just later and under pressure. Our API development page covers that groundwork.
What belongs on the launch checklist?
Before you list the server anywhere, check each item against the spec and against a second test account. These are the failures we'd look for first in any review.
| Check | Why |
|---|---|
| Protected resource metadata names the right authorization server | Clients can't start the flow without it |
401 responses include resource_metadata |
Fastest discovery path for clients |
| Signature, expiry, and audience checked on every request | Blocks tokens issued for other services |
| No token passthrough to upstream services | Required by the spec; keeps audit trails honest |
| Tools scoped to the user, tested as two users | Proves one user can't read another's data |
| Rate limits per user and per client | One misbehaving assistant can't flood you |
| Logs of which client called which tool, without private content | Answers "who did this?" without a data leak |
| Users can see and revoke connected assistants | Consent has to be reversible |
| Tested end to end in each assistant you support | Client support varies |
FAQ
Does a remote MCP server need its own authorization server?
No. The spec says the authorization server can be hosted with the MCP server or be a separate service, including an identity provider you already use. It must support OAuth 2.1 and publish its metadata, and your protected resource metadata must point to it in the authorization_servers field.
What is the resource parameter in MCP OAuth?
It's the RFC 8707 Resource Indicators parameter. The MCP client must send it in both the authorization and token requests, set to your server's canonical URI, so the authorization server can issue a token meant only for your server. Your server then checks the token's audience matches.
Is Dynamic Client Registration still supported in MCP?
Yes, but the 2026-07-28 revision marks it deprecated and keeps it for authorization servers that don't support Client ID Metadata Documents. New authorization servers should support Client ID Metadata Documents, and clients are told to prefer pre-registration, then metadata documents, then dynamic registration.
Can an MCP server forward the user's token to our API?
No. The spec forbids token passthrough. Your MCP server must accept only tokens issued for itself, and when it calls your internal API or a third-party API, it uses a separate credential for that call. Forwarding bypasses downstream checks and leaves logs pointing at the wrong caller.
Want ChatGPT, Claude, or Cursor to work with your product? See our MCP server development work and tell us which tools your users would ask for first.