Skip to content
Blog
Explainer

What is an MCP server, and what it quietly asks you to own

An MCP server exposes tools, resources and prompts to AI clients over the Model Context Protocol. What it is, how it works, and why it is not the thing that authorizes the agent.

Dharmendra Jagodana9 min read

In short

An MCP server is a program that exposes tools, resources and prompts to an AI client over the Model Context Protocol, as JSON-RPC over stdio or HTTPS. It does not authorize the agent: under the 2026-07-28 spec a remote one is an OAuth 2.1 resource server, and a separate authorization server issues its tokens.

An MCP server is a program that exposes tools, resources and prompts to an AI client over the Model Context Protocol. The client asks what is on offer, the server answers with a typed list, and the model calls entries by name. Locally that server is a subprocess on your laptop. Remotely it is an HTTPS endpoint you host.

Every explainer on the first page of results says roughly that, and they are right. Then they stop, usually one paragraph before the question that actually blocks people: who is allowed to call it?

The moment your server stops being a subprocess on your own machine and becomes a URL, the protocol hands you a second job it does not do for you. Under the current revision an MCP server is an OAuth 2.1 resource server. It validates tokens. It does not issue them. Something else has to, and that something else is an authorization server with discovery, a consent screen and revocation.

Key takeaway

The protocol is the easy half. An MCP server validates tokens it did not issue, which means a remote one is only as shippable as the authorization server sitting behind it.

Why the protocol exists

MCP exists to stop every assistant and every data source needing a bespoke integration.

Anthropic published it on 25 November 2024 with a specification, SDKs and a set of prebuilt servers for things like Git, Postgres and Slack. In December 2025 it was donated to the Agentic AI Foundation, a directed fund under the Linux Foundation set up with Block and OpenAI, whose platinum members now include AWS, Bloomberg, Cloudflare, Google and Microsoft. The announcement of that handover cited more than 10,000 active public MCP servers.

The problem it solves is the old N times M one. Five assistants and twenty data sources is a hundred integrations if each pair is its own adapter, and twenty five if both sides agree on a protocol. Nothing about that is novel. It is the same argument that produced ODBC and the Language Server Protocol, and it works for the same reason.

How it actually works

Three roles, one wire format. A host is the application a person is using, a client is the connector inside it that holds one connection, and a server is the thing you write. Every message is JSON-RPC 2.0.

What a server exposes comes in three kinds, and the useful distinction between them is not what they contain but who decides to use them:

  • Tools are model-controlled. The model picks one and calls it, which is why a tool that writes anything deserves more thought than its code suggests.
  • Resources are application-controlled. The host decides what to pull in as context: file contents, a query result, git history.
  • Prompts are user-controlled. They surface as slash commands or menu items that a person deliberately invokes.

Two transports are standard. With stdio the client launches your server as a subprocess and speaks newline-delimited JSON-RPC over the pipe. With Streamable HTTP every message is an HTTP POST to a single endpoint, and the reply is either a JSON object or a stream scoped to that request.

If you are reading older material, one change in the 2026-07-28 revision will trip you up. The protocol is now stateless: there is no initialize handshake and no protocol-level session. Each request carries the version it expects in its metadata, the server accepts or rejects it per request, and a mandatory server/discover RPC returns supported versions, capabilities and identity in one go. Servers no longer initiate requests of their own.

The half that is not MCP

Almost none of a remote connection is protocol-specific. Here is the shape of one.

An agent calls your server with no token. You answer 401 with a WWW-Authenticate header naming where your protected resource metadata lives. That document, defined by RFC 9728, is required: the spec says an MCP server MUST implement it. The client reads it, finds which authorization server you trust, fetches that server's metadata, and runs an ordinary OAuth 2.1 authorization code flow with PKCE. S256 is required, and a client MUST refuse to continue if the authorization server does not advertise support for it.

One parameter in that flow does most of the security work. RFC 8707 resource indicators mean the client MUST send a resource parameter, set to your server's canonical URI, in both the authorization request and the token request, whether or not the authorization server appears to support it. That is what binds the resulting token to you specifically.

Which sets up the two hard rules. A server MUST validate that a token's audience is itself, and MUST NOT accept or pass through a token issued for someone else. The spec calls token passthrough explicitly forbidden, and the reasoning is worth reading even if you never implement MCP. A server that forwards a caller's token upstream breaks the audit trail and bypasses whatever controls the upstream thought it had. The trust boundary becomes a hallway.

Notice what none of this is. There is no MCP-specific auth mechanism to learn. It is OAuth 2.1 with three RFCs bolted on, which is good news if you already run an authorization server and a surprise bill if you do not.

What the spec deprecated, and why your tutorial is probably wrong

This is the part that goes stale fastest, so here are the rows that change how you build, as of 28 October 2026, read from the specification's own deprecations page.

FeatureDeprecated inUse instead
HTTP+SSE transport2025-03-26Streamable HTTP
Dynamic Client Registration (RFC 7591)2026-07-28Client ID Metadata Documents
Sampling2026-07-28Call the model provider directly
Roots2026-07-28Tool parameters, resource URIs
Logging2026-07-28stderr, OpenTelemetry

None of it has been removed yet. The four deprecated in 2026-07-28 cannot go before the first revision dated on or after 28 July 2027. HTTP+SSE runs on a different clock: three months after SEP-2596 reaches Final.

The registration row is the one that matters, and it is the reason to distrust most of what you will read about MCP auth. Dynamic client registration was how an agent you had never met got a client ID without a human filling in a form. Several of the pages ranking for it today still present it that way. It is now deprecated in favour of Client ID Metadata Documents, where the client is identified by a URL that resolves to its own metadata. A page that describes DCR as the way agents register is describing the 2025 spec.

When an MCP server is the wrong choice

An explainer that only lists reasons to say yes is a brochure. Four cases where the answer is no:

You control both ends. If one application calls one model and you own both, an MCP server is indirection with a spec attached. Call your own functions. MCP earns its keep when the client is something you did not write.

You need it to be local, and it is. A stdio server reading your filesystem is genuinely simple and needs no authorization at all, because the credentials come from the environment the client launched it in. The spec says so. Going remote is what adds the OAuth bill, so do not go remote by default.

Your tool descriptions come from somewhere you do not trust. The specification states plainly that descriptions of tool behaviour should be treated as untrusted unless they come from a trusted server. A description is text the model reads and acts on. A server you did not write is a channel straight into your model's instructions.

You cannot own the consent screen. The spec's security guidance walks through the confused deputy case: a static client ID at a third-party authorization server, plus a consent cookie from an earlier approval, lets an attacker register their own redirect URI and skip the screen entirely. The mitigations are per-client consent recorded per user, exact-string redirect URI matching with no wildcards, and a single-use state cookie set only after approval. All three are authorization server responsibilities. If you are not running one, you are trusting someone who is.

What this costs when you actually run it

We build the authorization half, and the SDK ships the server half as an /mcp entry point. The numbers below are ours rather than the specification's, and they are what that second job looks like once it is running.

Every app built on BuildBase is an OAuth 2.0 authorization server for agents and third-party apps. That is a separate thing from the sign-in methods a person uses, and it never counts as one of them. Each organization gets its own RFC 8414 metadata document, cached for 300 seconds and invalidated whenever a client changes. It advertises S256 as the only code challenge method and none as the first supported token endpoint auth method, because the public clients doing the calling authenticate with PKCE alone.

Access tokens last 1 hour. Refresh tokens for agent clients last 30 days and rotate on every use, against 180 days for first-party app clients. Authorization codes expire after 10 minutes. Registration accepts at most 20 redirect URIs, rejects anything that is not HTTPS or loopback, and rejects a URI carrying a fragment or userinfo, since https://[email protected]/cb reads as your domain to a human and as evil.test to a browser. Replaying a consumed refresh token does not just fail, it revokes the whole token family.

One thing we got wrong first, which is usually the useful part. We originally published scopes on the authorization server, and that was the wrong place: scopes belong to the application that owns the data, not to a shared authorization server that sits across all of an organization's clients and resources. Our metadata now deliberately omits scopes_supported and the app publishes its own RFC 9728 document instead. The admin API rejects the old fields rather than quietly ignoring them.

And the honest one. Our implementation targets the 2025-06-18 revision, not 2026-07-28. Dynamic client registration is still our registration path where an organization turns it on, which is the mechanism the current spec deprecated. It works. It has until that 2027 revision, and moving to Client ID Metadata Documents is on us. A post that told you to check the spec revision and then skipped its own would not be worth much.

Where this sits

An MCP server is a protocol adapter in front of things you already have. The interesting questions are almost never about the adapter.

Weighing what belongs in your own service against what belongs in a dependency? The reasoning is the same here as anywhere else in a SaaS backend. If what you actually want is for another system to be told when something changes, rather than to come and ask, you want a webhook and not this. And the part that decides what an agent may touch once it is acting as a specific person is your roles and permissions model. MCP has no opinion about that at all.

mcp
ai-agents
oauth

Frequently Asked Questions

Is an MCP server a real server?

A local one is usually just a process on your machine that the client launches and talks to over stdin and stdout, so calling it a server is a stretch. A remote one is a real HTTPS service you host, secure and pay for. The word covers both, which is a large part of why the term confuses people.

How does an MCP server work?

The client asks what the server offers, the server answers with a typed list of tools, resources and prompts, and the model calls them by name with JSON arguments. Everything travels as JSON-RPC 2.0, either down a pipe to a subprocess on the same machine or as HTTP POSTs to a single endpoint.

Should OAuth live inside the MCP server or in a separate authorization server?

Separate. The spec makes the MCP server an OAuth 2.1 resource server: it validates tokens and answers an unauthenticated call with a 401 pointing at its protected resource metadata. The authorization server can run on the same box, but it is a distinct role with its own discovery, consent screen and revocation.

How should an MCP server validate access tokens?

Check the audience first. The spec says a server MUST reject a token that was not issued for it, and MUST NOT forward a token it received to an upstream API. That audience check is what stops a token lifted from some other service being replayed against yours, and skipping it is the mistake the spec calls out by name.

Put this into practice

The modules in this post are one console away. Start on the Free plan, or try a paid plan free for 7 days, no credit card.

Free plan7-day free trial on paid plansNo credit card required