Not OAuth, not quite REST

Two common first guesses: “MCP is an OAuth-style flow” and “MCP is just a REST API with a spec”. The first is wrong, the second half right. Sorting them out gives you the layer picture the rest of the course uses.

By the end of this lesson you can

  • draw MCP, its authorization layer and its two transports as layers;
  • say when OAuth applies and where a stdio server's credentials come from instead;
  • compare MCP with a REST API on consumer, shape, direction, versioning, transports and trust;
  • explain the LSP analogy and the M plus N argument.

Three layers

MCP is an application protocol: JSON-RPC 2.0 messages for tools, resources and prompts. OAuth sits at different layers: it is MCP's optional authorization layer, and it applies to one transport only.

The stack use the Show switch above to fade the other transport

MCP messages JSON-RPC 2.0: tools/*, resources/*, prompts/*, server/discover, subscriptions/listen stdio one JSON message per line, a subprocess Streamable HTTP one POST per message, JSON or SSE reply Authorization, optional OAuth 2.1 + PKCE, RFC 9728, RFC 8707 HTTP only stdio has no OAuth: credentials come from the environment env: { "GITHUB_TOKEN": "…" } on every request:Authorization: Bearer eyJ… token
  1. On top: MCP messages. The same JSON-RPC methods whatever carries them.
  2. Underneath: two transport bindings. stdio for a local subprocess, Streamable HTTP for a remote endpoint.
  3. Only above HTTP sits an authorization layer: OAuth 2.1 with PKCE, Protected Resource Metadata (RFC 9728) and the resource parameter (RFC 8707).
  4. A stdio server has no OAuth: it gets credentials from the environment the host passes it. stdio servers SHOULD NOT use OAuth.
  5. On HTTP the result of the OAuth flow, a bearer token, rides on every POST in the Authorization header. Lesson 8 walks the whole flow.
MCPOAuth 2.1 with PKCE
KindApplication RPC protocolAuthorization framework
Closest relativeLanguage Server ProtocolOther delegated-access grants
PurposeAn AI application talking to tools and dataGetting a scoped access token for a user
RelationshipMCP uses OAuth as its authorization layer, on HTTP only. The full flow.

Which layer does that?

Sort each job into the layer responsible for it.

  • Defines tools/call and the shape of its result. That is the protocol itself: the same on stdio and HTTP.
  • Gets a token for one user, scoped to one MCP server. The OAuth flow, with the resource parameter naming the server.
  • Frames each message as exactly one line on stdin. Framing is the stdio transport binding's job.
  • Says an unsupported protocol version gets error -32022. A protocol-level error, identical on both transports.
  • Uses a PKCE code verifier so a stolen authorization code is useless. PKCE is part of OAuth 2.1.
  • Cancels a request by closing the HTTP response stream. How cancellation is signalled depends on the transport (on stdio it is a notification).

Not quite REST

“A way to talk to an external service with an agreed spec” is half right. In the current revision it is even JSON over HTTP POST, with bearer tokens and a stateless server. The differences are where the interesting engineering is.

REST APIMCP
ConsumerA developer who reads docs at build timeA model that discovers tools at run time and reads descriptions as instructions
ShapeResources and verbs, many URLsOne endpoint, named methods (RPC)
DirectionClient asks, server answersServer can ask the client for user input, a model completion or roots, inside its result
VersioningIn the URL or a header, chosen by youProtocol version and client capabilities on every request
TransportsHTTPstdio and HTTP, identical messages
TrustResponse data is dataServer-written text enters the model's prompt, so it can steer the model

Common misconception

“MCP replaces my REST API.” Usually it wraps it. Your REST API sits behind the MCP server, which turns it into a handful of well-described tools a model can use.

The better analogy: LSP

MCP is a standard adapter that turns any API into function-calling tools, the way the Language Server Protocol turns any compiler into editor features. The specification names LSP as its inspiration. The payoff is the same: integrations add up instead of multiplying.

From M × N to M + N

Claude IDE Your agent GitHub Postgres Jira 3 × 3 = 9 adapters MCP one protocol 3 + 3 = 6 adapters
  1. Without a shared protocol, every host writes its own integration for every service.
  2. Three hosts and three services: nine adapters, each maintained separately. M × N.
  3. With MCP, each host implements the client side once and each service exposes one server.
  4. Three plus three: six. Add a host or a service and you write one more, not three. M + N, exactly what LSP did for editors and languages.

Quick check

A local stdio server needs a GitHub token. How should it get one?

  • Run the OAuth flow with PKCE on startup
  • From its environment, passed by the host from the config
  • From the _meta of each request
OAuth is MCP's authorization layer for HTTP only. stdio servers SHOULD NOT use it; they read credentials from the environment.

Which difference from REST creates a security problem REST never had?

  • MCP uses a single endpoint
  • MCP sends the protocol version on every request
  • Server-written text enters the model's prompt and can steer it
In REST, response data is data. In MCP, descriptions and results are read by a model that follows instructions, which is the root of tool poisoning (lesson 9).

Four hosts want to use five services. With MCP, roughly how many integrations are written?

  • 20
  • 9
  • 5
M + N: four client implementations and five servers. Without a shared protocol it would be M × N, twenty.

Recap