# 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.

- Source: https://www.buildbase.app/blog/what-is-an-mcp-server
- Section: Blog
- Author: Dharmendra Jagodana
- Published: 2026-10-28

## 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.

| Feature                                | Deprecated in | Use instead                      |
| -------------------------------------- | ------------- | -------------------------------- |
| HTTP+SSE transport                     | `2025-03-26`  | Streamable HTTP                  |
| Dynamic Client Registration (RFC 7591) | `2026-07-28`  | Client ID Metadata Documents     |
| Sampling                               | `2026-07-28`  | Call the model provider directly |
| Roots                                  | `2026-07-28`  | Tool parameters, resource URIs   |
| Logging                                | `2026-07-28`  | stderr, 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](/blog/new-sign-in-methods), 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://app.example.com@evil.test/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](/blog/what-is-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](/blog/what-are-webhooks) 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](/blog/what-is-rbac). MCP has no opinion
about that at all.
