Skip to main contentSkip to user menuSkip to navigation

Model Context Protocol

Understand Model Context Protocol: clients, servers, tools, resources, prompts, transport, and production integration trade-offs.

35 min readIntermediate
Not Started
Loading...

What is Model Context Protocol?

The Model Context Protocol (MCP) is an open protocol for connecting an AI application to programs that provide context or actions. Instead of inventing a connector for every integration, a host can use MCP to discover and exchange typed resources, prompts, and tools over JSON-RPC.

In plain language, MCP gives AI applications and capability providers a shared conversation format. It does not decide whether a server is trustworthy or whether an action is allowed.

The core invariant is capability is not authority. A successful handshake says which protocol features both sides understand. Authorization, user consent, tenant isolation, and operation policy remain separate decisions.

Keep the host, client, and server separate

An MCP deployment has three protocol participants. The distinction matters because each participant owns a different part of security and failure recovery.

One MCP connection

A host may manage many clients, but each client maintains one isolated connection to one server.

Application boundary

Host

Owns the user experience, model integration, consent, policy, and any movement of context between servers.

Session boundary

MCP client

Negotiates one stateful session, routes JSON-RPC messages, and tracks the capabilities of one server.

Capability boundary

MCP server

Publishes focused primitives and validates every request before touching its dependencies.

Data or side effect

External system

Provides the records, files, APIs, or business actions behind the server's MCP contract.

The host should give each server only the context needed for its task. A server should not receive the whole conversation or inspect another server's session.

Choose the primitive by who initiates it

MCP server primitives differ in how they enter the user experience. That ownership should shape discovery, review, and approval.

Application-controlled

Resources

Addressable context such as files, schemas, or records. The client lists or reads a URI, then decides whether the result belongs in model context.

User-controlled

Prompts

Reusable message templates. A user explicitly selects a prompt and supplies its arguments before the client retrieves the generated messages.

Model-controlled

Tools

Schema-described operations the model may request. The application should expose the request, validate its inputs, apply policy, and let a human deny sensitive calls.

Clients can also advertise features to servers, including roots, sampling, elicitation, and task support. Negotiating a feature only makes its messages legal for the session; it does not make every use safe.

Finish initialization before normal work

MCP is a stateful protocol. Initialization must be the first interaction, and both sides may use only the version and capabilities established for that session.

  1. 1

    Initialize

    Propose a version

    The client sends initialize with its latest supported protocol revision, implementation information, and client capabilities.

  2. 2

    Negotiate

    Return the contract

    The server returns a supported revision, server information, and server capabilities. The client disconnects if it cannot support the returned revision.

  3. 3

    Acknowledge

    Mark the session ready

    The client sends notifications/initialized. Normal tools, resources, and prompts operations begin only after this lifecycle boundary.

  4. 4

    Use

    Operate within bounds

    Both sides respect negotiated sub-capabilities, apply finite timeouts, validate messages, and terminate through the underlying transport.

For example, advertising resources does not imply subscription support, and advertising tools does not imply listChanged notifications or task-augmented calls. Check the specific capability object before sending related messages.

Compose the transport and capability contract

Transport selection changes process ownership, authentication, streaming, and failure behavior. Capability selection changes which protocol operations the session can legally perform. Build a connection and inspect both consequences together.

Loading connection composer...

The healthy design is not the bundle with the most features. It is the smallest negotiated surface that satisfies the workload across the correct process boundary.

Reject Unsupported Versions and Missing Capabilities

Select transport by deployment boundary

The protocol defines two standard transports. Both carry UTF-8 JSON-RPC messages, but they have different operating models.

Local subprocess

stdio

The client launches the server and exchanges newline-delimited messages through standard input and output. Logs belong on standard error. Pin the executable and constrain its environment, filesystem, and network access.

Remote or shared service

Streamable HTTP

The server exposes one MCP endpoint for POST and GET, with optional server-sent events. Validate Origin, authenticate protected requests, and bind local-only endpoints to localhost.

Streamable HTTP replaced the older HTTP+SSE transport from the 2024-11-05 revision. A compatibility migration may temporarily serve both, but new clients should target the current transport contract.

Treat schemas and annotations as inputs, not proof

MCP uses JSON Schema throughout the protocol. A tool can define an input schema and optional output schema, but schema validity proves only that a value has the expected shape.

Validate every boundary

  • Reject unknown fields when a tool contract should be closed.
  • Validate tool arguments before business logic and validate structured results before returning them.
  • Apply user, tenant, resource-ownership, rate-limit, and approval checks after schema validation.
  • Treat tool annotations as untrusted unless the server itself is trusted.
  • Sanitize returned text, links, and embedded resources before they enter model context.

Separate protocol errors from tool errors

  • Use JSON-RPC errors for invalid methods, malformed parameters, and protocol failures.
  • Return a tool result with isError: true for an expected operation failure the model can safely reason about.
  • Preserve correlation identifiers without logging tokens, authorization codes, secrets, or sensitive result bodies.

Put authorization around the session

For HTTP, MCP defines an OAuth-based authorization flow. Authentication protects access to the MCP endpoint, while host and server policy still decide whether a particular primitive or tool call is allowed.

A protected remote tool call

The token accepted by the MCP server is audience-bound to that server. A downstream API requires a separate credential.

Intent

User and host

Review the server, requested scopes, tool inputs, target resource, and side effect.

Grant

Authorization server

Issues a token for the canonical MCP server URI after the client requests the correct resource and scopes.

Enforce

MCP server

Validates issuer, audience, expiry, signature, scope, tenant, ownership, and current approval.

Separate audience

Downstream API

Receives its own credential. The server never forwards the client's MCP access token unchanged.

Token passthrough is forbidden by the MCP authorization specification. A token issued for the MCP server is not a reusable credential for a downstream API.

For stdio, the HTTP authorization flow does not apply. The local process normally receives narrowly scoped credentials through its environment, and the host must treat launching that process as a privileged action.

Recover the boundary that actually failed

An expired MCP session, an insufficient OAuth scope, a wrong token audience, and an ambiguous tool completion require different responses. Choose an incident and apply a recovery action to see whether it restores the correct boundary or creates a second failure.

Loading recovery runbook...

A lost HTTP connection does not prove that a write was canceled. Reconcile by operation identifier or server-side state before retrying, and make write tools idempotent when the dependency supports it.

Classify Session and Authorization Failures Before Retrying

Design timeouts, cancellation, and session state together

Bound request lifetime

  • Configure a finite timeout for every request.
  • Send a cancellation notification when the timeout expires and stop waiting for the response.
  • Allow progress to extend a working deadline only under an absolute maximum.
  • Remember that cancellation is a request, not proof that remote work stopped.

Keep session identity separate from user identity

  • Treat MCP-Session-Id as untrusted input and never as authentication.
  • Send MCP-Protocol-Version on subsequent HTTP requests.
  • If a server returns HTTP 404 for a known session, discard that session ID and initialize a new session.
  • Recheck authorization on every protected request and rotate session state when identity or grants change.

Make replay behavior explicit

  • Use caller-scoped idempotency keys for retryable writes.
  • Record an operation state that can distinguish accepted, running, completed, failed, and unknown outcomes.
  • Reconcile ambiguous outcomes before issuing another side effect.
  • Keep recovery evidence in audit logs without retaining secrets.

Review an MCP integration as three contracts

Interoperability

Protocol contract

Pin supported revisions, test initialization order, validate schemas, and use only negotiated capabilities and sub-capabilities.

Trust

Authority contract

Verify server provenance, minimize context, audience-bind tokens, separate downstream credentials, and require meaningful approval.

Operations

Recovery contract

Define timeout, cancellation, session expiry, reconciliation, idempotency, audit, revocation, and kill-switch behavior.

A production review should answer:

  • Which host owns user intent and each client connection?
  • Which protocol revision and exact capabilities were negotiated?
  • Which server supplied each primitive and returned content item?
  • Which host policy exposed it to the model, and which approval authorized the call?
  • Which identity, tenant, scope, and token audience reached each protected system?
  • Which evidence distinguishes a completed write from an ambiguous or retryable failure?

Sources and version notes

This lesson targets the latest stable MCP revision available while authoring, 2025-11-25. MCP uses dated revisions, so implementations should negotiate versions and consult the matching specification instead of treating a sample message as timeless.

No quiz questions available
Could not load questions file
Spotted an issue or have a better explanation? This page is open source.Edit on GitHub·Suggest an improvement