One read of Model Context Protocolmcp-20260814T095811Z
144 pages moved out of 144 read.
What this read moved
101-125 of 144, page 5 of 6This capture is too large to show at once. Changes 101-125 of 144 are below, significant first; the rest are on the following screens.
seps/2575-stateless-mcp First recorded · 841 lines, first recorded
# SEP-2575: Make MCP Stateless ## Abstract ## Motivation ### The Problem with Statefulness ## Design Principles ### Transport Consistency ## Specification ### Overview ### Protocol Version #### HTTP #### Per-request Version #### Unsupported Protocol Versions #### Version Negotiation Flow ### Discovery for Server Capabilities #### `server/discover` RPC ### Per-Request Client Capabilities #### Per-Request Metadata Schema #### Response Streaming #### Request Cancellation ##### Resumable Streams Are Removed #### Missing Required Capabilities ### `subscriptions/listen` RPC #### Request Schema #### Acknowledgment Notification #### Multiple Concurrent Subscriptions #### Stopping a Subscription #### Transport Behavior ### Deprecated and Removed RPCs ## Rationale ### Stateless-First by Default #### Alternative Considered: Optional Handshake #### Why it was rejected: ### Explicit Session Management ### Separation of Concerns #### Alternative Considered: A Monolithic Handshake #### Why it was rejected: ## Backward Compatibility ### Supporting Multiple Versions #### Client (supporting vPrev) → Server (vPrev, vPost) #### Client (supporting vPrev, vPost) → Server (vPrev) ## Security Implications ## Reference Implementation ## FAQ ### What is protocol level statelessness? ### Does this make MCP a fully stateless protocol? ### Why is it important for STDIO to be stateless as well? ### How does `server/discover` relate to the MCP Server Card? ## Open Questions ### What belongs in `_meta` vs. as a top-level protocol field? ### Should `clientInfo` be part of `ClientCapabilities`? ## Changes since SEP became Final
The first capture of this source. The page was already there, and this is what it said.
# SEP-2575: Make MCP Stateless
> Make MCP Stateless
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **SEP** | 2575 |
| **Title** | Make MCP Stateless |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-06-18 |
| **Author(s)** | Jonathan Hefner ([@jonathanhefner](https://github.com/jonathanhefner)), Mark Roth ([@markdroth](https://github.com/markdroth)), Shaun Smith ([@evalstate](https://github.com/evalstate)), Harvey Tuch ([@htuch](https://github.com/htuch)), Kurtis Van Gent ([@kurtisvg](https://github.com/kurtisvg)) |
| **Sponsor** | Kurtis Van Gent ([@kurtisvg](https://github.com/kurtisvg)) |
| **PR** | [#2575](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575) |
***
## Abstract
A truly stateless protocol, where every request is self-contained and can be
understood in isolation, is highly desirable for its inherent simplicity,
scalability, and reliability. The current Model Context Protocol (MCP) is not
stateless by default. The specification requires an initialization handshake
that establishes a session state between the client and server, which persists
for the duration of the connection.
This inherent statefulness makes it difficult to run MCP at scale. Placing an
MCP server behind a standard load balancer, for example, is challenging because
a client's session is coupled to the specific server instance holding its state.
This proposal outlines a series of changes to **enable stateless MCP as the
default**, embracing a "pay as you go" model for protocol complexity and state.
Under this model, we provide simple, stateless features by default and only
introduce the overhead of stateful, long-lived connections for cases where that
functionality is actually required.
Specifically, this SEP proposes removing the state-establishing initialization
handshake and replacing it with discrete, stateless alternatives. This initial
step allows each request to be processed independently, simplifying server-side
logic and paving the way for robust, scalable deployments.
## Motivation
The Model Context Protocol (MCP) specification currently mandates a stateful
initialization handshake. This design choice creates significant challenges for
scalability, reliability, and implementation simplicity. This SEP is motivated
by the need to address these shortcomings.
### The Problem with Statefulness
The core issue is that a server must retain session state from previous requests
to understand subsequent ones. This is in direct opposition to the design of
modern, cloud-native systems which favor stateless services for their resilience
and scalability.
1. **Impediment to Scalability:** The most critical issue is the difficulty of
load balancing stateful MCP. A simple stateless load balancer (e.g., L4/L7
round-robin) cannot be used, as it would route a client's requests to
different backend servers, none of which would have the correct session
state. Operators are forced to implement complex and fragile solutions like
sticky sessions, which bind a client to a specific server. This complicates
infrastructure, can lead to uneven load distribution, and makes horizontally
scaling the service non-trivial.
2. **Poor Resilience and Fault Tolerance:** In a stateful model, if the specific
server instance handling a client session fails, that session state is lost.
The client must detect the connection failure, re-establish a connection
(likely to a new server instance via the load balancer), and perform the
entire initialization handshake again. This process is disruptive and
inefficient, adding complexity around "resumability".
3. **Increased Implementation Complexity:** The current model imposes a
significant burden on developers.
* **Server-side:** Developers must implement logic to create, manage, and
eventually garbage-collect per-client session state. This is a common
source of bugs and memory leaks.
* **Client-side:** Developers must write complex code to manage a persistent
connection and handle the inevitable network failures and reconnections,
including the logic to resynchronize state after a disconnect.
## Design Principles
This proposal establishes a "pay as you go" model for protocol complexity,
guided by the following principles in order of preference:
1. **Prioritize Stateless-ness:** Whenever possible, a request must be
self-contained, providing all information the server needs to process it
without relying on state from previous requests.
2. **Prefer State References:** If a fully stateless exchange is not practical,
references to state should be passed in every request.
3. **Treat Statefulness as a Last Resort:** The complexity of stateful logic and
long-lived streaming connections should only be accepted when no simpler
alternative exists to solve a critical use case.
### Transport Consistency
It is critical that these stateless principles are applied consistently across
all transports. Keeping the `stdio` and `http` implementations in sync ensures a
**unified developer experience**, allowing the core protocol semantics to be
learned once and applied everywhere. This consistency simplifies the creation of
transport-agnostic libraries and tooling, and prevents protocol fragmentation
where different transports behave in fundamentally different ways. A single,
coherent protocol model is essential for a healthy ecosystem.
## Specification
### Overview
This specification fundamentally refactors the MCP interaction model to be
**stateless-first**. Currently, MCP requires a mandatory 3-way initialization
handshake before any resources can be exchanged. This handshake negotiates and
establishes several key pieces of information:
1. MCP Protocol Version
2. Server Capabilities and `serverInfo`
3. Client Capabilities and `clientInfo`
The requirement of this initialization handshake **enforces the establishment of
a state** that is expected to persist for subsequent communication between
client and server. Furthermore, by bundling these negotiations into a single
initialization phase, the specification creates an implied link between them,
particularly between the exchange of capabilities and a mandatory connection
lifecycle.
This proposal is to **remove the initialization handshake** and "unbundle" its
functions into discrete, stateless components. We will provide new, more clearly
defined mechanisms for clients and servers to exchange this information without
a mandatory state-creating cycle.
> **Note:** Session management (both transport-level and application-level) is
> addressed separately by [SEP-2322][SEP-2322] and [SEP-2567][SEP-2567]. This
> SEP focuses exclusively on removing the initialization handshake and providing
> stateless alternatives for version negotiation, discovery, and capabilities.
### Protocol Version
To make requests self-contained, metadata previously negotiated during the
handshake must now be included with **every request**.
#### HTTP
For the HTTP transport, protocol version MUST be passed as an **HTTP header**.
The header value MUST match the value provided in the request payload's `_meta`
field; otherwise the server MUST return a `400 Bad Request` (see
[SEP-2243][SEP-2243]).
* `MCP-Protocol-Version: 2025-06-18`
* **Purpose**: To inform the server which version of the MCP specification the
client is using for this specific request.
* **Requirement**: This header is **MANDATORY**. Servers should reject
requests with a missing or unsupported version.
* This header MUST match the value provided in the Request as specified below.
#### Per-request Version
The `protocol-version` MUST be embedded directly within the `_meta` field of the
request payload. For HTTP, this \_meta MUST match the associated HTTP header, or
else the server should return a 400 Bad Request.
The following diff illustrates the required changes to `RequestMetaObject`:
```ts theme={null}
export interface RequestMetaObject extends MetaObject {
progressToken?: ProgressToken;
+ /**
+ * The MCP Protocol Version being used for this request.
+ */
+ "io.modelcontextprotocol/protocolVersion": string;
// Additional per-request fields (clientInfo, clientCapabilities, logLevel)
// are introduced in the Per-Request Client Capabilities section below.
}
```
#### Unsupported Protocol Versions
If a server receives a request with a protocol version it does not implement
(whether the version is unknown to the server or is a known version the server
has chosen not to support, such as an experimental or draft version), it MUST
return a JSON-RPC error response. For HTTP, the response status code MUST be
`400 Bad Request`. The error MUST conform to the following structure:
```ts theme={null}
export const UNSUPPORTED_PROTOCOL_VERSION = -32022;
export interface UnsupportedProtocolVersionError extends Omit<
JSONRPCErrorResponse,
"error"
> {
error: Error & {
code: typeof UNSUPPORTED_PROTOCOL_VERSION;
data: {
/**
* An array of protocol version strings that the server supports.
*/
supported: string[];
/**
* The protocol version that was requested by the client.
*/
requested: string;
};
};
}
```
#### Version Negotiation Flow
Without an initialization handshake, version negotiation happens inline:
1. The client sends a request with its preferred protocol version in the
`MCP-Protocol-Version` header and `io.modelcontextprotocol/protocolVersion`
`_meta` field.
2. If the server supports that version, it processes the request normally.
3. If the server does not support the requested version, it returns an
`UnsupportedProtocolVersionError` containing its list of `supported`
versions.
4. The client selects a mutually supported version from the list and retries.
Alternatively, a client **MAY** call `server/discover` first to learn the
server's supported versions before sending any other requests.
### Discovery for Server Capabilities
To allow clients to adapt to different server implementations, this
specification introduces a **discovery RPC**. This provides a standard mechanism
for a server to advertise its supported protocol versions and capabilities.
Servers **MUST** implement `server/discover`. Clients **MAY** call it but are
not required to — a client is free to invoke any RPC without first calling the
discovery endpoint. If a client calls an unsupported RPC, the server **MUST**
return a `Method not found` JSON-RPC error (`-32601`). For HTTP, the response
status code MUST be `404 Not Found`.
#### `server/discover` RPC
* **Purpose**: To allow a client to query the server for its supported protocol
versions, capabilities, and other metadata.
**Request Schema:**
```ts theme={null}
export interface DiscoverRequest extends Request {
method: "server/discover";
params?: {};
}
```
**Response Schema:**
```ts theme={null}
export interface DiscoverResult extends Result {
/**
* A list of MCP Protocol Version strings that this server supports.
* The client should choose a version from this list for use in
* subsequent requests.
*/
supportedVersions: string[];
/**
* An object detailing the capabilities of the server.
*/
capabilities: ServerCapabilities;
/**
* Information about the server software implementation.
*/
serverInfo: Implementation;
/**
* Natural language instructions describing how to use the server and
* its features. This can be used by clients to improve an LLM's
* understanding of available tools (e.g., by including it in a system prompt).
*/
instructions?: string;
}
```
### Per-Request Client Capabilities
To complete the decoupling from the initial handshake, client capabilities are
no longer negotiated once at initialization. Instead, a client **MUST** specify
its capabilities on every request. This ensures the server is always fully
informed about what optional features the client can handle for that specific
transaction. An empty capabilities object means the client supports no optional
capabilities — servers **MUST NOT** infer capabilities from prior requests.
Cut at 300 lines. The page has the rest.
seps/2577-deprecate-roots-sampling-and-logging First recorded · 328 lines, first recorded
# SEP-2577: Deprecate Roots, Sampling, and Logging ## Abstract ## Motivation ### Roots ### Sampling ### Logging ## Specification ### Overview of changes ### Schema changes #### Deprecated capabilities #### Deprecated types — Roots #### Deprecated types — Sampling #### Deprecated types — Logging #### Annotation format #### Union types ### Documentation changes ### Capability negotiation ### Timeline ## Rationale ### Why deprecate rather than move to extensions? ### Why deprecate rather than remove immediately? ### Why these three features specifically? ## Backward Compatibility ## Security Implications ## Reference Implementation
The first capture of this source. The page was already there, and this is what it said.
# SEP-2577: Deprecate Roots, Sampling, and Logging
> Deprecate Roots, Sampling, and Logging
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ------------------------------------------------------------------------------- |
| **SEP** | 2577 |
| **Title** | Deprecate Roots, Sampling, and Logging |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2026-04-14 |
| **Author(s)** | Kurtis Van Gent ([@kurtisvg](https://github.com/kurtisvg)) |
| **Sponsor** | [@kurtisvg](https://github.com/kurtisvg) |
| **PR** | [#2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577) |
***
## Abstract
This SEP deprecates the following core protocol features:
* **Roots** (`roots/list`, `notifications/roots/list_changed`)
* **Sampling** (`sampling/createMessage`,
`ClientCapabilities.tasks.requests.sampling`)
* **Logging** (`logging/setLevel`, `notifications/message`)
These features are deprecated starting in the specification version that
includes this SEP (expected June 2026). They will continue to be fully
functional in all specification versions released within one year of that
version's release.
Each of those subsequent versions will in turn support the features for one year
after its own release, assuming the one-year-per-version support policy proposed
in a separate SEP. This provides implementations with an extended migration
window before the features are fully removed.
During the deprecation period, wire-level behavior is unchanged. No types are
removed, no capability negotiation changes, and no existing implementations
break. The deprecation serves as a signal to the ecosystem to stop building on
these features and to plan for their eventual removal.
## Motivation
The MCP specification aims to remain minimal and focused. Features that see low
adoption, overlap with existing alternatives, or impose disproportionate
implementation burden relative to their value are candidates for removal.
Keeping such features in the core specification increases the burden for every
client and server, slows protocol evolution, and makes the specification harder
to learn. The following three features meet these criteria.
Deprecating these features was proposed during a recent core contributor
meeting. This SEP formalizes that proposal with a concrete implementation plan.
See [discussion #2536][discussion-2536].
### Roots
Roots provides "informational guidance" about which directories or files a
server should operate on. In practice:
* **Low adoption**: Few clients implement roots support, and few servers rely on
it. The [feature support matrix][feature-matrix] shows limited client
coverage.
* **Vague semantics**: The specification describes roots as informational —
servers are not required to respect them, which reduces their utility.
* **Overlapping alternatives**: Working directory context can be provided
through tool parameters, resource URIs, server configuration, or environment
variables — all of which are more explicit.
### Sampling
Sampling allows servers to request LLM completions from the client. While
conceptually powerful, it has struggled with adoption:
* **Complex to implement**: Correct sampling implementation requires
human-in-the-loop approval, model selection logic, security considerations,
and (since SEP-1577) tool loop support. This complexity has contributed to low
client adoption.
* **Low adoption**: The [feature support matrix][feature-matrix] shows that few
clients support sampling, despite the feature being available since the
November 2024 specification.
* **Direct alternatives**: Servers that need LLM capabilities can integrate
directly with LLM provider APIs, giving them full control over model
selection, parameters, and streaming.
### Logging
Logging allows servers to send structured log messages to clients via the
protocol:
* **Overlapping infrastructure**: Standard logging mechanisms (stderr for stdio
transports, OpenTelemetry for structured observability) are mature, widely
adopted, and better suited to logging than an application-protocol channel.
* **Low value relative to complexity**: Adding log message types, severity
levels, and the `logging/setLevel` request to the core specification increases
the implementation surface for all clients and servers.
[discussion-2536]: https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/2536
[feature-matrix]: https://modelcontextprotocol.io/clients#feature-support-matrix
## Specification
### Overview of changes
1. Mark deprecated features with `@deprecated` annotations in the schema
2. Add deprecation notices to feature documentation pages
3. No wire-level protocol changes during the deprecation period
### Schema changes
Add `@deprecated` JSDoc annotations to the following items in
`schema/draft/schema.ts`. No types, interfaces, or union members are removed.
#### Deprecated capabilities
| Capability | Location |
| -------------------------------------------- | -------------------------------------- |
| `ClientCapabilities.roots` | Client capability for listing roots |
| `ClientCapabilities.sampling` | Client capability for LLM sampling |
| `ClientCapabilities.tasks.requests.sampling` | Task-augmented sampling sub-capability |
| `ServerCapabilities.logging` | Server capability for log messages |
#### Deprecated types — Roots
| Type | Description |
| ------------------------------ | ----------------------------------------- |
| `Root` | Represents a root directory or file |
| `ListRootsRequest` | Server-to-client request for `roots/list` |
| `ListRootsResult` | Result containing roots array |
| `ListRootsResultResponse` | JSON-RPC response wrapper |
| `RootsListChangedNotification` | Client notification when roots change |
#### Deprecated types — Sampling
| Type | Description |
| ----------------------------- | ---------------------------------------------- |
| `CreateMessageRequestParams` | Parameters for `sampling/createMessage` |
| `CreateMessageRequest` | Server-to-client request for sampling |
| `CreateMessageResult` | Result from a sampling request |
| `CreateMessageResultResponse` | JSON-RPC response wrapper |
| `SamplingMessage` | A message in a sampling conversation |
| `SamplingMessageContentBlock` | Content block union for sampling messages |
| `ToolChoice` | Controls model tool selection during sampling |
| `ToolUseContent` | Tool use content block in sampling messages |
| `ToolResultContent` | Tool result content block in sampling messages |
| `ModelPreferences` | Server preferences for model selection |
| `ModelHint` | Hints for model selection |
#### Deprecated types — Logging
| Type | Description |
| ---------------------------------- | --------------------------------------- |
| `LoggingLevel` | Syslog severity level enum |
| `SetLevelRequestParams` | Parameters for `logging/setLevel` |
| `SetLevelRequest` | Client-to-server request to set level |
| `SetLevelResultResponse` | JSON-RPC response wrapper |
| `LoggingMessageNotificationParams` | Parameters for log message notification |
| `LoggingMessageNotification` | Server-to-client log message |
#### Annotation format
Each deprecated item SHOULD receive a JSDoc `@deprecated` tag with a brief
explanation:
```typescript theme={null}
/**
* Present if the client supports listing roots.
*
* @deprecated Deprecated as of this specification version. Will be included
* in all versions released within one year, then may be removed.
*/
roots?: {
listChanged?: boolean;
};
```
#### Union types
The following union types reference deprecated types but MUST NOT be modified
during the deprecation period. They will be updated when the deprecated types
are removed:
* `ClientNotification` (includes `RootsListChangedNotification`)
* `ClientResult` (includes `CreateMessageResult`, `ListRootsResult`)
* `ServerRequest` (includes `CreateMessageRequest`, `ListRootsRequest`)
* `ServerNotification` (includes `LoggingMessageNotification`)
### Documentation changes
Add a deprecation warning block at the top of each feature's documentation page,
after the title:
**`docs/specification/draft/client/roots.mdx`:**
```mdx theme={null}
<Warning>
**Deprecated**: The Roots feature is deprecated as of this specification
version. It will remain fully functional in all specification versions released
within one year of the <YYYY-MM-DD> release. Each of those versions will
continue to support it for one year after its own release.
</Warning>
```
**`docs/specification/draft/client/sampling.mdx`:**
```mdx theme={null}
<Warning>
**Deprecated**: The Sampling feature is deprecated as of this specification
version. It will remain fully functional in all specification versions released
within one year of the <YYYY-MM-DD> release. Each of those versions will
continue to support it for one year after its own release.
</Warning>
```
**`docs/specification/draft/server/utilities/logging.mdx`:**
```mdx theme={null}
<Warning>
**Deprecated**: The Logging feature is deprecated as of this specification
version. It will remain fully functional in all specification versions released
within one year of the <YYYY-MM-DD> release. Each of those versions will
continue to support it for one year after its own release.
</Warning>
```
### Capability negotiation
During the deprecation period, capability negotiation is **unchanged**:
* Clients and servers that support deprecated features SHOULD continue to
declare the corresponding capabilities.
* Implementations that encounter deprecated capabilities MUST still handle them
correctly.
* Implementations SHOULD emit a warning (e.g., in logs or developer tooling)
when deprecated capabilities are negotiated.
* New implementations SHOULD NOT add support for deprecated features unless
needed for backward compatibility with existing counterparts.
### Timeline
* **Deprecated**: In the next specification release (currently planned for June
2026\).
* **Included in subsequent releases**: All specification versions released
within one year of this version's release MUST continue to include these
features as deprecated.
* **Per-version support**: Each version that includes these features will
support them for one year after that version's release, per the
one-year-per-version support policy proposed in a separate SEP.
* **Removal**: Specification versions released more than one year after this
version's release MAY remove these features entirely.
## Rationale
### Why deprecate rather than move to extensions?
These features are already implemented in many clients and servers. The
extensions mechanism (SEP-2133) specifies that unless an extension is provided,
implementations must behave as if the extension is not present. Retrofitting
this logic into existing SDKs — especially across multiple protocol versions —
would be complex and error-prone. Deprecation followed by removal is less
disruptive: implementations can continue using the features as-is during the
transition period, then simply stop when the features are removed.
### Why deprecate rather than remove immediately?
While adoption of these features is low, they are still in use. Removing them
immediately would cause unnecessary churn and disruption for users, client and
server owners, and SDK builders. A deprecation window minimizes this impact by
giving the ecosystem time to migrate at its own pace.
### Why these three features specifically?
These were identified during a core contributor meeting as the features with the
weakest adoption-to-complexity ratio. Each has viable alternatives outside the
protocol, and none are critical to the core resource/tool/prompt interaction
model that defines MCP. See [discussion #2536][discussion-2536].
## Backward Compatibility
During the deprecation period, there are **no backward compatibility issues**.
All deprecated features continue to work identically. No wire-level changes are
introduced.
Cut at 300 lines. The page has the rest.
seps/2596-spec-feature-lifecycle-and-deprecation First recorded · 423 lines, first recorded
# SEP-2596: Specification Feature Lifecycle and Deprecation Policy ## Abstract ## Motivation ## Specification ### Scope ### Feature states ### Deprecating a feature ### The deprecated registry ### Tier 1 SDK obligations ### Removing a feature ### Expedited removal ### Roles ### Transition ## Rationale ### Why a separate state model from specification revisions? ### Why a SEP to deprecate but not to remove? ### Why twelve months? ### Relationship to SEP-1400 (Semantic Versioning) ### Consensus ## Backward Compatibility ## Security Implications ## Reference Implementation ## Open Questions
The first capture of this source. The page was already there, and this is what it said.
# SEP-2596: Specification Feature Lifecycle and Deprecation Policy
> Specification Feature Lifecycle and Deprecation Policy
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Process
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ------------------------------------------------------------------------------- |
| **SEP** | 2596 |
| **Title** | Specification Feature Lifecycle and Deprecation Policy |
| **Status** | Final |
| **Type** | Process |
| **Created** | 2026-04-17 |
| **Author(s)** | Den Delimarsky ([@localden](https://github.com/localden)) |
| **Sponsor** | [@localden](https://github.com/localden) |
| **PR** | [#2596](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2596) |
***
## Abstract
This SEP defines a lifecycle for individual features within the Model Context Protocol
specification, separate from the revision lifecycle of the specification document itself. It
introduces three feature states (Active, Deprecated, Removed), the criteria and procedure for
moving between them, a minimum window between deprecation and removal, and the documentation
required at each transition. The goal is a predictable timeline that SDK authors and implementers
can plan migrations against when protocol surface area is retired.
## Motivation
The specification has already retired or signaled retirement of several features, but each case
has been handled ad hoc:
* The HTTP+SSE transport is described as "deprecated" in the
[Streamable HTTP backwards-compatibility guidance][transports-compat], with no stated removal
date.
* The `includeContext` values `"thisServer"` and `"allServers"` are labeled "soft-deprecated" in
[`sampling/createMessage`][sampling-includecontext] and in `schema.ts`, with the note that they
"may be removed in future spec releases."
* JSON-RPC batching was added in revision `2025-03-26` and removed in `2025-06-18`, a single
release later, with no deprecation period.
* Open proposals such as consolidating `Resource` and `ResourceTemplate` ([#1540][issue-1540]) and
deprecating roots, sampling, and logging ([SEP-2577][sep-2577]) would each retire existing
surface area but have no process to follow.
This inconsistency has costs. Implementers cannot tell whether "deprecated" and "soft-deprecated"
mean different things, or how long either state lasts before removal. Community questions such as
[discussion #2177][disc-2177] (asking when the SSE transport will actually be removed) have no
policy to point to. At the [NYC maintainer meeting][nyc-2026-03-31], large implementers described
indefinite support for past protocol versions as "corrosive tech debt." The [Stability over
velocity][design-principles] design principle observes that "removing from \[the spec] is nearly
impossible" but offers no path for the cases where removal is warranted.
The Core Maintainers agreed at the [April 1, 2026 meeting][cm-2026-04-01] that MCP needs "a formal
versioning status and a defined deprecation cycle" with "direction agreed, mechanics TBD." This SEP
proposes those mechanics.
## Specification
### Scope
This policy governs **features** of the MCP core specification: protocol messages, capabilities,
transports, schema types, and normative behavioral requirements. It does not govern the
independent lifecycle of SDK-specific APIs, registry policies, or the revision lifecycle of the
specification document itself (Draft, Current, Final), which is defined in the [versioning
guide][versioning].
Note that "Final" is used in two senses in this document: a specification *revision* is Final when
superseded by a later one (per the versioning guide), and a *SEP* reaches Final when its status
advances per the [SEP guidelines][sep-guidelines]. Context disambiguates; where it does not, this
document writes "the SEP reaches Final" or "Final revision" explicitly.
### Feature states
A specification feature is in exactly one of three states:
| State | Meaning | Implementer expectation |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Active** | The feature is part of the Current specification revision with no planned removal. | Implement per the feature's normative requirements. |
| **Deprecated** | The feature remains in the specification but is scheduled for removal. A migration path is documented (see below). | New implementations SHOULD NOT adopt the feature. Existing implementations SHOULD migrate before the earliest removal date. |
| **Removed** | The feature has been deleted from `draft` and will be absent from the next Current revision. It remains documented in the Final revision it last appeared in. | Implementations targeting that next Current revision MUST NOT depend on the feature. |
The term "soft-deprecated" is retired. Existing uses in the specification are reclassified as
Deprecated under this policy (see [Transition](#transition)).
Removal from the specification does not oblige an SDK to drop the feature from releases that
continue to support an earlier revision in which it was Active or Deprecated; that timeline is
governed by the SDK's own revision-support policy (see [Open Questions](#open-questions)).
A Deprecated feature MAY be restored to Active by a SEP that supersedes the deprecation SEP and
documents the changed circumstances. Restoration follows the same approval path as deprecation. If
the feature is later deprecated again, the minimum deprecation window in [Deprecating a
feature](#deprecating-a-feature) is measured afresh from the revision in which the new deprecation
takes effect.
### Deprecating a feature
A feature MAY be proposed for deprecation when at least one of the following holds:
* It has been superseded by another feature that covers the same use cases.
* It presents a security, privacy, or interoperability risk that cannot be mitigated in place.
* Ecosystem telemetry or SDK maintainer consensus indicates negligible adoption relative to its
maintenance cost.
Deprecation is a specification change and therefore requires a SEP per the [SEP
guidelines][sep-guidelines]. The deprecation SEP MUST:
1. Identify the feature by name and link to its definition in `schema.ts` (where applicable) and
the specification prose.
2. State the rationale against the criteria above.
3. Document the migration path, or state explicitly that none is required. If the migration path
names a replacement feature, that feature MUST be Active in the revision in which the
deprecation takes effect; the replacement and the deprecation MAY land in the same revision. A
feature is not deprecated under this policy while its documented replacement is still only in
`draft`.
4. Specify the **minimum deprecation window**: the number of months, at least twelve, that the
feature MUST remain Deprecated before it is eligible for removal. The window is measured from
the release of the specification revision in which the feature is first marked Deprecated, not
from the date the SEP reaches Final. The feature becomes eligible for removal in the first
specification revision released as Current on or after the window elapses; that point is the
feature's **earliest removal**.
When the deprecation SEP reaches Final the deprecation is scheduled: the following changes land in
the draft specification (`schema/draft/` and `docs/specification/draft/`). The feature becomes
Deprecated when the revision carrying these changes is released as Current under the [versioning
guide][versioning], and the minimum deprecation window is counted from that release. Anchoring the
clock to the revision release means every feature deprecated in the same revision shares one
earliest removal rather than each carrying a date derived from when its own SEP happened to land.
* The feature's entry in `schema.ts` gains a `@deprecated` JSDoc tag referencing the deprecation
SEP and the revision in which the deprecation takes effect.
* The specification prose for the feature gains a deprecation notice with the same information.
* The `changelog.mdx` for that revision gains an entry under a "Deprecated" heading. This SEP
introduces "Deprecated" and "Removed" as standing changelog headings alongside the existing
Major/Minor/Other groupings.
* The feature is added to the [deprecated registry](#the-deprecated-registry) with its deprecation
SEP, the revision in which it became Deprecated, its migration path, and its earliest removal.
### The deprecated registry
`docs/specification/draft/deprecated.mdx` is a single page listing every feature currently in the
Deprecated state. It is the canonical answer to "what is on its way out, and by when," so that an
implementer does not have to reconstruct that picture from deprecation entries spread across
revision changelogs. Each row records the feature, its deprecation SEP, the revision in which it
became Deprecated, the documented migration path, and its earliest removal. A deprecation adds a
row; a removal moves the row to a Removed section of the same page with a link to the changelog
entry, so the page also serves as the historical record. The registry carries no normative force
of its own; it is a derived view kept consistent with the per-feature notices and changelog
entries, which are the normative records.
### Tier 1 SDK obligations
A feature lifecycle is only as effective as the implementations that surface it to consumers. The
specification artifacts above record that a feature is Deprecated; Tier 1 SDKs (per
[SEP-1730][sep-1730]) deliver that record to the implementers who would otherwise discover the
removal by breakage. Once the revision in which a feature becomes Deprecated is released as
Current, Tier 1 SDKs:
* MUST mark the corresponding API surface deprecated using the language's native mechanism (for
example `@Deprecated` in Java, `[Obsolete]` in .NET, `@deprecated` JSDoc in TypeScript, the
`Deprecated:` doc convention in Go) in their next release, referencing the deprecation SEP and
the earliest removal date where the mechanism permits. The marker applies to the SDK API surface
and is not conditioned on the specification revision a consumer targets; surfacing it to
consumers still on an earlier revision is intentional forward signal.
* SHOULD emit a runtime warning when a deprecated feature is exercised, using the language's
idiomatic mechanism (for example Python's `DeprecationWarning`, Node.js's
`process.emitWarning`, or a configurable logger). A runtime warning reaches developers who never
read API documentation and is an observable signal a conformance test can assert against.
These obligations are conformance criteria for Tier 1 status. A Tier 1 SDK that persistently fails
to surface a Deprecated feature is subject to the [Tier Relegation Process][sep-1730-relegation]
in [SEP-1730][sep-1730].
### Removing a feature
1. Once a feature is set for removal, the removal is executed at the discretion of the Core
Maintainers after the minimum deprecation window has elapsed, during release preparation,
under the [governance decision process][governance-decisions]. Removal does not require its
own SEP. Before removing a feature the Core Maintainers MUST confirm that the migration target
named in the deprecation SEP, if any, is still Active.
2. A SEP is required for any other change to a deprecation or removal, for example extending or
shortening the timeline ([Expedited removal](#expedited-removal)) or restoring the feature to
Active ([Feature states](#feature-states)).
Note that features may remain Deprecated, without removal, for much longer than the minimum
deprecation window.
SDKs implement deprecation as part of the [SDK Tiering System][sep-1730] (see [Tier 1 SDK
obligations](#tier-1-sdk-obligations)); removal imposes no additional requirements on SDK
maintainers.
When a removal decision is taken, the feature is deleted from `schema/draft/schema.ts` (where
present) and the draft specification prose; `changelog.mdx` for that revision gains an entry under
the "Removed" heading that links to the deprecation SEP and the last Final revision in which the
feature was present; and the feature's [registry](#the-deprecated-registry) row moves to the
Removed section with a link to that changelog entry.
### Expedited removal
The twelve-month floor MAY be shortened when the feature presents an active security risk, meaning
a vulnerability with a published security advisory or documented in-the-wild exploitation for which
no in-place mitigation exists. Shortening the window requires Core Maintainer approval under the
[governance decision process][governance-decisions], recorded in the deprecation SEP or, where the
risk surfaces after that SEP is already Final, in a short expedited-removal SEP that references it.
The shortened window MUST still provide at least ninety days between the feature becoming
Deprecated and its earliest removal.
### Roles
| Action | Who |
| ---------------------------------------------- | ----------------------------------------------------------------------------- |
| Propose deprecation, extension, or restoration | Any contributor, per the SEP process |
| Sponsor | A Maintainer or Core Maintainer, per the SEP process |
| Approve a deprecation SEP | Core Maintainers, per the [governance decision process][governance-decisions] |
| Decide a removal during release preparation | Core Maintainers, per the [governance decision process][governance-decisions] |
| Approve an extension or restoration SEP | Core Maintainers, per the [governance decision process][governance-decisions] |
| Approve expedited removal | Core Maintainers, per the [governance decision process][governance-decisions] |
As with all Core Maintainer decisions, Lead Maintainers retain veto authority over each of the
approvals above, per the [governance roles][governance-roles] definition.
[governance-roles]: https://modelcontextprotocol.io/community/governance#roles
### Transition
Two features were already described as deprecated in the specification before this policy existed
(see [Motivation](#motivation)). When this SEP reaches Final they are classified as Deprecated and
seeded into the [registry](#the-deprecated-registry); the deprecation-SEP requirements in
[Deprecating a feature](#deprecating-a-feature) are not applied retroactively. The deprecation
decision in each case predates this policy; this section records it under the new vocabulary so the
terms "deprecated" and "soft-deprecated" carry a single defined meaning going forward.
Both features were publicly deprecated well over twelve months before this SEP, so the minimum
deprecation window has in practice already been served; re-anchoring their clock to a future
revision release would restart a window the ecosystem has already had. Each is therefore given a
three-month grace period from the date this SEP reaches Final before it is eligible for removal,
matching the floor the [Expedited removal](#expedited-removal) clause sets for the shortest
permissible window. Removal still follows [Removing a feature](#removing-a-feature): a Core
Maintainer decision at release preparation, not an automatic event when the grace period ends.
| Feature | Migration target | Earliest removal |
| ----------------------------------------------- | ------------------------------------ | --------------------------------------- |
| HTTP+SSE transport | [Streamable HTTP][transports-compat] | Three months after this SEP is Final |
| `includeContext: "thisServer"` / `"allServers"` | Omit the field or use `"none"` | Follows Sampling ([SEP-2577][sep-2577]) |
`includeContext` is a parameter of `sampling/createMessage`. [SEP-2577][sep-2577] deprecates the
Sampling feature as a whole; the two affected `includeContext` values follow that feature's
deprecation schedule rather than carrying an independent removal clock, and are removed no later
than Sampling itself.
This grandfathering applies only to features the specification already described as deprecated on
the date this SEP reaches Final. Every subsequent deprecation follows [Deprecating a
feature](#deprecating-a-feature) in full, and removal of the grandfathered features follows
[Removing a feature](#removing-a-feature) without exception.
When this SEP reaches Final the following land in `draft/` directly, with no separate
implementation gate: the [versioning guide][versioning] is updated to reference this policy;
`deprecated.mdx` is created seeded with the two features above; the "Deprecated" heading is added
to `changelog.mdx` with both entries; and each feature gains the `@deprecated` schema annotation
and prose notice described in [Deprecating a feature](#deprecating-a-feature). For
`includeContext` the annotation is on the property as a whole, since per-value `@deprecated` tags
are not expressible on a string-literal union; the HTTP+SSE transport has no `schema.ts` types and
is annotated in the transport prose only.
## Rationale
### Why a separate state model from specification revisions?
The [versioning guide][versioning] already defines Draft, Current, and Final for specification
*revisions*. Those states describe the editorial maturity of a whole document and say nothing about
whether a given message or field within a Current revision is on its way out. The [Kubernetes
deprecation policy][k8s-deprecation], the [Node.js deprecation cycle][nodejs-deprecation], and IETF
practice such as [RFC 8996][rfc-8996] (which deprecates TLS 1.0 and 1.1 within the TLS protocol
family) all maintain feature-level deprecation rules alongside their release versioning for this
reason.
### Why a SEP to deprecate but not to remove?
The deliberation that needs community review is the decision to retire a feature and the choice of
migration path; that is what the deprecation SEP carries. Once it reaches Final the project has
committed to removal and fixed the earliest date, so carrying out that decision on schedule adds no
new judgment and a second SEP for it is process for its own sake. The deliberate maintainer
decision still exists as the release-preparation removal decision and its confirmations in
[Removing a feature](#removing-a-feature), mirroring the tier advancement procedure in
Cut at 300 lines. The page has the rest.
seps/2663-tasks-extension First recorded · 987 lines, first recorded
# SEP-2663: Tasks Extension ## Abstract ## Motivation ## Specification ### Extension Identifier ### Capability Negotiation ### Supported Methods ### Polymorphic Results ### Tasks #### Task Status ### Task Creation ### Task Polling #### Request #### Response ### Task Update Requests #### Request #### Response ### Task Cancellation #### Request #### Response ### Task Status Notifications ### Streamable HTTP: Routing Headers ### Example Message Flow ### Error Handling #### Protocol Errors #### Task Execution Errors ### Reservations ## Rationale ### Unsolicited Tasks vs. Immediate Results ### Splitting Reads (`tasks/get`) and Writes (`tasks/update`) ### Task Creation Consistency ### Ack-only Cancellation ### Composition with Multi Round-Trip Requests ## Backward Compatibility ## Security Implications ## Reference Implementation
The first capture of this source. The page was already there, and this is what it said.
# SEP-2663: Tasks Extension
> Tasks Extension
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Extensions Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **SEP** | 2663 |
| **Title** | Tasks Extension |
| **Status** | Final |
| **Type** | Extensions Track |
| **Created** | 2026-04-27 |
| **Author(s)** | Luca Chang ([@LucaButBoring](https://github.com/LucaButBoring)), Caitie McCaffrey ([@CaitieM20](https://github.com/CaitieM20)); on behalf of the Agents Working Group |
| **Sponsor** | Caitie McCaffrey ([@CaitieM20](https://github.com/CaitieM20)) |
| **PR** | [#2663](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2663) |
***
## Abstract
This SEP defines an extension that allows a server to respond to a `tools/call` request with an asynchronous *task handle* instead of a final result, allowing the client to retrieve the eventual result by polling. The extension introduces three methods: `tasks/get`, `tasks/update`, and `tasks/cancel`; a polymorphic-result discriminator (`resultType: "task"`); and a `Task` shape that carries a task status, in-progress server-to-client requests, and a final result or error. Task creation is server-directed: the client signals support by including the extension in its per-request capabilities, and the server decides on a per-request basis whether to materialize a task.
Tasks will become a foundational building block of MCP and are expected to be supported in future protocol versions. The experimental `tasks` feature in the `2025-11-25` specification served as a stopgap until the protocol's extension mechanism was available. Now that [extensions](https://modelcontextprotocol.io/extensions/overview) have been [formalized](./2133-extensions.md), moving tasks to an official extension gives the feature time to incubate and evolve based on additional real-world implementation feedback, without being constrained by the core specification's release cadence. Once the extension has stabilized and achieved broad adoption, it is intended to be promoted into the core protocol.
This proposal *removes* the version of [tasks](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks) specified in the `2025-11-25` release from the core protocol and moves it to an Extension. It also proposes updates to Tasks shaped by implementation feedback since that release, and by several changes to the base protocol included in the `2026-06-30` specification:
* [SEP-2260: Require Server requests to be associated with a Client request](./2260-Require-Server-requests-to-be-associated-with-Client-requests.md)
* [SEP-2322: Multi Round-Trip Requests](./2322-MRTR.md)
* [SEP-2243: HTTP Header Standardization for Streamable HTTP Transport](./2243-http-standardization.md)
* [SEP-2567: Sessionless MCP via Explicit State Handles](./2567-sessionless-mcp.md)
* [SEP-2575: Make MCP Stateless](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575)
## Motivation
The experimental [tasks](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks) feature served as an alternate execution mode for tool calls, elicitation, and sampling, allowing receivers to return a poll handle instead of blocking until a final result was ready. Implementation experience surfaced several challenges:
1. **The handshake is fragile.** Tasks today expose method-level capabilities (`tasks.requests.tools.call` declares that `tools/call` **MAY** be task-augmented) alongside a tool-level `execution.taskSupport` field that declares whether a particular tool will accept the augmentation. Clients express their own support for tasks by passing a `task` parameter on their requests, but **MUST NOT** include it if the method/tool does not support tasks. A client that wants to opt into tasks must therefore prime its state with a `tools/list` call before issuing any task-augmented request, and cannot blindly attach a `task` parameter to every request to handle tools isomorphically. This is confusing, implicit, and easy to get wrong.
2. **`tasks/result` is a blocking trap.** In the current flow, a client that observes `input_required` is required to call `tasks/result` prematurely so that the server has an SSE stream on which to side-channel elicitation or sampling requests. `tasks/result` then blocks until the entire operation completes. This forces long-lived persistent connections that many clients and servers do not want to implement, and it conflicts with [SEP-2260](./2260-Require-Server-requests-to-be-associated-with-Client-requests.md), which disallows unsolicited server-to-client requests outright. Under SEP-2260, the SSE semantics that justified the blocking behavior no longer apply.
3. **`tasks/list` scoping cannot be defined.** To avoid clients cancelling or retrieving results for tasks they shouldn't have access to, all tasks should be bound to some sort of "authorization context," the implementation of which is left to individual servers according to their existing bespoke permission models. However, in many cases, it is not possible to perform this binding, in which case the task ID becomes the only line of defense against contamination. In this scenario, it is unsafe for a server to support `tasks/list` at all. While it was possible for tasks to instead be bound to a session, [SEP-2567](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2567) removes sessions from the protocol. There is no other natural scope a server can define unilaterally — task IDs can be unguessable handles that a server can recognize one at a time, but servers cannot reliably correlate two unrelated handles to the same caller without additional state.
Beyond implementation challenges, tasks face another structural issue: **Client-hosted tasks are no longer expressible.** [SEP-1686](./1686-tasks.md) permitted clients to host tasks for elicitation and sampling, in part to avoid coupling tasks to tool calls. [SEP-2260](./2260-Require-Server-requests-to-be-associated-with-Client-requests.md) makes any unsolicited server-to-client request invalid; every server-to-client polling request under client-hosted tasks would be unsolicited by definition.
This proposal intends to solve the above issues by redesigning certain aspects of the feature and moving tasks out to an official extension. Redefining tasks as an official extension gives the feature more time to incubate and evolve independently of the core specification, promoting adoption. As part of the redesign, this proposal consolidates the polling lifecycle into `tasks/get` and a new `tasks/update` to remove the blocking `tasks/result` method. The redesign allows servers to return tasks unsolicited (in response to ordinary, non-`task`-flagged requests) to eliminate the per-request opt-in and the `tools/list` warmup, relying instead on the extension capability as the single handshake point. Finally, this proposal removes client-hosted elicitation and sampling tasks in compliance with [SEP-2260](./2260-Require-Server-requests-to-be-associated-with-Client-requests.md).
## Specification
The MCP Tasks extension allows certain requests to be augmented with **tasks**. Tasks are durable state machines that carry information about the underlying execution state of the request they augment, and are intended for client polling and deferred result retrieval. Each task is uniquely identifiable by a server-generated **task ID**.
Tasks are useful for representing expensive computations and batch processing requests, and map naturally onto external job APIs.
### Extension Identifier
This extension is identified as: `io.modelcontextprotocol/tasks`.
### Capability Negotiation
The client and server declare support for the tasks extension in their respective capabilities objects (using updated form from [SEP-2575: Make MCP Stateless](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575)):
```jsonc theme={null}
// Client to server, in per-request capabilities
{
// Other request parameters...
"params": {
"_meta": {
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {},
},
},
},
},
}
```
```jsonc theme={null}
// Server to client, in response to server/discover
{
"result": {
// Other response parameters...
"capabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {},
},
},
},
}
```
No extension-specific settings are currently defined; an empty object indicates support.
A server that has negotiated this extension **MAY** return `CreateTaskResult` in lieu of a standard result (e.g. `CallToolResult`) in response to any supported request at its own discretion and on a per-request basis. The server is the sole decider; clients do not signal task preference on the request itself. The client declaring the extension capability does not suggest that it requires a `CreateTaskResult` in response to that request.
A server **MUST NOT** return `CreateTaskResult` to a client that did not include the extension capability on its request, regardless of prior declarations. A client that has negotiated this extension **MUST** be prepared to handle either `CallToolResult` or `CreateTaskResult` in response to any supported request it issues. A client that receives `CreateTaskResult` in response to an unsupported request type **MUST** interpret this as an invalid response to the request.
If a server is unable to service a request to a client that does not declare this extension capability without returning `CreateTaskResult`, the server **MUST** return an error with the code `-32021` (Missing Required Client Capability), indicating the required extension in the error response:
```jsonl theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
// MISSING_REQUIRED_CLIENT_CAPABILITY
"code": -32021,
// Message provided for example purposes only. The content of this example message is non-normative.
"message": "Missing required client capability",
"data": {
"requiredCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
}
}
```
### Supported Methods
The following methods currently support task-augmented execution:
* `tools/call`
This specification may be extended to support tasks over other request types in the future; implementations **SHOULD** be designed to accommodate additional request types in future revisions of this specification.
### Polymorphic Results
A request that is eligible for task-augmentation may return one of two distinct result shapes — the request's standard result, or a `CreateTaskResult`. The discriminator is the `resultType` field on the result object, introduced by [SEP-2322](./2322-MRTR.md):
```typescript theme={null}
// "task" is introduced by this extension.
type ResultType = "complete" | "input_required" | "task" | string;
```
Servers **MUST** set `resultType` to `"task"` when returning a `CreateTaskResult` so that clients can distinguish it from a standard result. Servers **MUST NOT** set `resultType` to `"task"` on result types other than `CreateTaskResult`.
Client implementors are advised that existing code returning a fixed shape (e.g., a `tools/call` method returning `CallToolResult`) need not change their public contract — they can transparently drive the polling flow internally and surface only the final, completed result. New implementation surfaces **MAY** expose the task lifecycle directly for applications able to leverage it.
### Tasks
A `Task` carries operational metadata about ongoing work.
```typescript theme={null}
interface Task {
/** Stable identifier for this task. */
taskId: string;
/** Current task status. */
status: "working" | "input_required" | "completed" | "cancelled" | "failed";
/**
* Optional message describing the current task state.
* This can provide context for any status, for example (non-normative):
* - Progress descriptions for "working"
* - Work blocked on "input_required"
* - Reasons for "cancelled" status
* - Summaries for "completed" status
* - Additional information for "failed" status (e.g., error details, what went wrong)
*
* This MAY be exposed to the end-user or model.
*/
statusMessage?: string;
/** ISO 8601 timestamp when the task was created. */
createdAt: string;
/** ISO 8601 timestamp when the task was last updated. */
lastUpdatedAt: string;
/**
* Time-to-live duration from creation in integer milliseconds, null for unlimited.
* The server may discard the task after the TTL elapses. This value MAY change
* over the lifetime of a task.
*/
ttlMs: number | null;
/**
* Suggested polling interval in integer milliseconds. Clients SHOULD honor
* this value to avoid overwhelming the server. This value MAY change over
* the lifetime of a task.
*/
pollIntervalMs?: number;
}
```
#### Task Status
Tasks can be in one of the following states:
* `working`: The request is currently being processed.
* `input_required`: The server needs input from the client before the task can proceed. The `tasks/get` response will include outstanding requests in the `inputRequests` field. The client **MUST** inspect this field and **SHOULD** provide responses via the `inputResponses` field in subsequent `tasks/update` requests.
* `completed`: The request completed successfully and results are available in the `result` field. This includes tool calls that returned results with `isError: true`.
* `failed`: The request failed due to a JSON-RPC error during execution. The task will include the `error` field with the JSON-RPC error details. This status **MUST NOT** be used for non-JSON-RPC errors.
* `cancelled`: The request was cancelled before completion.
Derived shapes of `Task` inline status-specific payload fields and are used by `tasks/get` responses and `notifications/tasks` notifications:
```ts theme={null}
/**
* A task that is in a normal working state.
* Used by tasks/get and notifications/tasks.
*/
export interface WorkingTask extends Task {
status: "working";
}
/**
* A task that is waiting for input from the client.
* Used by tasks/get and notifications/tasks.
*/
export interface InputRequiredTask extends Task {
status: "input_required";
/**
* Server-to-client requests that need to be fulfilled during task execution.
* Keys are arbitrary identifiers for matching requests to responses.
*/
inputRequests: InputRequests;
}
/**
* A task that has completed successfully.
* Used by tasks/get and notifications/tasks.
*/
export interface CompletedTask extends Task {
status: "completed";
/**
* The final result of the task.
* The structure matches the result type of the original request.
* For example, a CallToolRequest task would return the CallToolResult structure.
*/
result: JSONObject;
}
/**
* A task that has failed due to a JSON-RPC error.
* Used by tasks/get and notifications/tasks.
*/
export interface FailedTask extends Task {
status: "failed";
/**
* The JSON-RPC error that caused the task to fail.
*/
error: JSONObject;
}
/**
* A task that has been cancelled.
* Used by tasks/get and notifications/tasks.
*/
export interface CancelledTask extends Task {
status: "cancelled";
}
/**
* A union type representing a task with optional inlined result/error/inputRequests fields.
* This type is used by tasks/get and notifications/tasks to provide complete task state
* including terminal results or pending input requests.
*/
export type DetailedTask =
WorkingTask | InputRequiredTask | CompletedTask | FailedTask | CancelledTask;
```
### Task Creation
A server returns `CreateTaskResult` in lieu of the standard result shape for a request to indicate that request will be processed asynchronously.
```typescript theme={null}
// resultType: "task"
type CreateTaskResult = Result & Task;
```
**Example Request (CallToolRequest):**
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "New York"
Cut at 300 lines. The page has the rest.
seps/414-request-meta First recorded · 122 lines, first recorded
# SEP-414: Document OpenTelemetry Trace Context Propagation Conventions ## Abstract ## Specification ### Non-normative example ## Rationale ### Why document this? ### Related SEPs ## Backward Compatibility ## Security Implications ## Reference Implementation
The first capture of this source. The page was already there, and this is what it said.
# SEP-414: Document OpenTelemetry Trace Context Propagation Conventions
> Document OpenTelemetry Trace Context Propagation Conventions
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------- |
| **SEP** | 414 |
| **Title** | Document OpenTelemetry Trace Context Propagation Conventions |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-04-25 |
| **Author(s)** | Adrian Cole ([@codefromthecrypt](https://github.com/codefromthecrypt)) |
| **Sponsor** | Marcelo Trylesinski ([@Kludex](https://github.com/Kludex)) |
| **PR** | [#414](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/414) |
***
## Abstract
This SEP documents conventions for OpenTelemetry (OTel) trace context propagation in MCP.
[OTel semantic conventions for MCP](https://github.com/open-telemetry/semantic-conventions/blob/e126ea9105b15912ccd80deab98929025189b696/docs/gen-ai/mcp.md#context-propagation)
specify using `_meta` as the carrier for W3C Trace Context keys. This is already in practice in the
C# SDK and other implementations.
This specification documents an exception to the DNS prefixing convention for keys in `_meta`.
This enables interoperability across existing and new implementations and serves as a foundation
for related SEPs (such as [SEP-2028](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2028)).
## Specification
This SEP adds documentation to the MCP specification, noting:
1. When OTel trace context is propagated via `_meta`, the keys `traceparent`, `tracestate`, and
`baggage` follow [W3C Trace Context](https://www.w3.org/TR/trace-context/) and
[W3C Baggage](https://www.w3.org/TR/baggage/) value formats.
2. A non-normative example showing trace context in `_meta`.
3. A note clarifying why this an exception to DNS prefixing keys in `_meta`: to remain
compatible with existing implementations and the OpenTelemetry semantic conventions.
See [agentclientprotocol/agent-client-protocol#297](https://github.com/agentclientprotocol/agent-client-protocol/pull/297)
for equivalent documentation changes in ACP.
### Non-normative example
```json theme={null}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "New York"
},
"_meta": {
"traceparent": "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
}
}
}
```
## Rationale
### Why document this?
This is currently documented elsewhere, but not as an MCP specification. Doing so ensures that
SEPs depending on this pattern can complete, as well as other SDKs in and outside the MCP org
can as well, such as [Logfire](https://github.com/pydantic/logfire/blob/09232402fd7e268c667db59d1e9f890ed30f7850/logfire/_internal/integrations/mcp.py#L149-L162) and [ToolHive](https://github.com/stacklok/toolhive/issues/3399).
If we don't document this shared concern, differing interpretations could materialize, such
as namespacing traceparent like `io.modelcontextprotocol.traceparent`, which will break traces
and log correlation.
### Related SEPs
* [SEP-1788](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1788) - reserved
keys in `_meta`; should be updated with `traceparent`, `tracestate`, and `baggage` when this
SEP is implemented
* [SEP-2028](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2028) - builds on
this SEP for forwarding `_meta` values to HTTP headers
## Backward Compatibility
This SEP documents existing conventions and is backward compatible.
## Security Implications
Trace context in `_meta` may include correlation IDs. Implementations should follow existing
data-handling guidance appropriate to their environment.
## Reference Implementation
Existing implementations using this pattern:
* [C# SDK instrumentation](https://github.com/modelcontextprotocol/csharp-sdk/blob/main/src/ModelContextProtocol.Core/Diagnostics.cs)
* [Python SDK instrumentation](https://github.com/modelcontextprotocol/python-sdk/pull/1693)
* [OpenInference MCP instrumentation (Python)](https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-mcp)
* [OpenInference MCP instrumentation (TypeScript)](https://github.com/Arize-ai/openinference/tree/main/js/packages/openinference-instrumentation-mcp)
* [Envoy AI Gateway](https://github.com/envoyproxy/ai-gateway/blob/6331b54aef81dd6c8d3d184acc4e2cb8167cea2a/internal/tracing/tracingapi/mcp.go)
* [Logfire](https://github.com/pydantic/logfire/blob/09232402fd7e268c667db59d1e9f890ed30f7850/logfire/_internal/integrations/mcp.py#L149-L162)
* [ToolHive](https://github.com/stacklok/toolhive/issues/3399)
seps/932-model-context-protocol-governance First recorded · 126 lines, first recorded
# SEP-932: Model Context Protocol Governance ## Abstract ## Motivation ## Rationale ### Hierarchical Structure ### Individual vs Corporate Membership ### SEP Process ## Specification ### Governance Structure #### Contributors #### Maintainers #### Core Maintainers #### Lead Maintainers ## Backwards Compatibility ## Reference Implementation ## Security Implications
The first capture of this source. The page was already there, and this is what it said.
# SEP-932: Model Context Protocol Governance
> Model Context Protocol Governance
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Process
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------- |
| **SEP** | 932 |
| **Title** | Model Context Protocol Governance |
| **Status** | Final |
| **Type** | Process |
| **Created** | 2025-07-08 |
| **Author(s)** | David Soria Parra |
| **Sponsor** | None |
| **PR** | [#931](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/931) |
***
## Abstract
This SEP establishes the formal governance model for the Model Context Protocol (MCP) project. It defines the organizational structure, decision-making processes, and contribution guidelines necessary for transparent and effective project stewardship. The proposal introduces a hierarchical governance structure with clear roles and responsibilities, along with the Specification Enhancement Proposal (SEP) process for managing protocol changes.
## Motivation
As the Model Context Protocol grows in adoption and complexity, the need for formal governance becomes critical. The current informal decision-making process lacks:
1. **Transparency**: Community members have no clear visibility into how decisions are made
2. **Participation Pathways**: Contributors lack defined ways to influence project direction
3. **Accountability**: No formal structure exists for resolving disputes or contentious issues
4. **Scalability**: Ad-hoc processes cannot scale with growing community and technical complexity
Without formal governance, the project risks:
* Fragmentation of the ecosystem
* Unclear or inconsistent technical decisions
* Reduced community trust and participation
* Inability to effectively manage contributions at scale
## Rationale
The proposed governance model draws inspiration from successful open source projects like Python, PyTorch, and Rust. Key design decisions include:
### Hierarchical Structure
We chose a hierarchical model (Contributors → Maintainers → Core Maintainers → Lead Maintainers) that is effectively how the project decisions are made today. From there we will continue to evolve governance in the best interest of the project.
### Individual vs Corporate Membership
Membership is explicitly tied to individuals rather than companies to:
* Ensure decisions prioritize protocol integrity over corporate interests
* Prevent capture by any single organization
* Maintain continuity when individuals change employers
### SEP Process
The Specification Enhancement Proposal process ensures:
* All protocol changes undergo thorough review
* Community input is systematically collected
* Design decisions are documented for posterity
* Implementation precedes finalization
## Specification
### Governance Structure
#### Contributors
* Any individual who files issues, submits pull requests, or participates in discussions
* No formal membership or approval required
#### Maintainers
* Responsible for specific components (SDKs, documentation, etc.)
* Appointed by Core Maintainers
* Have write/admin access to their repositories
* May establish component-specific processes
#### Core Maintainers
* Deep understanding of MCP specification required
* Responsible for protocol evolution and project direction
* Meet bi-weekly for decisions
* Can veto maintainer decisions by majority vote
* Current members listed in governance documentation
#### Lead Maintainers
* Justin Spahr-Summers and David Soria Parra
* Can veto any decision
* Appoint/remove Core Maintainers
* Admin access to all infrastructure
## Backwards Compatibility
N/A
## Reference Implementation
See #931
1. **Documentation Files**:
* `/docs/community/governance.mdx` - Full governance documentation
* `/docs/community/sep-guidelines.mdx` - SEP process guidelines
## Security Implications
N/A
seps/973-expose-additional-metadata-for-implementations-res First recorded · 149 lines, first recorded
# SEP-973: Expose additional metadata for Implementations, Resources, Tools and Prompts ## Abstract ## Motivation ### Current State ### Proposed State ## Rationale ## Specification ## Backwards Compatibility ## Security Implications
The first capture of this source. The page was already there, and this is what it said.
# SEP-973: Expose additional metadata for Implementations, Resources, Tools and Prompts
> Expose additional metadata for Implementations, Resources, Tools and Prompts
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------- |
| **SEP** | 973 |
| **Title** | Expose additional metadata for Implementations, Resources, Tools and Prompts |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-07-15 |
| **Author(s)** | [@jesselumarie](https://github.com/jesselumarie) |
| **Sponsor** | None |
| **PR** | [#973](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/973) |
***
## Abstract
This SEP proposes adding two optional fields—`icons` and `websiteUrl`. The `icons` and `websiteUrl` would be added to the `Implementation` schema so that clients can visually identify third-party implementations and link directly to their documentation. The `icons` parameter will also be added to the `Tool`, `Resource` and `Prompt` schemas. While this can be used by both servers and clients for all implementations, we expect it to be used initially for server-provided implementations.
## Motivation
### Current State
Current implementations only expose namespaced metadata, forcing clients to display generic labels with no visual cues.
<img width="606" height="242" alt="Image" src="https://github.com/user-attachments/assets/0708a467-ed16-4654-8017-47fc30df9b23" />
### Proposed State
The proposed implementation would allow us to add visual affordances and links to documentation, making it easier to visually identify which servers/clients are providing an implementation e.g. a tool in a slash command interface:
<img width="1104" height="780" alt="Image" src="https://github.com/user-attachments/assets/2989b847-8a35-4c49-bb73-d27828df4df6" />
* **Visual Affordance:** Icons make it immediately clear to users which tool or resource source is in use.
* **Discoverability:** A link to documentation (`websiteUrl`) allows clients to direct users to more information with a single click.
## Rationale
This design builds on prior work in web manifests (MDN) and consolidates community feedback:
* **Consolidation of PRs:** Merges the changes from PR #417 and PR #862 into a single, cohesive enhancement.
* **Flexible Icon Sizes:** Supports multiple icon sizes (e.g., `48x48`, `96x96`, or `any` for vector formats) to accommodate different client UI needs.
* **Optional Fields:** By making both fields optional, existing implementations remain fully compatible.
## Specification
Extend the `Implementation` object as follows:
```typescript theme={null}
/**
* A url pointing to an icon URL or a base64-encoded data URI
*
* Clients that support rendering icons MUST support at least the following MIME types:
* - image/png - PNG images (safe, universal compatibility)
* - image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility)
*
* Clients that support rendering icons SHOULD also support:
* - image/svg+xml - SVG images (scalable but requires security precautions)
* - image/webp - WebP images (modern, efficient format)
*/
export interface Icon {
/**
* A standard URI pointing to an icon resource.
*
* Consumers MUST takes steps to ensure URLs serving icons are from the
* same domain as the client/server or a trusted domain.
*
* Consumers MUST take appropriate precautions when consuming SVGs as they can contain
* executable JavaScript
*
* @format uri
*/
src: string;
/** Optional override if the server’s MIME type is missing or generic. */
mimeType?: string;
/** e.g. "48x48", "any" (for SVG), or "48x48 96x96" */
sizes?: string;
}
/**
* Describes the MCP implementation
*/
export interface Implementation extends BaseMetadata {
version: string;
/**
* An optional list of icons for this implementation.
* This can be used by clients to display the implementation in a user interface.
* Each icon should have a `kind` property that specifies whether it is a data representation or a URL source, a `src` property that points to the icon file or data representation, and may also include a `mimeType` and `sizes` property.
* The `mimeType` property should be a valid MIME type for the icon file, such as "image/png" or "image/svg+xml".
* The `sizes` property should be a string that specifies one or more sizes at which the icon file can be used, such as "48x48" or "any" for scalable formats like SVG.
* The `sizes` property is optional, and if not provided, the client should assume that the icon can be used at any size.
*/
icons?: Icon[];
/**
* An optional URL of the website for this implementation.
*
* Consumers MUST takes steps to ensure URLs serving icons are from the
* same domain as the client/server or a trusted domain.
*
* Consumers MUST take appropriate precautions when consuming SVGs as they can contain
* executable JavaScript
*
* @format: uri
*/
websiteUrl?: string;
}
```
Extend the `Tool`, `Resource` and `Prompt` interfaces with the following type:
```typescript theme={null}
/**
* An optional list of icons for a resource.
* This can be used by clients to display the resource's icon in a user interface.
* Each icon should have a `kind` property that specifies whether it is a data representation or a URL source, a `src` property that points to the icon file or data representation, and may also include a `mimeType` and `sizes` property.
* The `mimeType` property should be a valid MIME type for the icon file, such as "image/png" or "image/svg+xml".
* The `sizes` property should be a string that specifies one or more sizes at which the icon file can be used, such as "48x48" or "any" for scalable formats like SVG.
* The `sizes` property is optional, and if not provided, the client should assume that the icon can be used at any size.
*/
icons?: Icon[];
```
## Backwards Compatibility
Both icons and websiteUrl are optional fields; clients that ignore them will fall back to existing behavior.
## Security Implications
This shouldn't introduce any new security implications.
seps/985-align-oauth-20-protected-resource-metadata-with-rf First recorded · 123 lines, first recorded
# SEP-985: Align OAuth 2.0 Protected Resource Metadata with RFC 9728 ## Abstract ## Rationale ## Proposed State ## Backward Compatibility
The first capture of this source. The page was already there, and this is what it said.
# SEP-985: Align OAuth 2.0 Protected Resource Metadata with RFC 9728
> Align OAuth 2.0 Protected Resource Metadata with RFC 9728
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------- |
| **SEP** | 985 |
| **Title** | Align OAuth 2.0 Protected Resource Metadata with RFC 9728 |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-07-16 |
| **Author(s)** | sunishsheth2009 |
| **Sponsor** | None |
| **PR** | [#985](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/985) |
***
## Abstract
This proposal brings the MCP spec's handling of OAuth 2.0 Protected Resource Metadata in line with [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728#name-obtaining-protected-resourc).
Currently, the MCP spec requires the use of the HTTP WWW-Authenticate header when returning a 401 Unauthorized to indicate the location of the protected resource metadata. However, [RFC 9728, Section 5](https://datatracker.ietf.org/doc/html/rfc9728#section-5) states:
“A protected resource MAY use the WWW-Authenticate HTTP response header field, as discussed in RFC 9110, to return a URL to its protected resource metadata to the client.”
This suggests that the MCP spec could be made more flexible while still maintaining RFC compliance.
## Rationale
Many large-scale, dynamic, multi-tenant environments rely on a centralized authentication service separate from the backend resource servers. In such deployments, injecting WWW-Authenticate headers from backend services is non-trivial due to separation of concerns and infrastructure complexity.
In these scenarios, having the option to discover metadata via a well-known URL provides a practical path forward for easier MCP adoption. Requiring only the header would impose significant communication overhead between components, especially when hundreds or thousands of MCP instances are created and destroyed dynamically. Also if there are specific managed MCP servers, adopting headers across centralized system would add significant overhead.
While this increases complexity for clients—who must now implement logic to probe metadata endpoints—it reduces friction for server deployments and may encourage broader adoption. There are tradeoffs:
Pros for Server Developers: Avoid complex header injection; simplifies integration in distributed environments.
Cons for Client Developers: Clients must fall back to metadata discovery logic when the header is absent, increasing client complexity.
## Proposed State
Update the MCP spec to:
```
Clients MUST interpret the WWW-Authenticate header, and fallback to probing for metadata if not present.
Servers SHOULD return the WWW-Authenticate header
```
**The reason for deviating a bit on the RFC:**
Go with SHOULD over MAY for WWW-Authenticate is that it makes supporting other features, such as incremental authorization easier (e.g. you make a request for a tool, but need additional scopes, and receive a WWW-Authenticate challenge indicating the scopes).
Based on the above, following the updated flow:
* Attempt the MCP request without a token.
* If a 401 Unauthorized response is received: Check for a WWW-Authenticate header. If present and includes the resource\_metadata parameter, use it to locate the resource metadata.
* If the header is absent or does not include resource\_metadata, fallback to requesting /.well-known/oauth-protected-resource.
This change allows more flexible deployment models without removing existing capabilities.
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
Note over C: Attempt unauthenticated MCP request
C->>M: MCP request without token
M-->>C: HTTP 401 Unauthorized (may include WWW-Authenticate header)
alt Header includes resource_metadata
Note over C: Extract resource_metadata URL from header
C->>M: GET resource_metadata URI
M-->>C: Resource metadata with authorization server URL
else No resource_metadata in header
Note over C: Fallback to metadata probing
C->>M: GET /.well-known/oauth-protected-resource
alt Metadata found
M-->>C: Resource metadata with authorization server URL
else Metadata not found
Note over C: Abort or use pre-configured values
end
end
Note over C: Validate RS metadata,<br />build AS metadata URL
C->>A: GET /.well-known/oauth-authorization-server
A-->>C: Authorization server metadata
Note over C,A: OAuth 2.1 authorization flow happens here
C->>A: Token request
A-->>C: Access token
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
## Backward Compatibility
This proposal is fully backward-compatible.
It retains support for the WWW-Authenticate header (already in the spec) and introduces a fallback mechanism using the .well-known metadata path, which is already defined in MCP as a MUST-support location.
Clients that already support metadata probing benefit from improved interoperability. Servers are not required to emit the WWW-Authenticate header if it is infeasible, but doing so is still encouraged to reduce client complexity and enable future extensibility.
seps/986-specify-format-for-tool-names First recorded · 81 lines, first recorded
# SEP-986: Specify Format for Tool Names ## Abstract ## Motivation ## Rationale ## Specification ## Backwards Compatibility ## Reference Implementation ## Security Implications
The first capture of this source. The page was already there, and this is what it said.
# SEP-986: Specify Format for Tool Names
> Specify Format for Tool Names
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------- |
| **SEP** | 986 |
| **Title** | Specify Format for Tool Names |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-07-16 |
| **Author(s)** | kentcdodds |
| **Sponsor** | None |
| **PR** | [#986](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/986) |
***
## Abstract
The Model Context Protocol (MCP) currently lacks a standardized format for tool names, resulting in inconsistencies and confusion for both implementers and users. This SEP proposes a clear, flexible standard for tool names: tool names should be 1–64 characters, case-sensitive, and may include alphanumeric characters, underscores (\_), dashes (-), dots (.), and forward slashes (/). This aims to maximize compatibility, clarity, and interoperability across MCP implementations while accommodating a wide range of naming conventions.
## Motivation
Without a prescribed format for tool names, MCP implementations have adopted a variety of naming conventions, including different separators, casing, and character sets. This inconsistency can lead to confusion, errors in tool invocation, and difficulties in documentation and automation. Standardizing the allowed characters and length will:
* Make tool names predictable and interoperable across clients.
* Allow for hierarchical and namespaced tool names (e.g., using / and .).
* Support both human-readable and machine-generated names.
* Avoid unnecessary restrictions that could block valid use cases.
## Rationale
Community discussion highlighted the need for flexibility in tool naming. While some conventions (like lower-kebab-case) are common, many tools and clients use uppercase, underscores, dots, and slashes for namespacing or clarity. The proposed pattern—allowing a-z, A-Z, 0-9, \_, -, ., and /—is based on patterns used in major clients (e.g., VS Code, Claude) and aligns with common conventions in programming and APIs. Restricting spaces and commas avoids parsing issues and ambiguity. The length limit (1–64) is generous enough for most use cases but prevents abuse.
## Specification
* Tool names SHOULD be between 1 and 64 characters in length (inclusive).
* Tool names are case-sensitive.
* Allowed characters: uppercase and lowercase ASCII letters (A-Z, a-z), digits
(0-9), underscore (\_), dash (-), dot (.), and forward slash (/).
* Tool names SHOULD NOT contain spaces, commas, or other special characters.
* Tool names SHOULD be unique within their namespace.
* Example valid tool names:
* getUser
* user-profile/update
* DATA\_EXPORT\_v2
* admin.tools.list
## Backwards Compatibility
This change is not backwards compatible for existing tools that use disallowed characters or exceed the new length limits. To minimize disruption:
* Existing non-conforming tool names SHOULD be supported as aliases for at least one major version, with a deprecation warning.
* Tool authors SHOULD update their documentation and code to use the new format.
* A migration guide SHOULD be provided to assist implementers in updating their tool names.
## Reference Implementation
A reference implementation can be provided by updating the MCP core library to enforce the new tool name validation rules at registration time. Existing tools can be updated to provide aliases for their new conforming names, with warnings for deprecated formats. Example code and migration scripts can be included in the MCP repository.
## Security Implications
None. Standardizing tool name format does not introduce new security risks.
seps/990-enable-enterprise-idp-policy-controls-during-mcp-o First recorded · 95 lines, first recorded
# SEP-990: Enable enterprise IdP policy controls during MCP OAuth flows ## Abstract ## How Has This Been Tested? ## Breaking Changes ## Additional Context
The first capture of this source. The page was already there, and this is what it said.
# SEP-990: Enable enterprise IdP policy controls during MCP OAuth flows
> Enable enterprise IdP policy controls during MCP OAuth flows
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------- |
| **SEP** | 990 |
| **Title** | Enable enterprise IdP policy controls during MCP OAuth flows |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-06-04 |
| **Author(s)** | Aaron Parecki ([@aaronpk](https://github.com/aaronpk)) |
| **Sponsor** | None |
| **PR** | [#646](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/646) |
***
## Abstract
This extension is designed to facilitate secure and interoperable authorization of MCP clients within corporate environments, leveraging existing enterprise identity infrastructure.
* For end users, this removes the need to manually connect and authorize the MCP Client to individual services within the organization.
* For enterprise admins, this enables visibility and control over which MCP Servers are able to be used within the organization.
## How Has This Been Tested?
We have an end to end implementation of this [here](https://github.com/oktadev/okta-cross-app-access-mcp), and in-progress MCP implementations with some partners.
## Breaking Changes
This is designed to augment the existing OAuth profile by providing an alternative when used under an enterprise IdP. MCP clients can opt in to this profile when necessary.
## Additional Context
For more background on this problem, you can refer to my blog post about this here:
[Enterprise-Ready MCP](https://aaronparecki.com/2025/05/12/27/enterprise-ready-mcp)
I also presented this at the MCP Dev Summit in May.
A high level overview of the flow is below:
```mermaid theme={null}
sequenceDiagram
participant UA as Browser
participant C as MCP Client
participant MAS as MCP Authorization Server
participant MRS as MCP Resource Server
participant IdP as Identity Provider
rect rgb(255,255,225)
C-->>UA: Redirect to IdP
UA->>+IdP: Redirect to IdP
Note over IdP: User Logs In
IdP-->>-UA: IdP Authorization Code
UA->>C: IdP Authorization Code
C->>+IdP: Token Request with IdP Authorization Code
IdP-->-C: ID Token
end
note over C: User is logged<br>in to MCP Client.<br>Client stores ID Token.
C->+IdP: Exchange ID Token for ID-JAG
note over IdP: Evaluate Policy
IdP-->-C: Responds with ID-JAG
C->+MAS: Token Request with ID-JAG
note over MAS: Validate ID-JAG
MAS-->-C: MCP Access Token
loop
C->>+MRS: Call MCP API with Access Token
MRS-->>-C: MCP Response with Data
end
```
> \[!IMPORTANT]
> **State:** Ready to Review
seps/991-enable-url-based-client-registration-using-oauth-c First recorded · 303 lines, first recorded
# SEP-991: Enable URL-based Client Registration using OAuth Client ID Metadata Documents ## Abstract ## Motivation ### The Target Use Case: No Pre-existing Relationship ### Key Innovation: Server-Controlled Trust Without Pre-Coordination ## Specification Changes ### Client Requirements ### Server Requirements ### Discovery ### Integration with Existing MCP Auth ## Rationale ### Why This Solves the "No Pre-existing Relationship" Problem ### Redirect URI Attestation ### Risks of this approach #### Risk: Localhost URL Impersonation #### Risk: Server Side Request Forgery (SSRF) #### Risk: Distributed Denial of Service (DDoS) #### Risk: Maturity of referenced specification #### Risk: Client implementation burden, especially local clients #### Risk: Fragmentation of authorization approaches ## Alternatives Considered ## Backward Compatibility ## Prototype Implementation ## Security Implications ### Best Practices ## References
The first capture of this source. The page was already there, and this is what it said.
# SEP-991: Enable URL-based Client Registration using OAuth Client ID Metadata Documents
> Enable URL-based Client Registration using OAuth Client ID Metadata Documents
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Standards Track
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ----------------------------------------------------------------------------------------------------------------- |
| **SEP** | 991 |
| **Title** | Enable URL-based Client Registration using OAuth Client ID Metadata Documents |
| **Status** | Final |
| **Type** | Standards Track |
| **Created** | 2025-07-07 |
| **Author(s)** | Paul Carleton ([@pcarleton](https://github.com/pcarleton)) Aaron Parecki ([@aaronpk](https://github.com/aaronpk)) |
| **Sponsor** | None |
| **PR** | [#991](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/991) |
***
## Abstract
This SEP proposes adopting OAuth Client ID Metadata Documents as specified in [draft-parecki-oauth-client-id-metadata-document-03](https://datatracker.ietf.org/doc/draft-parecki-oauth-client-id-metadata-document/) as an additional client registration mechanism for the Model Context Protocol (MCP). This approach allows OAuth clients to use HTTPS URLs as client identifiers, where the URL points to a JSON document containing client metadata. This specifically addresses the common MCP scenario where servers and clients have no pre-existing relationship, enabling servers to trust clients without pre-coordination while maintaining full control over access policies.
## Motivation
The Model Context Protocol currently supports two client registration approaches:
1. **Pre-registration**: Requires either client developers or users to manually register clients with each server
2. **Dynamic Client Registration (DCR)**: Allows just-in-time registration by sending client metadata to a register endpoint on the Authorization server.
Both approaches have significant limitations for MCP's use case where clients frequently need to connect to servers they've never encountered before:
* Pre-registration by developers is impractical as servers may not exist when clients ship
* Pre-registration by users creates poor UX requiring manual credential management
* DCR requires servers to manage unbounded databases, handle expiration, and trust self-asserted metadata
### The Target Use Case: No Pre-existing Relationship
This proposal specifically targets the common MCP scenario where:
* A user wants to connect a client to a server they've discovered
* The client developer has never heard of this server
* The server operator has never heard of this client
* Both parties need to establish trust without prior coordination
For scenarios with pre-existing relationships, pre-registration remains the optimal solution. However, MCP's value comes from its ability to connect arbitrary clients and servers, making the "no pre-existing relationship" case critical to address.
Relatedly, there are many more MCP servers than there are clients (similar to how there are many more web browsers than API's). A common scenario is an MCP server developer wanting to restrict usage to a set of clients they trust.
### Key Innovation: Server-Controlled Trust Without Pre-Coordination
Client ID Metadata Documents enable a unique trust model where:
1. **Servers can trust clients they've never seen before** based on:
* The HTTPS domain hosting the metadata
* The metadata content itself
* Domain reputation and security policies
2. **Servers maintain full control** through flexible policies:
* **Open Servers**: Can accept any HTTPS client\_id, enabling maximum interoperability
* **Protected Servers**: Can restrict to trusted domains or specific clients
3. **No client pre-coordination required**:
* Clients don't need to know about servers in advance
* Clients just need to host their metadata document
* Trust flows from the client's domain, not prior registration
## Specification Changes
The change to the specification will be adding Client ID Metadata documents as a SHOULD, and changing DCR to a MAY, as we think that Client ID Metadata documents are a better default option for this scenario.
We will primarily rely on the text in the linked RFC, aiming not to repeat most of it. Below is a short version of what we'll need to specify.
```mermaid theme={null}
sequenceDiagram
participant User
participant Client as MCP Client
participant Server as Authorization Server
participant Metadata as Metadata Endpoint<br/>(Client's HTTPS URL)
participant Resource as MCP Server
Note over Client,Metadata: Client hosts metadata at<br/>https://app.example.com/oauth/metadata.json
User->>Client: Initiates connection to MCP Server
Client->>Server: Authorization Request<br/>client_id=https://app.example.com/oauth/metadata.json<br/>redirect_uri=http://localhost:3000/callback
Note over Server: Authenticates user
Note over Server: Detects URL-formatted client_id
Server->>Metadata: GET https://app.example.com/oauth/metadata.json
Metadata-->>Server: JSON Metadata Document<br/>{client_id, client_name, redirect_uris, ...}
Note over Server: Validates:<br/>1. client_id matches URL<br/>2. redirect_uri in allowed list<br/>3. Document structure valid<br/>4. Domain allowed via trust policy
alt Validation Success
Server->>User: Display consent page with client_name
User->>Server: Approves access
Server->>Client: Authorization code via redirect_uri
Client->>Server: Exchange code for token<br/>client_id=https://app.example.com/oauth/metadata.json
Server-->>Client: Access token
Client->>Resource: MCP requests with access token
Resource-->>Client: MCP responses
else Validation Failure
Server->>User: Error response<br/>error=invalid_client or invalid_request
end
Note over Server: Cache metadata for future requests<br/>(respecting HTTP cache headers)
```
### Client Requirements
* Clients MUST host their metadata document at an HTTPS URL following RFC requirements
* The client\_id URL MUST use "https" scheme and contain a path component
* Metadata documents MUST be valid JSON and include at minimum:
* `client_id`: matching the document URL exactly
* `client_name`: human-readable name for authorization prompts
* `redirect_uris`: array of allowed redirect URIs
* `token_endpoint_auth_method`: "none" for public clients
Note a client can use `private_key_jwt` for a `token_endpoint_auth_method` given the client metadata can provide public key information.
### Server Requirements
* Servers SHOULD fetch metadata documents when encountering URL-formatted client\_ids
* Servers MUST validate the fetched document contains matching client\_id
* Servers SHOULD cache metadata respecting HTTP headers (max 24 hours recommended)
* Servers MUST validate redirect URIs match those in metadata document
### Discovery
* Servers advertise support via OAuth metadata: `client_id_metadata_document_supported: true`
* Clients detect support and can fallback to DCR or pre-registration if unavailable
Example metadata document:
```json theme={null}
{
"client_id": "https://app.example.com/oauth/client-metadata.json",
"client_name": "Example MCP Client",
"client_uri": "https://app.example.com",
"logo_uri": "https://app.example.com/logo.png",
"redirect_uris": [
"http://127.0.0.1:3000/callback",
"http://localhost:3000/callback"
],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
```
### Integration with Existing MCP Auth
This proposal adds Client ID Metadata Documents as a third registration option alongside pre-registration and DCR. Servers MAY support any combination of these approaches:
* Pre-registration remains unchanged
* DCR remains unchanged
* Client ID Metadata Documents are detected by URL-formatted client\_ids, and server support is advertised in OAuth metadata.
## Rationale
### Why This Solves the "No Pre-existing Relationship" Problem
Unlike pre-registration which requires coordination, or DCR which requires servers to manage a registration database, Client ID Metadata Documents provide:
1. **Verifiable Identity**: The HTTPS URL serves as both identifier and trust anchor
2. **No Coordination Needed**: Clients publish metadata, servers consume it
3. **Flexible Trust Policies**: Servers decide their own trust criteria without requiring client changes
4. **Stable Identifiers**: Unlike DCR's ephemeral IDs, URLs are stable and auditable
### Redirect URI Attestation
A key benefit of Client ID Metadata Documents is attestation of redirect URIs:
1. **The metadata document cryptographically binds redirect URIs to the client identity** via HTTPS
2. **Servers can trust that redirect URIs in the metadata are controlled by the client** - not attacker-supplied
3. **This prevents redirect URI manipulation attacks** common with self-asserted registration
### Risks of this approach
#### Risk: Localhost URL Impersonation
A limitation of Client ID Metadata Documents is that they cannot prevent localhost URL impersonation by itself. An attacker can claim to be any client by:
1. Providing the legitimate client's metadata URL as their client\_id
2. Binding to the same localhost port the legitimate client uses
3. Intercepting the authorization code when the user approves
This attack is concerning because the server sees the correct metadata
document and the user sees the correct client name, making detection
difficult.
Platform-specific attestations (iOS DeviceCheck, Android
Play Integrity) could address this, but they're not universally available. This
would work by a developer running a backend service that consumes the DeviceCheck / Play Integrity
signatures and returns a JWT usable as the `private_key_jwt` authentication for the `token_endpoint_auth_method`.
A similar approach without requiring platform-specific attestations that still raises the cost of the attack
is possible using JWKS and short-lived JWTs signed by a server-side component hosted by the client developer. This component could use attestation mechanisms other than platform-specific ones to attest to the clients identity, such as the client's standard login flow. Using short lived JWTs reduces the risk of credential compromise and replay, but does not eliminate it
entirely - an attacker could still proxy requests to the legitimate
client's signing endpoint.
Fully mitigating this risk is outside the scope of this proposal. This
proposal has the same risks as DCR does in a localhost redirect scenario.
Servers SHOULD display additional warnings for localhost-only clients.
#### Risk: Server Side Request Forgery (SSRF)
The authorization server takes a URL as input from an unknown client, and then fetches that URL. A malicious client could use this to send non-metadata requests on behalf of the authorization server. An example would be sending a URL corresponding to a private administration endpoint that the authorization server has access to.
This can be prevented by validating the URL's and the IP's those URL's resolve to prior to initiating a fetch request.
#### Risk: Distributed Denial of Service (DDoS)
Similarly, an attacker could try to leverage a pool of authorization servers to perform a denial of service attack on a non-MCP server.
There is not any additional amplification for the fetch request (i.e. the bandwidth from the client to make the request roughly equals the bandwidth of the request sent to the target server), and each authorization server can aggressively cache the result of these metadata fetches, so it is unlikely to be an attractive DDoS vector.
#### Risk: Maturity of referenced specification
The RFC for Client ID Metadata documents is still a draft. It has been implemented by the platform Bluesky, but has not been ratified or very widely adopted outside of that, and may evolve over time. Our intention is to evolve and align with subsequent drafts and any final standard, while minimizing disruption and breakage with existing implementations.
This approach has the risk that there are implementation challenges or flaws in the protocol that have not surfaced yet. However, even though DCR has been ratified, and it also has a number of implementation challenges that developers are facing when trying to use it in an open ecosystem context like MCP. Those challenges are the motivation behind this proposal.
#### Risk: Client implementation burden, especially local clients
This specification requires an additional piece of infrastructure for clients, since they need to host a metadata file behind an HTTPS url. Without this specification, a client could be strictly a desktop application for example.
The burden of hosting this endpoint is expected to be low as hosting a static JSON file is fairly straightforward and most known clients have a webpage advertising their client or providing download links.
#### Risk: Fragmentation of authorization approaches
Authorization for MCP is already challenging to fully implement for clients and servers. Questions about how to do it correctly and best practices are some of the most common in the community. Adding another branch to the authorization flow means this could be even more complicated and fractured, meaning fewer developers succeed in following the specification, and the promise of compatibility and an open ecosystem suffers as a result.
This proposal intends to simplify the story for authorization server and resource server developers by providing a clearer mechanism to trust redirect URIs and less operational overhead. This proposal depends on that simplicity being clearly the better option for most folks, which will drive more adoption and end up being the most supported option. If we do not believe that it is clearly the better option, then we should not adopt this proposal.
This proposal also provides a unified mechanism for both open servers and servers that want to restrict which clients can be used. Alternatives to this proposal require that clients and servers implement different mechanisms for the open and protected use cases.
## Alternatives Considered
1. **Enhanced DCR with Software Statements**: More complex, requires JWKS hosting and JWT signing
2. **Mandatory Pre-registration**: Poor developer and user experience for MCP's distributed ecosystem
3. **Mutual TLS**: Requires trusting a client certificate authority, impractical in an open ecosystem
4. **Status Quo**: Continues current pain points for server implementers
Client ID Metadata document is a strict improvement over DCR for the most common open-ecosystem use case. It can be further extended in the future to better support things like OS-level attestations and jwks\_uri's.
## Backward Compatibility
This proposal is fully backward compatible:
* Existing pre-registered clients continue working unchanged
* Existing DCR implementations continue working unchanged
* Servers can adopt Client ID Metadata Documents incrementally
* Clients can detect support and fall back to other methods
## Prototype Implementation
A prototype implementation is available [here](https://github.com/modelcontextprotocol/typescript-sdk/pull/839) demonstrating:
1. Client-side metadata document hosting
2. Server-side metadata fetching and validation
3. Integration with existing MCP OAuth flows
4. Proper error handling and fallback behavior
## Security Implications
1. **Phishing Prevention**: Display client hostname prominently
2. **SSRF Protection**: Validate URLs, limit response size, timeout requests, rate limit outbound requests
### Best Practices
* Only fetch client metadata after authenticating the user
* Implement rate limiting on outbound metadata fetches
* Consider additional warnings for new/unknown/localhost domains
* Log metadata fetch failures for monitoring
## References
* [draft-parecki-oauth-client-id-metadata-document-03](https://www.ietf.org/archive/id/draft-parecki-oauth-client-id-metadata-document-03.txt)
* [OAuth 2.1](https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/)
Cut at 300 lines. The page has the rest.
seps/994-shared-communication-practicesguidelines First recorded · 133 lines, first recorded
# SEP-994: Shared Communication Practices/Guidelines ## Abstract ## Motivation ## Specification ### Communication Channels ### Discord Guidelines #### Public Channels (Default) #### Private Channels (Exceptions) ### GitHub Discussions ### GitHub Issues ### Decision Records ## Rationale ## Backward Compatibility ## Reference Implementation
The first capture of this source. The page was already there, and this is what it said.
# SEP-994: Shared Communication Practices/Guidelines
> Shared Communication Practices/Guidelines
<div className="flex items-center gap-2 mb-4">
<Badge color="green" shape="pill">
Final
</Badge>
<Badge color="gray" shape="pill">
Process
</Badge>
</div>
<Note>
This SEP has reached Final status and is preserved as a historical record of
the design as accepted. Changes made to the protocol after finalization are
not reflected here. Refer to the [current
specification](/specification/latest) and its changelog for authoritative
requirements.
</Note>
| Field | Value |
| ------------- | ------------------------------------------------------------------------------- |
| **SEP** | 994 |
| **Title** | Shared Communication Practices/Guidelines |
| **Status** | Final |
| **Type** | Process |
| **Created** | 2025-07-17 |
| **Author(s)** | [@localden](https://github.com/localden) |
| **Sponsor** | None |
| **PR** | [#1002](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1002) |
***
## Abstract
This SEP establishes the communication strategy and framework for the Model Context Protocol community. It defines the official channels for contributor communication, guidelines for their use, and processes for decision documentation.
## Motivation
As the MCP community grows, clear communication guidelines are essential for:
* **Consistency**: Ensuring all contributors know where and how to communicate
* **Transparency**: Making project decisions visible and accessible
* **Efficiency**: Directing discussions to the most appropriate channels
* **Security**: Establishing proper processes for handling sensitive issues
## Specification
### Communication Channels
The MCP project uses three primary communication channels:
1. **Discord**: For real-time or ad-hoc discussions among contributors
2. **GitHub Discussions**: For structured, longer-form discussions
3. **GitHub Issues**: For actionable tasks, bug reports, and feature requests
Security-sensitive issues follow a separate process defined in SECURITY.md.
### Discord Guidelines
The Discord server is designed for **MCP contributors** and is not intended for general MCP support.
#### Public Channels (Default)
* Open community engagement and collaborative development
* SDK and tooling development discussions
* Working and Interest Group discussions
* Community onboarding and contribution guidance
* Office hours and maintainer availability
#### Private Channels (Exceptions)
Private channels are reserved for:
* Security incidents (CVEs, protocol vulnerabilities)
* People matters (maintainer discussions, code of conduct)
* Coordination requiring immediate focused response
All technical and governance decisions must be documented publicly in GitHub.
### GitHub Discussions
Used for structured, long-form discussion:
* Project roadmap planning
* Announcements and release communications
* Community polls and consensus-building
* Feature requests with context and rationale
### GitHub Issues
Used for actionable items:
* Bug reports with reproducible steps
* Documentation improvements
* CI/CD and infrastructure issues
* Release tasks and milestone tracking
### Decision Records
All MCP decisions are documented publicly:
* **Technical decisions**: GitHub Issues and SEPs
* **Specification changes**: Changelog on the MCP website
* **Process changes**: Community documentation
* **Governance decisions**: GitHub Issues and SEPs
Decision documentation includes:
* Decision makers
* Background context and motivation
* Options considered
* Rationale for chosen approach
* Implementation steps
## Rationale
This framework balances openness with practicality:
* **Public by default**: Maximizes transparency and community participation
* **Private when necessary**: Protects security and personal matters
* **Channel separation**: Keeps discussions organized and searchable
* **Documentation requirements**: Ensures decisions are preserved and discoverable
## Backward Compatibility
This SEP establishes new processes and does not affect existing protocol functionality.
## Reference Implementation
The communication guidelines are published at: [https://modelcontextprotocol.io/community/communication](https://modelcontextprotocol.io/community/communication)
seps/index First recorded · 72 lines, first recorded
# Specification Enhancement Proposals (SEPs) ## Summary ## All SEPs ## SEP Status Definitions
The first capture of this source. The page was already there, and this is what it said.
# Specification Enhancement Proposals (SEPs) > Index of all MCP Specification Enhancement Proposals Specification Enhancement Proposals (SEPs) are the primary mechanism for proposing major changes to the Model Context Protocol. Each SEP provides a concise technical specification and rationale for proposed features. <Card title="Submit a SEP" icon="file-plus" href="/community/sep-guidelines"> Learn how to submit your own Specification Enhancement Proposal </Card> ## Summary * **Final**: 41 ## All SEPs | SEP | Title | Status | Type | Created | | ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------- | ---------------- | ---------- | | [SEP-2663](/seps/2663-tasks-extension) | Tasks Extension | <Badge color="green" shape="pill">Final</Badge> | Extensions Track | 2026-04-27 | | [SEP-2596](/seps/2596-spec-feature-lifecycle-and-deprecation) | Specification Feature Lifecycle and Deprecation Policy | <Badge color="green" shape="pill">Final</Badge> | Process | 2026-04-17 | | [SEP-2577](/seps/2577-deprecate-roots-sampling-and-logging) | Deprecate Roots, Sampling, and Logging | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-04-14 | | [SEP-2575](/seps/2575-stateless-mcp) | Make MCP Stateless | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-06-18 | | [SEP-2567](/seps/2567-sessionless-mcp) | Sessionless MCP via Explicit State Handles | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-03-11 | | [SEP-2549](/seps/2549-TTL-for-list-results) | TTL for List Results | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-04-09 | | [SEP-2484](/seps/2484-conformance-tests-required-for-final-seps) | Require Conformance Tests for Standards Track SEPs to Reach Final Status | <Badge color="green" shape="pill">Final</Badge> | Process | 2026-03-27 | | [SEP-2468](/seps/2468-recommend-issuer-claim-for-auth) | Recommend Issuer (iss) Parameter in MCP Auth Responses | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-03-25 | | [SEP-2322](/seps/2322-MRTR) | Multi Round-Trip Requests | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-02-03 | | [SEP-2260](/seps/2260-Require-Server-requests-to-be-associated-with-Client-requests) | Require Server requests to be associated with a Client request. | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-02-16 | | [SEP-2243](/seps/2243-http-standardization) | HTTP Header Standardization for Streamable HTTP Transport | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-02-04 | | [SEP-2207](/seps/2207-oidc-refresh-token-guidance) | OIDC-Flavored Refresh Token Guidance | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-02-04 | | [SEP-2164](/seps/2164-resource-not-found-error) | Standardize Resource Not Found Error Code | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-01-28 | | [SEP-2149](/seps/2149-working-group-charter-template) | MCP Group Governance and Charter Template | <Badge color="green" shape="pill">Final</Badge> | Process | 2025-01-15 | | [SEP-2148](/seps/2148-contributor-ladder) | MCP Contributor Ladder | <Badge color="green" shape="pill">Final</Badge> | Process | 2026-01-15 | | [SEP-2133](/seps/2133-extensions) | Extensions | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-01-21 | | [SEP-2106](/seps/2106-json-schema-2020-12) | Tools `inputSchema` & `outputSchema` Conform to JSON Schema 2020-12 | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2026-01-06 | | [SEP-2085](/seps/2085-governance-succession-and-amendment) | Governance Succession and Amendment Procedures | <Badge color="green" shape="pill">Final</Badge> | Process | 2025-12-05 | | [SEP-1865](/seps/1865-mcp-apps-interactive-user-interfaces-for-mcp) | MCP Apps - Interactive User Interfaces for MCP | <Badge color="green" shape="pill">Final</Badge> | Extensions Track | 2025-11-21 | | [SEP-1850](/seps/1850-pr-based-sep-workflow) | PR-Based SEP Workflow | <Badge color="green" shape="pill">Final</Badge> | Process | 2025-11-20 | | [SEP-1730](/seps/1730-sdks-tiering-system) | SDKs Tiering System | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-10-29 | | [SEP-1699](/seps/1699-support-sse-polling-via-server-side-disconnect) | Support SSE polling via server-side disconnect | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-10-22 | | [SEP-1686](/seps/1686-tasks) | Tasks | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-10-20 | | [SEP-1613](/seps/1613-establish-json-schema-2020-12-as-default-dialect-f) | Establish JSON Schema 2020-12 as Default Dialect for MCP | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-10-06 | | [SEP-1577](/seps/1577--sampling-with-tools) | Sampling With Tools | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-09-30 | | [SEP-1330](/seps/1330-elicitation-enum-schema-improvements-and-standards) | Elicitation Enum Schema Improvements and Standards Compliance | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-08-11 | | [SEP-1319](/seps/1319-decouple-request-payload-from-rpc-methods-definiti) | Decouple Request Payload from RPC Methods Definition | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-08-08 | | [SEP-1303](/seps/1303-input-validation-errors-as-tool-execution-errors) | Input Validation Errors as Tool Execution Errors | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-08-05 | | [SEP-1302](/seps/1302-formalize-working-groups-and-interest-groups-in-mc) | Formalize Working Groups and Interest Groups in MCP Governance | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-08-05 | | [SEP-1046](/seps/1046-support-oauth-client-credentials-flow-in-authoriza) | Support OAuth client credentials flow in authorization | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-23 | | [SEP-1036](/seps/1036-url-mode-elicitation-for-secure-out-of-band-intera) | URL Mode Elicitation for secure out-of-band interactions | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-22 | | [SEP-1034](/seps/1034--support-default-values-for-all-primitive-types-in) | Support default values for all primitive types in elicitation schemas | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-22 | | [SEP-1024](/seps/1024-mcp-client-security-requirements-for-local-server-) | MCP Client Security Requirements for Local Server Installation | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-22 | | [SEP-994](/seps/994-shared-communication-practicesguidelines) | Shared Communication Practices/Guidelines | <Badge color="green" shape="pill">Final</Badge> | Process | 2025-07-17 | | [SEP-991](/seps/991-enable-url-based-client-registration-using-oauth-c) | Enable URL-based Client Registration using OAuth Client ID Metadata Documents | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-07 | | [SEP-990](/seps/990-enable-enterprise-idp-policy-controls-during-mcp-o) | Enable enterprise IdP policy controls during MCP OAuth flows | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-06-04 | | [SEP-986](/seps/986-specify-format-for-tool-names) | Specify Format for Tool Names | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-16 | | [SEP-985](/seps/985-align-oauth-20-protected-resource-metadata-with-rf) | Align OAuth 2.0 Protected Resource Metadata with RFC 9728 | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-16 | | [SEP-973](/seps/973-expose-additional-metadata-for-implementations-res) | Expose additional metadata for Implementations, Resources, Tools and Prompts | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-07-15 | | [SEP-932](/seps/932-model-context-protocol-governance) | Model Context Protocol Governance | <Badge color="green" shape="pill">Final</Badge> | Process | 2025-07-08 | | [SEP-414](/seps/414-request-meta) | Document OpenTelemetry Trace Context Propagation Conventions | <Badge color="green" shape="pill">Final</Badge> | Standards Track | 2025-04-25 | ## SEP Status Definitions | Status | Definition | | ----------------------------------------------------- | -------------------------------------------------------- | | <Badge color="gray" shape="pill">Draft</Badge> | SEP proposal with a sponsor, undergoing informal review | | <Badge color="yellow" shape="pill">In-Review</Badge> | SEP proposal ready for formal review by Core Maintainers | | <Badge color="blue" shape="pill">Accepted</Badge> | SEP accepted, awaiting reference implementation | | <Badge color="green" shape="pill">Final</Badge> | SEP finalized with reference implementation complete | | <Badge color="red" shape="pill">Rejected</Badge> | SEP rejected by Core Maintainers | | <Badge color="red" shape="pill">Withdrawn</Badge> | SEP withdrawn by the author | | <Badge color="purple" shape="pill">Superseded</Badge> | SEP replaced by a newer SEP | | <Badge color="orange" shape="pill">Dormant</Badge> | SEP without a sponsor, closed after 6 months |
specification/2026-07-28/architecture/index First recorded · 172 lines, first recorded
# Architecture ## Core Components ### Host ### Clients ### Servers ## Design Principles ## Capability Negotiation
The first capture of this source. The page was already there, and this is what it said.
# Architecture
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) follows a client-host-server architecture where each
host can run multiple client instances. MCP is a stateless protocol: every request is
self-contained and carries its own protocol version and capabilities.
This architecture enables users to integrate AI capabilities across applications while
maintaining clear security boundaries and isolating concerns. Built on JSON-RPC, MCP
provides a protocol focused on context exchange and sampling coordination between
clients and servers.
## Core Components
```mermaid theme={null}
graph LR
subgraph "Application Host Process"
H[Host]
C1[Client 1]
C2[Client 2]
C3[Client 3]
H --> C1
H --> C2
H --> C3
end
subgraph "Local machine"
S1[Server 1<br>Files & Git]
S2[Server 2<br>Database]
R1[("Local<br>Resource A")]
R2[("Local<br>Resource B")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3[Server 3<br>External APIs]
R3[("Remote<br>Resource C")]
C3 --> S3
S3 <--> R3
end
```
### Host
The host process acts as the container and coordinator:
* Creates and manages multiple client instances
* Controls client connection permissions and lifecycle
* Enforces security policies and consent requirements
* Handles user authorization decisions
* Coordinates AI/LLM integration and sampling
* Manages context aggregation across clients
### Clients
Each client is created by the host and communicates with exactly one server:
* Communicates with exactly one server
* Attaches protocol version and capabilities to every request
* Routes protocol messages bidirectionally
* Manages subscriptions and notifications
* Maintains security boundaries between servers
A host application creates and manages multiple clients, with each client having a 1:1
relationship with a particular server.
### Servers
Servers provide specialized context and capabilities:
* Expose resources, tools and prompts via MCP primitives
* Operate independently with focused responsibilities
* Request client input (sampling, elicitation, roots) via `InputRequiredResult` within a reply
* Must respect security constraints
* Can be local processes or remote services
## Design Principles
MCP is built on several key design principles that inform its architecture and
implementation:
1. **Servers should be extremely easy to build**
* Host applications handle complex orchestration responsibilities
* Servers focus on specific, well-defined capabilities
* Simple interfaces minimize implementation overhead
* Clear separation enables maintainable code
2. **Servers should be highly composable**
* Each server provides focused functionality in isolation
* Multiple servers can be combined seamlessly
* Shared protocol enables interoperability
* Modular design supports extensibility
3. **Servers should not be able to read the whole conversation, nor "see into" other
servers**
* Servers receive only necessary contextual information
* Full conversation history stays with the host
* Each server maintains isolation
* Cross-server interactions are controlled by the host
* Host process enforces security boundaries
4. **Features can be added to servers and clients progressively**
* Core protocol provides minimal required functionality
* Additional capabilities can be negotiated as needed
* Servers and clients evolve independently
* Protocol designed for future extensibility
* Backwards compatibility is maintained
## Capability Negotiation
The Model Context Protocol uses a capability-based negotiation system where clients and
servers declare their supported features on each request. Clients include their
capabilities in `_meta.io.modelcontextprotocol/clientCapabilities` on every request.
Servers advertise their capabilities in response to
[`server/discover`](/specification/2026-07-28/server/discover), which clients may call before
any other request for up-front capability discovery.
* Servers declare capabilities like tool support, resource subscriptions, and prompt
templates
* Clients declare capabilities like sampling support and elicitation handling
* Both parties must respect declared capabilities throughout the interaction
* Additional capabilities can be negotiated through extensions to the protocol
```mermaid theme={null}
sequenceDiagram
participant Host
participant Client
participant Server
opt Discovery
Client->>Server: server/discover
Server-->>Client: supported versions + capabilities
end
loop Client Requests
Host->>Client: User- or model-initiated action
Client->>Server: Request (with _meta: version, clientCapabilities)
alt Server requires client input
Server-->>Client: InputRequiredResult (e.g. sampling/createMessage)
Client->>Host: Forward to AI
Host-->>Client: AI response
Client->>Server: Original request (with input)
end
Server-->>Client: Response
Client-->>Host: Update UI or respond to model
end
opt Subscriptions
Client->>Server: subscriptions/listen (toolsListChanged, resourceSubscriptions, …)
Server--)Client: notifications/subscriptions/acknowledged
loop Stream
Server--)Client: notifications/* (tagged with subscriptionId)
end
end
```
Each capability unlocks specific protocol features on a per-request basis. For example:
* Implemented [server features](/specification/2026-07-28/server) must be advertised in the
server's capabilities
* Receiving resource update notifications requires opening a
[`subscriptions/listen`](/specification/2026-07-28/basic/patterns/subscriptions) stream
with the desired resource URIs
* [Tool](/specification/2026-07-28/server/tools) invocation requires the server to declare tool capabilities
This capability negotiation ensures clients and servers have a clear understanding of
supported functionality while maintaining protocol extensibility.
specification/2026-07-28/basic/authorization/authorization-server-discovery First recorded · 142 lines, first recorded
# Authorization Server Discovery ## Authorization Server Location ## Protected Resource Metadata Discovery Requirements ## Authorization Server Metadata Discovery ## Sequence Diagram
The first capture of this source. The page was already there, and this is what it said.
# Authorization Server Discovery
<div id="enable-section-numbers" />
This document describes the mechanisms by which MCP servers advertise their associated
authorization servers to MCP clients, as well as the discovery process through which MCP
clients can determine authorization server endpoints and supported capabilities.
## Authorization Server Location
MCP servers **MUST** implement the OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
specification to indicate the locations of authorization servers. The Protected Resource Metadata document returned by the MCP server **MUST** include
the `authorization_servers` field containing at least one authorization server.
The specific use of `authorization_servers` is beyond the scope of this specification; implementers should consult
OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)) for
guidance on implementation details.
Implementors should note that Protected Resource Metadata documents
can define multiple authorization servers. The responsibility for
selecting which authorization server to use lies with the MCP client,
following the guidelines specified in
[RFC9728 Section 7.6 "Authorization Servers"](https://datatracker.ietf.org/doc/html/rfc9728#name-authorization-servers).
When multiple authorization servers are listed in `authorization_servers`, each is an
independent OAuth 2.0 authorization server. Consistent with
[RFC 6749 Section 2.2](https://datatracker.ietf.org/doc/html/rfc6749#section-2.2), client
identifiers are unique to the authorization server that issued them. Clients **MUST** maintain
separate registration state (client credentials, tokens) per authorization server and
**MUST NOT** assume that credentials valid for one authorization server will be accepted by
another. See
[Authorization Server Binding](/specification/2026-07-28/basic/authorization/client-registration#authorization-server-binding)
for the requirements on associating client credentials with the authorization server that issued them.
## Protected Resource Metadata Discovery Requirements
MCP servers **MUST** implement one of the following discovery mechanisms to provide authorization server location information to MCP clients:
1. **WWW-Authenticate Header**: Include the resource metadata URL in the `WWW-Authenticate` HTTP header under `resource_metadata` when returning `401 Unauthorized` responses, as described in [RFC9728 Section 5.1](https://datatracker.ietf.org/doc/html/rfc9728#name-www-authenticate-response).
2. **Well-Known URI**: Serve metadata at a well-known URI as specified in [RFC9728](https://datatracker.ietf.org/doc/html/rfc9728). This can be either:
* At the path of the server's MCP endpoint: `https://example.com/public/mcp` could host metadata at `https://example.com/.well-known/oauth-protected-resource/public/mcp`
* At the root: `https://example.com/.well-known/oauth-protected-resource`
MCP clients **MUST** support both discovery mechanisms and use the resource metadata URL from the parsed `WWW-Authenticate` headers when present; otherwise, they **MUST** fall back to constructing and requesting the well-known URIs in the order listed above.
MCP clients **MUST** be able to parse `WWW-Authenticate` headers and respond appropriately to `HTTP 401 Unauthorized` responses from the MCP server.
Servers can also include a `scope` parameter in the `WWW-Authenticate` challenge to indicate the
scopes required for accessing the resource; the scope semantics and the associated client behavior
are defined in the [Scope Selection Strategy](/specification/2026-07-28/basic/authorization#scope-selection-strategy) section.
## Authorization Server Metadata Discovery
MCP uses the default `oauth-authorization-server` well-known URI
suffix defined in
[RFC 8414 Section 3.1](https://datatracker.ietf.org/doc/html/rfc8414#section-3.1)
for authorization server metadata discovery. MCP does not define
an application-specific well-known URI suffix.
To handle different issuer URL formats and ensure
interoperability with both OAuth 2.0 Authorization Server
Metadata and OpenID Connect Discovery 1.0 specifications, MCP
clients **MUST** attempt multiple well-known endpoints when
discovering authorization server metadata.
The discovery approach is based on
[RFC 8414 Section 3.1 "Authorization Server Metadata Request"](https://datatracker.ietf.org/doc/html/rfc8414#section-3.1)
for OAuth 2.0 Authorization Server Metadata discovery and
[RFC 8414 Section 5 "Compatibility Notes"](https://datatracker.ietf.org/doc/html/rfc8414#section-5)
for OpenID Connect Discovery 1.0 interoperability.
For issuer URLs with path components
(e.g., `https://auth.example.com/tenant1`), clients **MUST**
try endpoints in the following priority order:
1. OAuth 2.0 Authorization Server Metadata with path insertion:
`https://auth.example.com/.well-known/oauth-authorization-server/tenant1`
2. OpenID Connect Discovery 1.0 with path insertion:
`https://auth.example.com/.well-known/openid-configuration/tenant1`
3. OpenID Connect Discovery 1.0 path appending:
`https://auth.example.com/tenant1/.well-known/openid-configuration`
For issuer URLs without path components
(e.g., `https://auth.example.com`), clients **MUST** try:
1. OAuth 2.0 Authorization Server Metadata:
`https://auth.example.com/.well-known/oauth-authorization-server`
2. OpenID Connect Discovery 1.0:
`https://auth.example.com/.well-known/openid-configuration`
After retrieving a metadata document, MCP clients **MUST** validate it as required by [RFC8414 Section 3.3](https://datatracker.ietf.org/doc/html/rfc8414#section-3.3) or [OpenID Connect Discovery Section 4.3](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation): the `issuer` value in the document **MUST** be identical to the issuer identifier used to construct the well-known URL. If they differ, the client **MUST NOT** use the metadata. For example, a document fetched from `https://attacker.example/.well-known/oauth-authorization-server` that contains `"issuer": "https://honest.example"` **MUST** be rejected.
## Sequence Diagram
The following diagram outlines an example flow:
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
Note over C: Attempt unauthenticated MCP request
C->>M: MCP request without token
M-->>C: HTTP 401 Unauthorized (may include WWW-Authenticate header)
alt Header includes resource_metadata
Note over C: Extract resource_metadata URL from header
C->>M: GET resource_metadata URI
M-->>C: Resource metadata with authorization server URL
else No resource_metadata in header
Note over C: Fallback to well-known URI probing
Note over M: _Not applicable if the MCP server is at the root_
C->>M: GET /.well-known/oauth-protected-resource/mcp
alt Sub-path metadata found
M-->>C: Resource metadata with authorization server URL
else Sub-path not found
C->>M: GET /.well-known/oauth-protected-resource
alt Root metadata found
M-->>C: Resource metadata with authorization server URL
else Root metadata not found
Note over C: Abort or use pre-configured values
end
end
end
Note over C: Validate RS metadata,<br />build AS metadata URL
C->>A: GET Authorization server metadata endpoint
Note over C,A: Try OAuth 2.0 and OpenID Connect<br/>discovery endpoints in priority order
A-->>C: Authorization server metadata
Note over C,A: OAuth 2.1 authorization flow happens here
C->>A: Token request
A-->>C: Access token
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
specification/2026-07-28/basic/authorization/client-registration First recorded · 200 lines, first recorded
# Client Registration ## Client ID Metadata Documents ### Implementation Requirements ### Example Metadata Document ### Client ID Metadata Documents Flow ### Advertising CIMD Support ## Pre-registration ## Dynamic Client Registration ### Application Type and Redirect URI Constraints ## Authorization Server Binding
The first capture of this source. The page was already there, and this is what it said.
# Client Registration
<div id="enable-section-numbers" />
MCP supports three client registration mechanisms. Choose based on your scenario:
* **[Client ID Metadata Documents](#client-id-metadata-documents)**: When client and server have no prior relationship (most common)
* **[Pre-registration](#pre-registration)**: When client and server have an existing relationship
* **[Dynamic Client Registration](#dynamic-client-registration)**: For backwards compatibility or specific requirements
Clients supporting all options **SHOULD** use the following priority order:
1. Use pre-registered client information for the server if the client has it available
2. Use Client ID Metadata Documents if the Authorization Server indicates that it supports them (via `client_id_metadata_document_supported` in OAuth Authorization Server Metadata)
3. Use Dynamic Client Registration as a fallback if the Authorization Server supports it (via `registration_endpoint` in OAuth Authorization Server Metadata)
4. Prompt the user to enter the client information if no other option is available
## Client ID Metadata Documents
MCP clients and authorization servers **SHOULD** support OAuth Client ID Metadata Documents as specified in
[OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00)
for client registration.
This approach enables clients to use HTTPS URLs as client identifiers, where the URL points to a JSON document
containing client metadata. This addresses the common MCP scenario where servers and clients have
no pre-existing relationship.
### Implementation Requirements
MCP implementations supporting Client ID Metadata Documents **MUST** follow the requirements specified in
[OAuth Client ID Metadata Document](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00).
Key requirements include:
**For MCP Clients:**
* Clients **MUST** host their metadata document at an HTTPS URL following RFC requirements
* The `client_id` URL **MUST** use the "https" scheme and contain a path component, e.g. `https://example.com/client.json`
* The metadata document **MUST** include at least the following properties: `client_id`, `client_name`, `redirect_uris`
* Clients **MUST** ensure the `client_id` value in the metadata matches the document URL exactly
* Clients **MAY** use `private_key_jwt` for client authentication (e.g., for requests to the token endpoint) with appropriate JWKS configuration as described in [Section 6.2 of Client ID Metadata Document](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.2)
**For Authorization Servers:**
* **SHOULD** fetch metadata documents when encountering URL-formatted client\_ids
* **MUST** validate that the fetched document's `client_id` matches the URL exactly
* **SHOULD** cache metadata respecting HTTP cache headers
* **MUST** validate redirect URIs presented in an authorization request against those in the metadata document
* **MUST** validate the document structure is valid JSON and contains required fields
* **SHOULD** follow the security considerations in [Section 6 of Client ID Metadata Document](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6) and in [Client ID Metadata Document Security](/specification/2026-07-28/basic/authorization/security-considerations#client-id-metadata-document-security)
### Example Metadata Document
```json theme={null}
{
"client_id": "https://app.example.com/oauth/client-metadata.json",
"client_name": "Example MCP Client",
"client_uri": "https://app.example.com",
"logo_uri": "https://app.example.com/logo.png",
"redirect_uris": [
"http://127.0.0.1:3000/callback",
"http://localhost:3000/callback"
],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none"
}
```
### Client ID Metadata Documents Flow
The following diagram illustrates the complete flow when using Client ID Metadata Documents:
```mermaid theme={null}
sequenceDiagram
participant User
participant Client as MCP Client
participant Server as Authorization Server
participant Metadata as Metadata Endpoint<br/>(Client's HTTPS URL)
participant Resource as MCP Server
Note over Client,Metadata: Client hosts metadata at<br/>https://app.example.com/oauth/metadata.json
User->>Client: Initiates connection to MCP Server
Client->>Server: Authorization Request<br/>client_id=https://app.example.com/oauth/metadata.json<br/>redirect_uri=http://localhost:3000/callback
Server->>User: Authentication prompt
User->>Server: Provides credentials
Note over Server: Authenticates user
Note over Server: Detects URL-formatted client_id
Server->>Metadata: GET https://app.example.com/oauth/metadata.json
Metadata-->>Server: JSON Metadata Document<br/>{client_id, client_name, redirect_uris, ...}
Note over Server: Validates:<br/>1. client_id matches URL<br/>2. redirect_uri in allowed list<br/>3. Document structure valid<br/>4. (Optional) Domain allowed via trust policy
alt Validation Success
Server->>User: Display consent page with client_name
User->>Server: Approves access
Server->>Client: Authorization code via redirect_uri
Client->>Server: Exchange code for token<br/>client_id=https://app.example.com/oauth/metadata.json
Server-->>Client: Access token
Client->>Resource: MCP requests with access token
Resource-->>Client: MCP responses
else Validation Failure
Server->>User: Error response<br/>error=invalid_client or invalid_request
end
Note over Server: Cache metadata for future requests<br/>(respecting HTTP cache headers)
```
### Advertising CIMD Support
Authorization servers advertise that they support clients using Client ID Metadata Documents by including the following property in their OAuth Authorization Server metadata:
```json theme={null}
{
"client_id_metadata_document_supported": true
}
```
MCP clients **SHOULD** check for this capability and **MAY** fall back to
[Dynamic Client Registration](#dynamic-client-registration)
or [pre-registration](#pre-registration) if unavailable.
## Pre-registration
MCP clients **SHOULD** support an option for static client credentials such as those supplied by a pre-registration flow. This could be:
1. Hardcode a client ID (and, if applicable, client credentials) specifically for the MCP client to use when
interacting with that authorization server, or
2. Present a UI to users that allows them to enter these details, after registering an
OAuth client themselves (e.g., through a configuration interface hosted by the
server).
## Dynamic Client Registration
<Warning>
Dynamic Client Registration is deprecated. New implementations should use
[Client ID Metadata Documents](#client-id-metadata-documents) instead. This
option remains available for backwards compatibility with authorization
servers that do not support Client ID Metadata Documents.
</Warning>
MCP clients and authorization servers **MAY** support the
OAuth 2.0 Dynamic Client Registration Protocol [RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)
to allow MCP clients to obtain OAuth client IDs without user interaction.
This option is included for backwards compatibility with earlier versions of the MCP authorization spec.
### Application Type and Redirect URI Constraints
When authorization servers support OpenID Connect (OIDC) and
Dynamic Client Registration, they may enforce additional
constraints on redirect URIs based on the `application_type`
parameter as defined in
[OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html).
MCP clients **MUST** specify an appropriate `application_type`
during Dynamic Client Registration. Omitting it defaults to
`"web"` under OIDC, which can conflict with native-style redirect
URIs; non-OIDC servers safely ignore the parameter.
* **Native applications** (desktop applications, mobile apps,
CLI tools, and locally-hosted web applications accessed via
`localhost`) **SHOULD** use `application_type: "native"`
* **Web applications** (remote browser-based applications
served from a non-local host) **SHOULD** use
`application_type: "web"`
MCP clients **MUST** be prepared to handle registration
failures due to redirect URI constraints when authorization
servers implement OIDC. When a registration request is rejected,
clients **SHOULD** surface a meaningful error to the user or
developer. Clients **MAY** retry registration with an adjusted
`application_type` or with redirect URIs that conform to the
authorization server's requirements for the given application
type.
## Authorization Server Binding
Clients that use pre-registered credentials, or persist client credentials obtained via Dynamic Client
Registration, **MUST** associate those
credentials with the specific authorization server that issued them,
keyed by the authorization server's `issuer` identifier. When the
authorization server changes (detected via updated
[protected resource metadata](/specification/2026-07-28/basic/authorization/authorization-server-discovery#authorization-server-location)),
clients **MUST NOT** reuse client credentials
from a different authorization server and **MUST** re-register
with the new authorization server.
Pre-registered credentials are inherently specific to a particular
authorization server. If the authorization server indicated by
protected resource metadata no longer matches the one the
credentials were registered with, clients **SHOULD** surface an
error rather than silently attempting to use mismatched credentials.
Client IDs based on Client ID Metadata Documents are portable
across authorization servers, since they are self-hosted HTTPS URLs
resolved by the authorization server on demand. No re-registration
is needed when the authorization server changes.
specification/2026-07-28/basic/authorization/index First recorded · 422 lines, first recorded
# Authorization ## Introduction ### Purpose and Scope ### Protocol Requirements ### Standards Compliance ## Roles ## Overview ## Authorization Server Discovery ## Client Registration ## Scope Selection Strategy ## Authorization Flow Steps ### Authorization Response Validation ## Resource Parameter Implementation ### Canonical Server URI ## Access Token Usage ### Token Requirements ### Token Handling ## Refresh Tokens ## Error Handling ### Scope Challenge Handling #### Runtime Insufficient Scope Errors #### Step-Up Authorization Flow ## Security Considerations ## MCP Authorization Extensions
The first capture of this source. The page was already there, and this is what it said.
# Authorization
<div id="enable-section-numbers" />
## Introduction
### Purpose and Scope
The Model Context Protocol provides authorization capabilities at the transport level,
enabling MCP clients to make requests to restricted MCP servers on behalf of resource
owners. This specification defines the authorization flow for HTTP-based transports.
### Protocol Requirements
Authorization is **OPTIONAL** for MCP implementations. When supported:
* Implementations using an HTTP-based transport **SHOULD** conform to this specification.
* Implementations using an STDIO transport **SHOULD NOT** follow this specification, and
instead retrieve credentials from the environment.
* Implementations using alternative transports **MUST** follow established security best
practices for their protocol.
### Standards Compliance
This authorization mechanism is based on established specifications listed below, but
implements a selected subset of their features to ensure security and interoperability
while maintaining simplicity:
* OAuth 2.1 IETF DRAFT ([draft-ietf-oauth-v2-1-13](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13))
* OAuth 2.0 Bearer Token Usage
([RFC6750](https://datatracker.ietf.org/doc/html/rfc6750))
* OAuth 2.0 Authorization Server Metadata
([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* OAuth 2.0 Dynamic Client Registration Protocol
([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591))
* Resource Indicators for OAuth 2.0
([RFC8707](https://www.rfc-editor.org/rfc/rfc8707.html))
* OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728))
* OAuth 2.0 Authorization Server Issuer Identification ([RFC9207](https://datatracker.ietf.org/doc/html/rfc9207))
* OAuth Client ID Metadata Documents ([draft-ietf-oauth-client-id-metadata-document-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00))
* [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)
* OpenID Connect Dynamic Client Registration 1.0 ([OpenID Connect Registration](https://openid.net/specs/openid-connect-registration-1_0.html))
## Roles
A protected *MCP server* acts as an [OAuth 2.1 resource server](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
capable of accepting and responding to protected resource requests using access tokens.
An *MCP client* acts as an [OAuth 2.1 client](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#name-roles),
making protected resource requests on behalf of a resource owner.
The *authorization server* is responsible for interacting with the user (if necessary) and issuing access tokens for use at the MCP server.
The implementation details of the authorization server are beyond the scope of this specification. It may be hosted with the
resource server or a separate entity. [Authorization Server Discovery](/specification/2026-07-28/basic/authorization/authorization-server-discovery)
specifies how an MCP server indicates the location of its corresponding authorization server to a client.
## Overview
1. Authorization servers **MUST** implement OAuth 2.1 with appropriate security
measures for both confidential and public clients.
2. Authorization servers and MCP clients **SHOULD** support [OAuth Client ID Metadata Documents](/specification/2026-07-28/basic/authorization/client-registration#client-id-metadata-documents)
([draft-ietf-oauth-client-id-metadata-document-00](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00)).
3. Authorization servers and MCP clients **MAY** support the OAuth 2.0 Dynamic Client Registration
Protocol ([RFC7591](https://datatracker.ietf.org/doc/html/rfc7591)). Note that
[Dynamic Client Registration](/specification/2026-07-28/basic/authorization/client-registration#dynamic-client-registration)
is deprecated and retained for backwards compatibility with authorization servers that do not support Client ID Metadata Documents.
4. MCP servers **MUST** implement OAuth 2.0 Protected Resource Metadata ([RFC9728](https://datatracker.ietf.org/doc/html/rfc9728)).
MCP clients **MUST** use OAuth 2.0 Protected Resource Metadata for [authorization server discovery](/specification/2026-07-28/basic/authorization/authorization-server-discovery).
5. MCP authorization servers **MUST** provide at least one of the following discovery mechanisms:
* OAuth 2.0 Authorization Server Metadata ([RFC8414](https://datatracker.ietf.org/doc/html/rfc8414))
* [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html)
MCP clients **MUST** support both [discovery mechanisms](/specification/2026-07-28/basic/authorization/authorization-server-discovery#authorization-server-metadata-discovery) to obtain the information required to interact with the authorization server.
## Authorization Server Discovery
MCP servers advertise their associated authorization servers through OAuth 2.0 Protected
Resource Metadata, and MCP clients determine authorization server endpoints and supported
capabilities through authorization server metadata discovery. Implementations **MUST**
follow the normative discovery requirements defined in
[Authorization Server Discovery](/specification/2026-07-28/basic/authorization/authorization-server-discovery).
## Client Registration
Before initiating the authorization flow, MCP clients **MUST** obtain a client ID through
one of three registration mechanisms: Client ID Metadata Documents, pre-registration, or
Dynamic Client Registration, following the requirements and selection priority defined in
[Client Registration](/specification/2026-07-28/basic/authorization/client-registration).
## Scope Selection Strategy
MCP servers **SHOULD** include a `scope` parameter in the `WWW-Authenticate` header as defined in
[RFC 6750 Section 3](https://datatracker.ietf.org/doc/html/rfc6750#section-3)
to indicate the scopes required for accessing the resource. This provides clients with immediate
guidance on the appropriate scopes to request during authorization,
following the principle of least privilege and preventing clients from requesting excessive permissions.
The scopes included in the `WWW-Authenticate` challenge **MAY** match `scopes_supported`, be a subset
or superset of it, or an alternative collection that is neither a strict subset nor
superset. Clients **MUST NOT** assume any particular set relationship between the challenged
scope set and `scopes_supported`. Clients **MUST** treat the scopes provided in the
challenge as authoritative for the current operation. These scopes are required to
satisfy the current request. When re-authorizing, clients **SHOULD** include these scopes
alongside any previously granted scopes to avoid losing permissions needed for other operations
(see [Step-Up Authorization Flow](#step-up-authorization-flow)). Servers **SHOULD** strive for
consistency in how they construct scope sets but they are not required to surface every dynamically
issued scope through `scopes_supported`.
Example 401 response with scope guidance:
```http theme={null}
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
```
When implementing authorization flows, MCP clients **SHOULD** follow the principle of least privilege by requesting
only the scopes necessary for their intended operations. During the initial authorization handshake, MCP clients
**SHOULD** follow this priority order for scope selection:
1. **Use `scope` parameter** from the initial `WWW-Authenticate` header in the 401 response, if provided
2. **If `scope` is not available**, use all scopes defined in `scopes_supported` from the Protected Resource Metadata document, omitting the `scope` parameter if `scopes_supported` is undefined.
The `scopes_supported` field is intended to represent the minimal set of scopes necessary
for basic functionality (see [Scope Minimization](/docs/2026-07-28/tutorials/security/security_best_practices#scope-minimization)),
with additional scopes requested incrementally through the step-up authorization flow steps
described in the [Scope Challenge Handling](#scope-challenge-handling) section.
## Authorization Flow Steps
The registration step shown in the flow uses one of the mechanisms defined in
[Client Registration](/specification/2026-07-28/basic/authorization/client-registration).
The complete Authorization flow proceeds as follows:
```mermaid theme={null}
sequenceDiagram
participant B as User-Agent (Browser)
participant C as Client
participant M as MCP Server (Resource Server)
participant A as Authorization Server
C->>M: MCP request without token
M->>C: HTTP 401 Unauthorized with WWW-Authenticate header
Note over C: Extract resource_metadata URL from WWW-Authenticate
C->>M: Request Protected Resource Metadata
M->>C: Return metadata
Note over C: Parse metadata and extract authorization server(s)<br/>Client determines AS to use
C->>A: GET Authorization server metadata endpoint
Note over C,A: Try OAuth 2.0 and OpenID Connect<br/>discovery endpoints in priority order
A-->>C: Authorization server metadata
alt Client ID Metadata Documents
Note over C: Client uses HTTPS URL as client_id
Note over A: Server detects URL-formatted client_id
A->>C: Fetch metadata from client_id URL
C-->>A: JSON metadata document
Note over A: Validate metadata and redirect_uris
else Dynamic client registration
C->>A: POST /register
A->>C: Client Credentials
else Pre-registered client
Note over C: Use existing client_id
end
Note over C: Generate PKCE parameters<br/>Include resource parameter<br/>Apply scope selection strategy<br/>Record expected issuer
C->>B: Open browser with authorization URL + code_challenge + resource
B->>A: Authorization request with resource parameter
Note over A: User authorizes
A->>B: Redirect to callback with authorization code + iss
B->>C: Authorization code callback
Note over C: Validate iss against recorded issuer (RFC 9207)
C->>A: Token request + code_verifier + resource
A->>C: Access token (+ refresh token)
C->>M: MCP request with access token
M-->>C: MCP response
Note over C,M: MCP communication continues with valid token
```
### Authorization Response Validation
Before redirecting the user-agent, the client **MUST** record the `issuer` value from the selected authorization server's validated metadata document (see [Authorization Server Metadata Discovery](/specification/2026-07-28/basic/authorization/authorization-server-discovery#authorization-server-metadata-discovery)) and associate it with the same per-request record used to store the PKCE code verifier (and the `state` value, if used). The validation in this section depends on that recorded value being authentic; it provides no protection if the expected issuer was obtained from an unvalidated source.
MCP authorization servers **SHOULD** include the `iss` parameter in authorization responses, including error responses, as defined in [RFC9207 Section 2](https://datatracker.ietf.org/doc/html/rfc9207#section-2). Authorization servers that include the `iss` parameter **MUST** advertise this by setting `authorization_response_iss_parameter_supported` to `true` in their metadata ([RFC9207 Section 2.3](https://datatracker.ietf.org/doc/html/rfc9207#section-2.3)).
On receiving the authorization response, MCP clients **MUST** apply the validation in [RFC9207 Section 2.4](https://datatracker.ietf.org/doc/html/rfc9207#section-2.4) before transmitting the authorization code to any token endpoint:
| `authorization_response_iss_parameter_supported` | `iss` in response | Client action |
| ------------------------------------------------ | ----------------- | ------------------------------------------------------------------------------------------ |
| `true` | present | Compare to the recorded issuer using simple string comparison ([RFC3986 Section 6.2.1][1]) |
| `true` | absent | Reject the response |
| `false` or absent | present | Compare to the recorded issuer using simple string comparison ([RFC3986 Section 6.2.1][1]) |
| `false` or absent | absent | Proceed |
[1]: https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.1
The third row applies the local-policy provision in [RFC9207 Section 2.4](https://datatracker.ietf.org/doc/html/rfc9207#section-2.4): this specification compares a present `iss` against the recorded issuer regardless of metadata advertisement, to accommodate authorization servers that emit `iss` before updating their metadata.
A future revision of this specification is expected to upgrade authorization server inclusion of `iss` from **SHOULD** to **MUST**. Implementers are encouraged to emit and validate `iss` now to ease that transition; client rejection behavior on `iss` absence will continue to be keyed on `authorization_response_iss_parameter_supported` until that revision defines the upgrade path.
After decoding the `iss` value from the `application/x-www-form-urlencoded` response per [RFC 9207 Section 2.4](https://datatracker.ietf.org/doc/html/rfc9207#section-2.4), clients **MUST NOT** apply scheme or host case folding, default-port elision, trailing-slash, or percent-encoding normalization ([RFC 3986 Sections 6.2.2-6.2.3](https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2)) before comparison.
This validation applies equally to error responses - on mismatch the client **MUST NOT** act on or display `error`, `error_description`, or `error_uri`.
## Resource Parameter Implementation
MCP clients **MUST** implement Resource Indicators for OAuth 2.0 as defined in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html)
to explicitly specify the target resource for which the token is being requested. The `resource` parameter:
1. **MUST** be included in both authorization requests and token requests.
2. **MUST** identify the MCP server that the client intends to use the token with.
3. **MUST** use the canonical URI of the MCP server as defined in [RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#name-access-token-request).
### Canonical Server URI
For the purposes of this specification, the canonical URI of an MCP server is defined as the resource identifier as specified in
[RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#section-2) and aligns with the `resource` parameter in
[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728).
MCP clients **SHOULD** provide the most specific URI that they can for the MCP server they intend to access, following the guidance in [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707). While the canonical form uses lowercase scheme and host components, implementations **SHOULD** accept uppercase scheme and host components for robustness and interoperability.
Examples of valid canonical URIs:
* `https://mcp.example.com/mcp`
* `https://mcp.example.com`
* `https://mcp.example.com:8443`
* `https://mcp.example.com/server/mcp` (when path component is necessary to identify individual MCP server)
Examples of invalid canonical URIs:
* `mcp.example.com` (missing scheme)
* `https://mcp.example.com#fragment` (contains fragment)
> **Note:** While both `https://mcp.example.com/` (with trailing slash) and `https://mcp.example.com` (without trailing slash) are technically valid absolute URIs according to [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986), implementations **SHOULD** consistently use the form without the trailing slash for better interoperability unless the trailing slash is semantically significant for the specific resource.
For example, if accessing an MCP server at `https://mcp.example.com`, the authorization request would include:
```
&resource=https%3A%2F%2Fmcp.example.com
```
MCP clients **MUST** send this parameter regardless of whether authorization servers support it.
## Access Token Usage
### Token Requirements
Access token handling when making requests to MCP servers **MUST** conform to the requirements defined in
[OAuth 2.1 Section 5 "Resource Requests"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5).
Specifically:
1. MCP client **MUST** use the Authorization request header field defined in
[OAuth 2.1 Section 5.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.1.1):
```
Authorization: Bearer <access-token>
```
Note that authorization **MUST** be included in every HTTP request from client to server.
2. Access tokens **MUST NOT** be included in the URI query string
Example request:
```http theme={null}
GET /mcp HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```
### Token Handling
MCP servers, acting in their role as an OAuth 2.1 resource server, **MUST** validate access tokens as described in
[OAuth 2.1 Section 5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.2).
MCP servers **MUST** validate that access tokens were issued specifically for them as the intended audience,
according to [RFC 8707 Section 2](https://www.rfc-editor.org/rfc/rfc8707.html#section-2).
If validation fails, servers **MUST** respond according to
[OAuth 2.1 Section 5.3](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-5.3)
error handling requirements. Invalid or expired tokens **MUST** receive a HTTP 401
response.
MCP clients **MUST NOT** send tokens to the MCP server other than ones issued by the MCP server's authorization server.
MCP servers **MUST** only accept tokens that are valid for use with their
own resources.
MCP servers **MUST NOT** accept or transit any other tokens.
## Refresh Tokens
This section provides guidance for MCP Clients and MCP Servers when handling or issuing
refresh tokens for both OAuth and OpenID Connect.
Cut at 300 lines. The page has the rest.
specification/2026-07-28/basic/authorization/security-considerations First recorded · 128 lines, first recorded
# Authorization Security Considerations ## Token Audience Binding and Validation ## Token Theft ## Communication Security ## Authorization Code Protection ## Mix-Up Attacks ## Open Redirection ## Client ID Metadata Document Security ### Authorization Server Abuse Protection ### Localhost Redirect URI Risks ### Trust Policies ## Confused Deputy Problem ## Access Token Privilege Restriction
The first capture of this source. The page was already there, and this is what it said.
# Authorization Security Considerations <div id="enable-section-numbers" /> This document outlines security requirements that implementers **MUST** consider when building MCP clients and servers. Additionally, implementors **MUST** follow OAuth 2.1 security best practices as outlined in [OAuth 2.1 Section 7. "Security Considerations"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#name-security-considerations). ## Token Audience Binding and Validation [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html) Resource Indicators provide critical security benefits by binding tokens to their intended audiences **when the Authorization Server supports the capability**. To enable current and future adoption: * MCP clients **MUST** include the `resource` parameter in authorization and token requests as specified in the [Resource Parameter Implementation](/specification/2026-07-28/basic/authorization#resource-parameter-implementation) section * MCP servers **MUST** validate that tokens presented to them were specifically issued for their use The [Security Best Practices document](/docs/2026-07-28/tutorials/security/security_best_practices#token-passthrough) outlines why token audience validation is crucial and why token passthrough is explicitly forbidden. ## Token Theft Attackers who obtain tokens stored by the client, or tokens cached or logged on the server can access protected resources with requests that appear legitimate to resource servers. Clients and servers **MUST** implement secure token storage and follow OAuth best practices, as outlined in [OAuth 2.1, Section 7.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.1). Authorization servers **SHOULD** issue short-lived access tokens to reduce the impact of leaked tokens. For public clients, authorization servers **MUST** rotate refresh tokens as described in [OAuth 2.1 Section 4.3.1 "Token Endpoint Extension"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-4.3.1). ## Communication Security Implementations **MUST** follow [OAuth 2.1 Section 1.5 "Communication Security"](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-1.5). Specifically: 1. All authorization server endpoints **MUST** be served over HTTPS. 2. All redirect URIs **MUST** be either `localhost` or use HTTPS. ## Authorization Code Protection An attacker who has gained access to an authorization code contained in an authorization response can try to redeem the authorization code for an access token or otherwise make use of the authorization code. (Further described in [OAuth 2.1 Section 7.5](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.5)) To mitigate this, MCP clients **MUST** implement PKCE according to [OAuth 2.1 Section 7.5.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.5.2) and **MUST** verify PKCE support before proceeding with authorization. PKCE helps prevent authorization code interception and injection attacks by requiring clients to create a secret verifier-challenge pair, ensuring that only the original requestor can exchange an authorization code for tokens. MCP clients **MUST** use the `S256` code challenge method when technically capable, as required by [OAuth 2.1 Section 4.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-4.1.1). Since OAuth 2.1 and PKCE specifications do not define a mechanism for clients to discover PKCE support, MCP clients **MUST** rely on authorization server metadata to verify this capability: * **OAuth 2.0 Authorization Server Metadata**: If `code_challenge_methods_supported` is absent, the authorization server does not support PKCE and MCP clients **MUST** refuse to proceed. * **OpenID Connect Discovery 1.0**: While the [OpenID Provider Metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) does not define `code_challenge_methods_supported`, this field is commonly included by OpenID providers. MCP clients **MUST** verify the presence of `code_challenge_methods_supported` in the provider metadata response. If the field is absent, MCP clients **MUST** refuse to proceed. Authorization servers providing OpenID Connect Discovery 1.0 **MUST** include `code_challenge_methods_supported` in their metadata to ensure MCP compatibility. ## Mix-Up Attacks An attacker that controls one of the authorization servers an MCP client interacts with may attempt to have the client send it an authorization code or token issued by a different, honest authorization server (a mix-up attack, described in [RFC9207 Section 1](https://datatracker.ietf.org/doc/html/rfc9207#section-1)). [Authorization Response Validation](/specification/2026-07-28/basic/authorization#authorization-response-validation) specifies the required mitigation. ## Open Redirection An attacker may craft malicious redirect URIs to direct users to phishing sites. MCP clients **MUST** have redirect URIs registered with the authorization server. Authorization servers **MUST** validate exact redirect URIs against pre-registered values to prevent redirection attacks. MCP clients **SHOULD** use and verify state parameters in the authorization code flow and discard any results that do not include or have a mismatch with the original state. Authorization servers **MUST** take precautions to prevent redirecting user agents to untrusted URI's, following suggestions laid out in [OAuth 2.1 Section 7.12.2](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13#section-7.12.2) Authorization servers **SHOULD** only automatically redirect the user agent if it trusts the redirection URI. If the URI is not trusted, the authorization server MAY inform the user and rely on the user to make the correct decision. ## Client ID Metadata Document Security When implementing [Client ID Metadata Documents](/specification/2026-07-28/basic/authorization/client-registration#client-id-metadata-documents), authorization servers **MUST** consider the security implications detailed in [OAuth Client ID Metadata Document, Section 6](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00#name-security-considerations). Key considerations include: ### Authorization Server Abuse Protection Authorization servers fetching metadata documents **SHOULD** consider [Server-Side Request Forgery (SSRF)](https://developer.mozilla.org/docs/Web/Security/Attacks/SSRF) risks, as described in [OAuth Client ID Metadata Document: Server Side Request Forgery (SSRF) Attacks](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-client-id-metadata-document-00#name-server-side-request-forgery). ### Localhost Redirect URI Risks Client ID Metadata Documents cannot prevent `localhost` URL impersonation by themselves. Authorization servers: * **SHOULD** display additional warnings for `localhost`-only redirect URIs * **MAY** require additional attestation mechanisms for enhanced security * **MUST** clearly display the redirect URI hostname during authorization ### Trust Policies Authorization servers **MAY** implement domain-based trust policies for accepting Client ID Metadata Documents, as described in [Section 6.4](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.4) and [Section 6.8](https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-6.8) of the Client ID Metadata Document specification. ## Confused Deputy Problem Attackers can exploit MCP servers acting as intermediaries to third-party APIs, leading to [confused deputy vulnerabilities](/docs/2026-07-28/tutorials/security/security_best_practices#confused-deputy-problem). By using stolen authorization codes, they can obtain access tokens without user consent. MCP proxy servers using static client IDs **MUST** obtain user consent for each [dynamically registered client](/specification/2026-07-28/basic/authorization/client-registration#dynamic-client-registration) before forwarding to third-party authorization servers (which may require additional consent). ## Access Token Privilege Restriction An attacker can gain unauthorized access or otherwise compromise an MCP server if the server accepts tokens issued for other resources. MCP servers **MUST** validate access tokens before processing the request, ensuring the access token is issued specifically for the MCP server, and take all necessary steps to ensure no data is returned to unauthorized parties. A MCP server **MUST** follow the guidelines in [OAuth 2.1 - Section 5.2](https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-13.html#section-5.2) to validate inbound tokens. MCP servers **MUST** only accept tokens specifically intended for themselves and **MUST** reject tokens that do not include them in the audience claim or otherwise verify that they are the intended recipient of the token. See the [Security Best Practices Token Passthrough section](/docs/2026-07-28/tutorials/security/security_best_practices#token-passthrough) for details. If the MCP server makes requests to upstream APIs, it may act as an OAuth client to them. The access token used at the upstream API is a separate token, issued by the upstream authorization server. The MCP server **MUST NOT** pass through the token it received from the MCP client. MCP clients **MUST** implement and use the `resource` parameter as defined in [RFC 8707 - Resource Indicators for OAuth 2.0](https://www.rfc-editor.org/rfc/rfc8707.html) to explicitly specify the target resource for which the token is being requested. This requirement aligns with the recommendation in [RFC 9728 Section 7.4](https://datatracker.ietf.org/doc/html/rfc9728#section-7.4). This ensures that access tokens are bound to their intended resources and cannot be misused across different services.
specification/2026-07-28/basic/index First recorded · 497 lines, first recorded
# Overview ## Messages ### Requests ### Responses #### Result Responses ##### ResultType #### Error Responses #### Error Codes ### Notifications ### Message Patterns ## Statelessness ## Auth ## Schema ## JSON Schema Usage ### Schema Dialect ### Example Usage #### Default dialect (2020-12): #### Explicit dialect (draft-07): ### Implementation Requirements ### Schema Validation ### `$ref` Resolution ### Composition-Keyword Resource Use ## General fields ### `_meta` ### `icons`
The first capture of this source. The page was already there, and this is what it said.
# Overview
<div id="enable-section-numbers" />
The Model Context Protocol consists of several key components that work together:
* **Base Protocol**: Core JSON-RPC message types
* **Versioning and Compatibility**: Protocol version negotiation, extension negotiation, and interoperability with earlier protocol revisions
* **Message Patterns**: Messaging patterns supported by the core protocol including request and response, multi round-trip requests (MRTR), and subscribe and notify
* **Authorization**: Authentication and authorization framework for HTTP-based transports
* **Server Features**: Resources, prompts, and tools exposed by servers
* **Client Features**: Elicitation, sampling and root directory lists provided by clients
* **Utilities**: Cross-cutting concerns like logging and argument completion
All implementations **MUST** support the base protocol, versioning,
and the message patterns. Other components **MAY** be implemented based on the specific needs of the
application.
These protocol layers establish clear separation of concerns while enabling rich
interactions between clients and servers. The modular design allows implementations to
support exactly the features they need.
## Messages
All messages between MCP clients and servers **MUST** follow the
[JSON-RPC 2.0](https://www.jsonrpc.org/specification) specification. The protocol defines
these types of messages:
### Requests
[Requests](/specification/2026-07-28/schema#jsonrpcrequest) are sent from the client to the server, to initiate an operation.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Requests **MUST** include a string or integer ID.
* Unlike base JSON-RPC, the ID **MUST NOT** be `null`.
* The request ID **MUST NOT** match the ID of any other request the sender has issued and
not yet received a response for.
### Responses
Responses are sent in reply to requests, containing either the result or error of the operation.
#### Result Responses
[Result responses](/specification/2026-07-28/schema#jsonrpcresultresponse) are sent when the operation completes successfully.
```typescript theme={null}
{
jsonrpc: "2.0";
id: string | number;
result: {
resultType: string;
[key: string]: unknown;
};
}
```
* Result responses **MUST** include the same ID as the request they correspond to.
* Result responses **MUST** include a `result` field.
* The `result` **MAY** follow any JSON object structure.
* The `result` **MUST** include a `resultType` field to indicate the type of the result.
##### ResultType
The `resultType` field in a result indicates the type of the result being returned. MCP supports polymorphic result types,
allowing servers to return different structures based on the outcome of the request. The `resultType` field is a string that clients
can use to determine how to parse and handle the `result` object.
* A `resultType` of `"complete"` indicates the request completed successfully and the result contains the final content.
* A `resultType` of `"input_required"` indicates the request is incomplete and more information is needed to process the request. The result contains an [`InputRequiredResult`](/specification/2026-07-28/basic/patterns/mrtr#inputrequiredresult) object with additional information needed.
* Extensions **MAY** add additional `ResultType` values. The set of supported `ResultType` values **MUST** be created from the set defined in the core protocol and include any additional values of supported extensions that are advertised via capabilities.
* A `resultType` of any value unrecognized by the client **MUST** be considered invalid.
* For backward compatibility with servers implementing earlier protocol versions, which do not include `resultType`, clients **MUST** treat an absent `resultType` as `"complete"`.
#### Error Responses
[Error responses](/specification/2026-07-28/schema#jsonrpcerrorresponse) are sent when the operation fails or encounters an error.
```typescript theme={null}
{
jsonrpc: "2.0";
id?: string | number;
error: {
code: number;
message: string;
data?: unknown;
}
}
```
* Error responses **MUST** include the same ID as the request they correspond to (except in error cases where the ID could not be read due a malformed request).
* Error responses **MUST** include an `error` field with a `code` and `message`.
* Error codes **MUST** be integers.
* Error responses **MAY** include a `data` member with additional information of any type, such
as nested errors.
#### Error Codes
MCP uses the standard JSON-RPC 2.0 error codes (`-32700`, `-32600` to `-32603`)
for general protocol failures.
JSON-RPC 2.0 reserves the range `-32000` to `-32099` for implementation-defined
server errors. MCP partitions this range as follows:
* **`-32000` to `-32019` — legacy.** Codes in this sub-range were allocated by
implementations before this policy was introduced. New codes **MUST NOT** be
allocated in this sub-range, and new implementations **SHOULD NOT** use codes
from this sub-range at all. Apart from `-32002` (see below), receivers
**MUST NOT** assume any specific meaning for these codes.
* **`-32020` to `-32099` — reserved for the MCP specification.** Error codes
in this sub-range are defined exclusively by the MCP specification and
recorded in the [schema](/specification/2026-07-28/schema). Implementations
**MUST NOT** emit any code from this sub-range that is not defined by this
specification and **MUST** use defined codes only with their specified
meanings.
MCP defines the following error codes:
| Code | Name |
| -------- | ---------------------------------------------------------------------------------------------------------- |
| `-32020` | [`HeaderMismatch`](/specification/2026-07-28/schema#headermismatcherror) |
| `-32021` | [`MissingRequiredClientCapability`](/specification/2026-07-28/schema#missingrequiredclientcapabilityerror) |
| `-32022` | [`UnsupportedProtocolVersion`](/specification/2026-07-28/schema#unsupportedprotocolversionerror) |
Codes defined by earlier protocol versions remain reserved and will not be
reused. Implementations of this protocol version **MUST NOT** emit these codes:
* `-32002` — resource not found (2025-11-25 and earlier; replaced by `-32602`).
Clients [**SHOULD** still
accept `-32002`](/specification/2026-07-28/server/resources#error-handling) from
servers implementing earlier versions.
* `-32042` — URL elicitation required (2025-11-25 only).
Errors that are purely local to an implementation (for example, a request
timeout raised inside an SDK) are not currently assigned codes by this
specification. Implementations surfacing local errors in JSON-RPC-shaped
structures should ensure they cannot be mistaken for errors received from the
peer. Future versions of the specification may define standard codes for
common local error conditions in the reserved sub-range.
New error codes for purposes not defined by this specification **SHOULD** be
allocated outside the JSON-RPC reserved range (`-32768` to `-32000`); the
remainder of the integer space is available for application-defined errors.
### Notifications
[Notifications](/specification/2026-07-28/schema#jsonrpcnotification) are sent from the client to the server or vice versa, as a one-way message.
The receiver **MUST NOT** send a response.
```typescript theme={null}
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}
```
* Notifications **MUST NOT** include an ID.
### Message Patterns
The Model Context Protocol (MCP) supports several [Message Patterns](/specification/2026-07-28/basic/patterns) that define how clients and servers interact:
1. **[Request and Response](/specification/2026-07-28/basic/patterns#request-and-response)**: A client sends a request to the server, and the server responds with a result or error.
2. **[Multi Round-Trip Requests (MRTR)](/specification/2026-07-28/basic/patterns#multi-round-trip-requests)**: A server requires additional client input (sampling, elicitation, or roots) to complete a request.
3. **[Subscribe and Notify](/specification/2026-07-28/basic/patterns#subscribe-and-notify)**: A client subscribes to a stream of notifications from the server, which are sent as they occur.
## Statelessness
The Model Context Protocol (MCP) is a **stateless protocol**: all the
information needed to process a request is contained in the request itself.
A server processes each request independently; no state should be inferred
from previous requests, even those on the same connection or stream.
Specifically:
* Servers **MUST NOT** rely on prior requests over the same connection to
establish context (e.g., capabilities, protocol version, client identity).
Every request supplies this metadata in its [`_meta`](#_meta) field.
* Servers **SHOULD** be prepared to handle requests associated with multiple
tasks, threads, or conversations.
* Servers **SHOULD NOT** require that a client reuse the same connection or process to
perform related operations.
* Clients **SHOULD NOT** use an individual task, thread, or conversation as the
lifetime boundary for the stdio process.
* State that needs to span multiple requests (e.g., long-running tasks,
application-level handles) **MUST** be referenced by an explicit identifier
the client passes on each request.
<Note>
This implies that an open connection, such as a STDIO process, is not a
conversation or session: clients may interleave unrelated requests on the same
transport, and a server must not treat connection or process identity as a
proxy for conversation or session continuity.
</Note>
Long-lived requests like
[`subscriptions/listen`](/specification/2026-07-28/basic/patterns/subscriptions)
remain request/response; the response is just an open stream of notifications.
Their state is scoped to the request itself, not to the connection underneath.
<Info>
For a walkthrough of how the per-request model maps to SDK code, see the
[Architecture guide](/docs/2026-07-28/learn/architecture#example).
</Info>
## Auth
MCP provides an [Authorization](/specification/2026-07-28/basic/authorization) framework for use with HTTP.
Implementations using an HTTP-based transport **SHOULD** conform to this specification,
whereas implementations using STDIO transport **SHOULD NOT** follow this specification,
and instead retrieve credentials from the environment.
Additionally, clients and servers **MAY** negotiate their own custom authentication and
authorization strategies.
For further discussions and contributions to the evolution of MCP's auth mechanisms, join
us in
[GitHub Discussions](https://github.com/modelcontextprotocol/specification/discussions)
to help shape the future of the protocol!
## Schema
The full specification of the protocol is defined as a
[TypeScript schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2026-07-28/schema.ts).
This is the source of truth for all protocol messages and structures.
There is also a
[JSON Schema](https://github.com/modelcontextprotocol/specification/blob/main/schema/2026-07-28/schema.json),
which is automatically generated from the TypeScript source of truth, for use with
various automated tooling.
## JSON Schema Usage
The Model Context Protocol uses JSON Schema for validation throughout the protocol. This section clarifies how JSON Schema should be used within MCP messages.
### Schema Dialect
MCP supports JSON Schema with the following rules:
1. **Default dialect**: When a schema does not include a `$schema` field, it defaults to [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/schema)
2. **Explicit dialect**: Schemas MAY include a `$schema` field to specify a different dialect
3. **Supported dialects**: Implementations MUST support at least 2020-12 and SHOULD document which additional dialects they support
4. **Recommendation**: Implementors are RECOMMENDED to use JSON Schema 2020-12.
### Example Usage
#### Default dialect (2020-12):
```json theme={null}
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}
```
#### Explicit dialect (draft-07):
```json theme={null}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["name"]
}
```
### Implementation Requirements
* Clients and servers **MUST** support JSON Schema 2020-12 for schemas without an explicit `$schema` field
* Clients and servers **MUST** validate schemas according to their declared or default dialect. They **MUST** handle unsupported dialects gracefully by returning an appropriate error indicating the dialect is not supported.
* Clients and servers **SHOULD** document which schema dialects they support
### Schema Validation
* Schemas **MUST** be valid according to their declared or default dialect
### `$ref` Resolution
JSON Schema 2020-12 permits `$ref` to point at an absolute URI. Implementations **MUST NOT**
automatically dereference `$ref` values that resolve to a network URI.
Cut at 300 lines. The page has the rest.
specification/2026-07-28/basic/patterns/cancellation First recorded · 120 lines, first recorded
# Cancellation ## Cancellation Flow ## Transport-Specific Cancellation ## Timeouts ## Behavior Requirements ## Timing Considerations ## Implementation Notes ## Error Handling
The first capture of this source. The page was already there, and this is what it said.
# Cancellation
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional cancellation of in-progress requests
through notification messages. A client **SHOULD** send a cancellation notification
to indicate that a request it previously issued should be terminated.
A server **MUST** send `notifications/cancelled`
referencing a `subscriptions/listen` request ID when it tears down that subscription
stream (see [Subscriptions][subscriptions]). Servers **MUST NOT** send
`notifications/cancelled` for any other purpose.
## Cancellation Flow
When a client wants to cancel an in-progress request, it sends a `notifications/cancelled`
notification containing:
* The ID of the request to cancel
* An optional reason string that can be logged or displayed
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/cancelled",
"params": {
"requestId": "123",
"reason": "User requested cancellation"
}
}
```
## Transport-Specific Cancellation
How a client signals cancellation depends on the transport:
* **Streamable HTTP**: Closing the SSE response stream is the cancellation signal.
The server **MUST** treat a client disconnect as cancellation of that request. No
`notifications/cancelled` message is required or expected.
* **stdio**: There is no per-request stream to close. The client **MUST** send a
`notifications/cancelled` notification referencing the request ID.
## Timeouts
Implementations **SHOULD** establish timeouts for all sent requests, to prevent hung
connections and resource exhaustion. When the request has not received a success or error
response within the timeout period, the sender **SHOULD** cancel the request and stop
waiting for a response. As described in
[Transport-Specific Cancellation](#transport-specific-cancellation), this means:
* **Streamable HTTP**: closing the response stream for the request, which constitutes
cancellation.
* **stdio**: sending a `notifications/cancelled` notification referencing the request ID.
SDKs and other middleware **SHOULD** allow these timeouts to be configured on a
per-request basis.
Implementations **MAY** choose to reset the timeout clock when receiving a
[progress notification](/specification/2026-07-28/basic/patterns/progress) corresponding to
the request, as this implies that work is actually happening. However, implementations
**SHOULD** always enforce a maximum timeout, regardless of progress notifications, to
limit the impact of a misbehaving client or server.
## Behavior Requirements
1. Cancellation notifications **MUST** only reference requests that:
* Were previously issued by the client
* Are believed to still be in-progress
2. Server-sent cancellation notifications **MUST** reference a
`subscriptions/listen` request, to terminate that subscription stream
3. Servers receiving cancellation notifications **SHOULD**:
* Stop processing the cancelled request
* Free associated resources
* Not send a response for the cancelled request
4. Servers **MAY** ignore cancellation notifications if:
* The referenced request is unknown
* Processing has already completed
* The request cannot be cancelled
5. The client **SHOULD** ignore any response to the cancelled request that arrives
afterward
## Timing Considerations
Due to network latency, cancellation notifications may arrive after request processing
has completed, and potentially after a response has already been sent.
Both parties **MUST** handle these race conditions gracefully:
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: Request (ID: 123)
Note over Server: Processing starts
Client--)Server: notifications/cancelled (ID: 123)
alt
Note over Server: Processing may have<br/>completed before<br/>cancellation arrives
else If not completed
Note over Server: Stop processing
end
```
## Implementation Notes
* Both parties **SHOULD** log cancellation reasons for debugging
* Application UIs **SHOULD** indicate when cancellation is requested
## Error Handling
Invalid cancellation notifications **SHOULD** be ignored:
* Unknown request IDs
* Already completed requests
* Malformed notifications
This maintains the "fire and forget" nature of notifications while allowing for race
conditions in asynchronous communication.
[subscriptions]: /specification/2026-07-28/basic/patterns/subscriptions
specification/2026-07-28/basic/patterns/index First recorded · 83 lines, first recorded
# Overview ## Request and Response ## Multi Round-Trip Requests ## Subscribe and Notify ## Adding Patterns
The first capture of this source. The page was already there, and this is what it said.
# Overview
<div id="enable-section-numbers" />
This page defines the message patterns of the core protocol: the ways a
client and server compose JSON-RPC
[requests, responses, and notifications](/specification/2026-07-28/basic/index#messages)
into interactions. Every
[transport](/specification/2026-07-28/basic/transports) carries all of these
patterns; transports differ only in how messages are framed and delivered.
Every interaction begins with the client:
* The **client** sends JSON-RPC *requests* and *notifications*.
* The **server** answers each request with a JSON-RPC *response* (a result
or error), optionally preceded by *notifications* scoped to that request.
Servers **MUST NOT** initiate JSON-RPC requests, and clients do not send
JSON-RPC responses.
## Request and Response
The client sends a request; the server answers it with a result or an error.
While the request is in flight, the server **MAY** send notifications scoped
to it, such as
[`notifications/progress`](/specification/2026-07-28/basic/patterns/progress)
and [`notifications/message`](/specification/2026-07-28/server/utilities/logging).
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: request
Server-->>Client: notifications/progress (optional)
Server-->>Client: response
```
## Multi Round-Trip Requests
When a server needs client input (sampling, elicitation, or roots) to
complete a request, it answers with an
[`InputRequiredResult`](/specification/2026-07-28/basic/patterns/mrtr#inputrequiredresult)
and the client retries the request with the matching `inputResponses`. See
[Multi Round-Trip Requests](/specification/2026-07-28/basic/patterns/mrtr).
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: request (id: 1)
Server-->>Client: InputRequiredResult (inputRequests)
Client->>Server: request (id: 2, original params + inputResponses)
Server-->>Client: response
```
## Subscribe and Notify
To receive change notifications (list changes, resource updates), the client
sends a
[`subscriptions/listen`](/specification/2026-07-28/basic/patterns/subscriptions)
request; the reply is a long-lived stream of the requested notification
types. Stream state is scoped to the request: if the underlying channel is
lost, the client re-issues the request.
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Client->>Server: subscriptions/listen
Server-->>Client: notifications/subscriptions/acknowledged
note over Client,Server: Stream stays open
Server-->>Client: notifications/* (tagged with subscriptionId)
```
## Adding Patterns
All core protocol features are built from these patterns. A protocol
revision that adds a pattern defines it on this page. Transports carry new
patterns without changes, because patterns are expressed entirely in terms
of requests, responses, and notifications.
specification/2026-07-28/basic/patterns/mrtr First recorded · 275 lines, first recorded
# Multi Round-Trip Requests ## Multi Round-Trip Requests ### Core Types #### InputRequests #### InputResponses #### InputRequiredResult ### Supported Requests ### Basic Workflow #### Server Requirements (Basic Workflow) #### Client Requirements (Basic Workflow) ### Error Handling ### Security Considerations
The first capture of this source. The page was already there, and this is what it said.
# Multi Round-Trip Requests
<div id="enable-section-numbers" />
<Note>
Multi Round-Trip Requests (MRTR) was introduced in this version of the MCP
specification. This replaces the previous approach of sending server-initiated
requests. Servers **MUST** send server-to-client requests (such as
`roots/list`, `sampling/createMessage`, or `elicitation/create`) using the
MRTR pattern. The previous pattern of server-initiated requests is no longer
supported. This is a breaking change.
</Note>
<Note>
For brevity, the request examples on this page omit the `_meta` request
metadata (`io.modelcontextprotocol/protocolVersion`,
`io.modelcontextprotocol/clientInfo`, and
`io.modelcontextprotocol/clientCapabilities`). Every request **MUST** include
the required `_meta` fields; see
[`_meta`](/specification/2026-07-28/basic/index#meta).
</Note>
## Multi Round-Trip Requests
The Model Context Protocol (MCP) defines several ways for servers to request additional information
from users during the processing of client requests (such as
`roots/list`, `sampling/createMessage`, or `elicitation/create`). The **multi round-trip requests** pattern
provides a standardized way to handle these server-requests without requiring a shared storage layer across
server instances or requiring stateful load balancing.
The high level flow functions as follows:
1. Client sends an initial request to the server with the parameters needed to perform the operation.
2. Server determines that additional information is required to fulfill the request and responds requesting more information.
3. Client gathers the requested information from the user or other sources, then retries the original request including the additional requested information.
4. Server determines it has sufficient information to complete the operation, and responds with the final result.
```mermaid theme={null}
sequenceDiagram
participant C as Client
participant S as Server
C->>S: client request (id: 1, request params)
note over S: Server needs more info <br/> to process request.
S-->>C: Request for additional input.
note over C: Client gathers input and <br/> retries initial request.
C->>S: client request (id: 2, request params, requested input)
note over S: Server has enough information <br/> to complete the request.
S-->>C: Result (id: 2, result)
```
### Core Types
This flow is implemented in MCP using the following Types.
#### InputRequests
An [`InputRequests`](/specification/2026-07-28/schema#inputrequests) object is a map of server-client requests.
Keys are server-assigned string identifiers;
values are request objects (e.g., [`ElicitRequest`](/specification/2026-07-28/schema#elicitrequest), [`CreateMessageRequest`](/specification/2026-07-28/schema#createmessagerequest), or [`ListRootsRequest`](/specification/2026-07-28/schema#listrootsrequest)).
```json theme={null}
{
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
}
},
"capital_of_france": {
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
}
```
#### InputResponses
An [`InputResponses`](/specification/2026-07-28/schema#inputresponses) object is a map of client responses to the server requests.
Keys correspond to the keys in the `InputRequests` map; values are the client's result for each request (e.g., [`ElicitResult`](/specification/2026-07-28/schema#elicitresult), [`CreateMessageResult`](/specification/2026-07-28/schema#createmessageresult), or [`ListRootsResult`](/specification/2026-07-28/schema#listrootsresult)).
```json theme={null}
{
"github_login": {
"action": "accept",
"content": {
"name": "octocat"
}
},
"capital_of_france": {
"role": "assistant",
"content": {
"type": "text",
"text": "The capital of France is Paris."
},
"model": "claude-3-sonnet-20240307",
"stopReason": "endTurn"
}
}
```
#### InputRequiredResult
An [`InputRequiredResult`](/specification/2026-07-28/schema#inputrequiredresult) is a type of [`Result`](/specification/2026-07-28/basic#responses),
indicating that additional input is needed before the request can be completed.
* `inputRequests` *(optional)*: An [`InputRequests`](/specification/2026-07-28/schema#inputrequests) map of server-initiated requests that the client must fulfill.
* `requestState` *(optional)*: An opaque string meaningful only to the server. Clients **MUST NOT** inspect, parse, modify, or make any assumptions about its contents.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "input_required",
"inputRequests": {
// Elicitation request.
"github_login": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Please provide your GitHub username",
"requestedSchema": {
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
}
},
// Sampling request.
"capital_of_france": {
"method": "sampling/createMessage",
"params": {
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "What is the capital of France?"
}
}
],
"modelPreferences": {
"hints": [{ "name": "claude-3-sonnet" }],
"intelligencePriority": 0.8,
"speedPriority": 0.5
},
"systemPrompt": "You are a helpful assistant.",
"maxTokens": 100
}
}
},
"requestState": "AEAD-protected blob"
}
}
```
### Supported Requests
Servers **MAY** send `InputRequiredResult` responses on the following client requests:
| Client Request | Supports InputRequiredResult |
| -------------------------------------------------------------------------------- | ---------------------------- |
| [`prompts/get`](/specification/2026-07-28/server/prompts#getting-a-prompt) | Yes |
| [`resources/read`](/specification/2026-07-28/server/resources#reading-resources) | Yes |
| [`tools/call`](/specification/2026-07-28/server/tools#calling-tools) | Yes |
Servers **MUST NOT** send `InputRequiredResult` responses on any other client requests.
### Basic Workflow
The basic workflow describes how a server can request additional input from the client as part of a client-server request.
In this example we use `tools/call` as the client request, but the same pattern applies to any of the supported requests listed above.
Notably, it allows servers to request additional information without maintaining any server-side state.
The server encodes any needed context into the `requestState` field, which the client echoes back on retry.
```mermaid theme={null}
sequenceDiagram
participant U as User
participant C as Client
participant S as Server
C->>S: tools/call (id: 1)
note over S: Server needs more info via Elicitation
S-->>C: InputRequiredResult (id: 1, ElicitRequest, requestState)
note over C,S: Initial Request Terminated
C->>U: Prompts user for input
U-->>C: Provides responses
note over C: Client retries tool call <br/> with inputResponses and requestState
C->>S: tools/call (id: 2, ElicitResult, requestState)
note over S: Server reconstitutes state<br/>Completes execution
S-->>C: Result (id: 2, ToolCallResult)
```
Note that the requests in each step are completely independent: the server processing the retry does not need any information beyond
what is directly present in the retry request.
#### Server Requirements (Basic Workflow)
1. Servers **MAY** respond to any [supported client request](#supported-requests) with an `InputRequiredResult`.
2. The `InputRequiredResult` **MAY** include an `inputRequests` field.
* `inputRequests` keys are server assigned identifiers and **MUST** be unique within the scope of the request.
* `inputRequests` values are request objects that **MUST** be one of [`ElicitRequest`](/specification/2026-07-28/schema#elicitrequest), [`CreateMessageRequest`](/specification/2026-07-28/schema#createmessagerequest), or [`ListRootsRequest`](/specification/2026-07-28/schema#listrootsrequest)
3. The `InputRequiredResult` **MAY** include a `requestState` field. If specified, this field is an opaque string meaningful only to the server. Servers are free to encode the state in any format (e.g. base64-encoded JSON, encrypted JWT, serialized binary).
4. If a client request contains a `requestState` field, servers **MUST** treat `requestState` as an attacker-controlled input. If `requestState` influences authorization, resource access, or business logic, servers **MUST** protect its integrity (e.g. HMAC or AEAD)
and **MUST** reject state that fails verification. Integrity protection **MAY** be omitted only when tampering can cause nothing worse than request failure.
5. To prevent replay, servers **SHOULD** include the following inside the integrity-protected `requestState` payload and verify each on receipt:
* the authenticated principal, rejecting state presented by a different principal.
* a short expiry (TTL), rejecting state presented after it lapses;
* an identifier for the originating request, e.g. the method name and a digest of its salient parameters, rejecting state presented on a request that does not match.
<Warning>
Note that these measures bound the replay window and prevent cross-user
and cross-request reuse, but do not by themselves guarantee single-use.
Servers for which a given `requestState` must be consumed at most once
(e.g., one-time redemptions) **MUST** enforce that invariant server-side.
</Warning>
6. Servers **MUST** include at least one of `inputRequests` or `requestState` in every `InputRequiredResult` response.
7. Servers **MUST NOT** send an `inputRequests` that the client has not declared support for in its capabilities. For example, if a client does not declare support for `elicitation`, the server **MUST NOT** include any `elicitation/create` requests in the `inputRequests` field.
8. Servers **MUST NOT** assume that clients will fulfill the `inputRequests` or retry the original request. Servers **MAY** choose to return an `InputRequiredResult` on multiple attempts at the same request if they want to repeatedly prompt the user for information until they have what they need to complete the request.
#### Client Requirements (Basic Workflow)
1. If a client receives an `InputRequiredResult` that contains the `inputRequests` field, the client **MUST** construct the requested
inputs before retrying the original request. If the `InputRequiredResult` does *not* contain the `inputRequests` field,
the client **MAY** retry the original request immediately.
2. If an `InputRequiredResult` contains the `requestState` field, the client **MUST** echo back the exact value of that field when retrying the original request.
Clients **MUST NOT** inspect, parse, modify, or make any assumptions about the `requestState` contents. If the `InputRequiredResult` does not contain a `requestState` field, the client **MUST NOT** include one in the retry.
3. The JSON-RPC `id` **MUST** be different between the initial request and the retry, as they are independent requests.
4. Both the `inputRequests` and `requestState` fields affect only the client's retry of the original request. They **MUST NOT** be used for any other request that the client may be sending in parallel.
### Error Handling
Servers **SHOULD** validate that the data provided by the client is a valid `InputResponses` object and that the information inside can be correctly parsed.
Protocol errors (malformed JSON, invalid schema, internal server errors) **SHOULD** return a JSON-RPC error response with an appropriate error code and message.
If additional, unexpected parameters are provided in the `InputResponses` object, the server **SHOULD** ignore any information it does not recognize or need.
If the client fails to send all the information requested in a previous `InputRequests`, and the missing information is necessary for the server to process the request,
the server **SHOULD** respond with a new `InputRequiredResult` requesting the missing information again, rather than returning an error.
### Security Considerations
Because `requestState` passes through the client, malicious or compromised clients could attempt to modify it to alter server behavior,
bypass authorization checks, or corrupt server logic. Servers **MUST** validate request state as described in the [server requirements](#server-requirements-basic-workflow) above.
specification/2026-07-28/basic/patterns/progress First recorded · 88 lines, first recorded
# Progress ## Progress Flow ## Behavior Requirements ## Implementation Notes
The first capture of this source. The page was already there, and this is what it said.
# Progress
<div id="enable-section-numbers" />
The Model Context Protocol (MCP) supports optional progress tracking for long-running
operations through notification messages. The server **MAY** send progress notifications
to report the status of requests the client has issued.
## Progress Flow
When a client wants to *receive* progress updates for a request, it includes a
`progressToken` in the request metadata.
* Progress tokens **MUST** be a string or integer value
* Progress tokens can be chosen by the client using any means, but **MUST** be unique
across all active requests.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}
```
The server **MAY** then send progress notifications containing:
* The original progress token
* The current progress value so far
* An optional "total" value
* An optional "message" value
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}
```
* The `progress` value **MUST** increase with each notification, even if the total is
unknown.
* The `progress` and the `total` values **MAY** be floating point.
* The `message` field **SHOULD** provide relevant human readable progress information.
## Behavior Requirements
1. Progress notifications **MUST** only reference tokens that:
* Were provided in an active request
* Are associated with an in-progress operation
2. Servers receiving a request with a progress token **MAY**:
* Choose not to send any progress notifications
* Send notifications at whatever frequency they deem appropriate
* Omit the total value if unknown
```mermaid theme={null}
sequenceDiagram
participant Client
participant Server
Note over Client,Server: Request with progress token
Client->>Server: Method request with progressToken
Note over Client,Server: Progress updates
Server-->>Client: Progress notification (0.2/1.0)
Server-->>Client: Progress notification (0.6/1.0)
Server-->>Client: Progress notification (1.0/1.0)
Note over Client,Server: Operation complete
Server->>Client: Method response
```
## Implementation Notes
* Clients and servers **SHOULD** track active progress tokens
* Both parties **SHOULD** implement rate limiting to prevent flooding
* Progress notifications **MUST** stop after completion
specification/2026-07-28/basic/patterns/subscriptions First recorded · 163 lines, first recorded
# Subscriptions ## Opening a Stream ### Notification Filter ## Acknowledgment ## Receiving Notifications ## Multiple Concurrent Subscriptions ## Cancellation ### Graceful Closure
The first capture of this source. The page was already there, and this is what it said.
# Subscriptions
<div id="enable-section-numbers" />
`subscriptions/listen` opens a long-lived notification stream from the server to the
client. Unlike one-off requests, the stream stays open and delivers notifications until
the client cancels it. It replaces the former `resources/subscribe` RPC and the HTTP GET
endpoint.
## Opening a Stream
The client sends a `subscriptions/listen` request with a `notifications` filter
specifying which event types it wants to receive. The server **MUST NOT** send
notification types the client has not explicitly requested.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"method": "subscriptions/listen",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "ExampleClient",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
},
"notifications": {
"toolsListChanged": true,
"resourceSubscriptions": ["file:///project/config.json"]
}
}
}
```
### Notification Filter
| Field | Type | Description |
| ----------------------- | ---------- | ----------------------------------------------------------------- |
| `toolsListChanged` | `boolean` | Receive `notifications/tools/list_changed` when tools change |
| `promptsListChanged` | `boolean` | Receive `notifications/prompts/list_changed` when prompts change |
| `resourcesListChanged` | `boolean` | Receive `notifications/resources/list_changed` when list changes |
| `resourceSubscriptions` | `string[]` | Receive `notifications/resources/updated` for these resource URIs |
All fields are optional. Omitting a field is equivalent to not subscribing to that
notification type.
## Acknowledgment
The server **MUST** send `notifications/subscriptions/acknowledged` as the first message
carrying the subscription's ID in `_meta` under `io.modelcontextprotocol/subscriptionId`,
and **MUST NOT** send any notification on the
subscription before it. On stdio, where every subscription shares one channel, this
ordering is defined per subscription ID and not per channel: messages belonging to other
subscriptions **MAY** be interleaved before it.
The `notifications` field in the acknowledgment reflects the subset the server agreed to
honor. Notification types the server does not support are omitted.
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/subscriptions/acknowledged",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 1
},
"notifications": {
"toolsListChanged": true,
"resourceSubscriptions": ["file:///project/config.json"]
}
}
}
```
The client **SHOULD** check the acknowledged filter against what it requested and handle
any unsupported types gracefully.
## Receiving Notifications
All notifications delivered on the stream carry
`io.modelcontextprotocol/subscriptionId` in `_meta`, identifying the
`subscriptions/listen` request that opened the stream. The value is the JSON-RPC ID of
the `subscriptions/listen` request. In the examples above, the request used `"id": 1`,
so the acknowledgment and all subsequent notifications carry the subscription ID `1`.
On stdio, where all messages
share a single channel, clients **MUST** use this field to correlate notifications
with their originating subscription.
```json theme={null}
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 1
},
"uri": "file:///project/config.json"
}
}
```
## Multiple Concurrent Subscriptions
A client **MAY** have multiple active subscriptions concurrently — for example,
one listening for tools-list changes and another for resource updates. Each
subscription is identified by the JSON-RPC request ID of its
`subscriptions/listen` request, and every notification on the stream carries
that ID in
`io.modelcontextprotocol/subscriptionId` so clients can demultiplex them.
## Cancellation
A subscription ends when:
* The **client** cancels it — close the SSE stream (HTTP) or send
`notifications/cancelled` referencing the `subscriptions/listen` request ID (stdio).
* The **server** tears it down (e.g., during shutdown) — it **SHOULD** send the
empty `subscriptions/listen` response to signal a graceful end (see
[Graceful Closure](#graceful-closure)), then close the stream.
* The underlying transport closes (HTTP timeout, TCP disconnect, stdio process
exit).
### Graceful Closure
When the server ends a subscription on its own initiative (for example, during
shutdown), it **SHOULD** respond to the original `subscriptions/listen` request
with an empty result before closing the stream. This is the JSON-RPC response to
the long-lived request, correlated by its `id`, and signals that the subscription
ended gracefully — as opposed to an abrupt transport drop, which carries no
response.
```json theme={null}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"_meta": {
"io.modelcontextprotocol/subscriptionId": 1
}
}
}
```
Like every other message on the stream, the response carries
`io.modelcontextprotocol/subscriptionId` in `_meta`, identifying which
subscription it closes. The value matches the JSON-RPC `id` of the originating
`subscriptions/listen` request.
A client that receives this response knows the subscription closed cleanly; a
transport that closes without it indicates an unexpected disconnect, which the
client **MAY** treat as a trigger to reconnect.
On **stdio**, if the connection is terminated and then re-established, the
client **MUST** re-send `subscriptions/listen` to re-establish its
subscriptions — the server holds no subscription state across reconnections.
See [Cancellation][cancellation] for the full rules.
[cancellation]: /specification/2026-07-28/basic/patterns/cancellation
specification/2026-07-28/basic/transports/index First recorded · 87 lines, first recorded
# Overview ## Messages ## Request Metadata ## Cancellation ## Custom Transports ## Backward Compatibility
The first capture of this source. The page was already there, and this is what it said.
# Overview <div id="enable-section-numbers" /> This page defines what a transport must provide to carry MCP messages, the standard transport bindings, and the requirements for defining new ones. Protocol semantics are identical on every transport. A transport is a **binding**: it defines how messages are framed and delivered, how request metadata is carried, and how cancellation and termination are signaled. It does not define what the messages mean: the [message patterns](/specification/2026-07-28/basic/patterns) are part of the core protocol and are the same on every binding. The binding pages specify the standard transports: 1. [stdio](/specification/2026-07-28/basic/transports/stdio): newline-delimited messages over the standard streams of a client-launched subprocess. 2. [Streamable HTTP](/specification/2026-07-28/basic/transports/streamable-http): each message is an HTTP POST to a single MCP endpoint; replies arrive as a JSON object or a request-scoped SSE stream. It is also possible for clients and servers to implement [custom transports](#custom-transports). ## Messages MCP uses JSON-RPC to encode messages. JSON-RPC messages **MUST** be UTF-8 encoded. A binding **MUST** deliver client-sent *requests* and *notifications* to the server, and server-sent *responses* and *notifications* to the client. No other message direction exists: per the [message patterns](/specification/2026-07-28/basic/patterns), servers do not initiate JSON-RPC requests and clients do not send JSON-RPC responses. ## Request Metadata All protocol metadata travels in the message body: every request carries its protocol version and client capabilities in [`_meta.io.modelcontextprotocol/*`](/specification/2026-07-28/basic/index#meta) fields. A binding **MAY** additionally mirror selected body fields into envelope metadata. The Streamable HTTP transport mirrors them into [HTTP headers](/specification/2026-07-28/basic/transports/streamable-http#request-metadata) so that intermediaries can route and inspect requests without parsing the body. The body remains the source of truth; bindings that mirror metadata define how mismatches are rejected. ## Cancellation Each binding defines how a client abandons an in-flight request: on stdio the client sends a `notifications/cancelled` notification; on Streamable HTTP it closes the request's response stream. The protocol-level rules are the same everywhere; see [Cancellation](/specification/2026-07-28/basic/patterns/cancellation). ## Custom Transports Clients and servers **MAY** implement additional custom transport mechanisms to suit their specific needs. The protocol is transport-agnostic and can be implemented over any communication channel that supports bidirectional message exchange. Implementers who choose to support custom transports **MUST** preserve the JSON-RPC message format, the [message patterns](/specification/2026-07-28/basic/patterns), and the per-request metadata model. Custom transports **SHOULD** document their connection establishment, message framing, and cancellation patterns to aid interoperability. Custom transports that run over a reliable bidirectional byte stream (e.g., Unix domain sockets or TCP) **SHOULD** reuse the [stdio framing](/specification/2026-07-28/basic/transports/stdio) rather than defining a new one: the stdio binding is just newline-delimited JSON-RPC over a byte stream, and only its process-lifecycle rules are specific to standard streams. ## Backward Compatibility Earlier protocol revisions established a connection-scoped session with an `initialize` handshake and allowed servers to initiate JSON-RPC requests. Clients and servers that interoperate with those revisions detect the counterpart's era and fall back as described in [Versioning: Backward Compatibility](/specification/2026-07-28/basic/versioning#backward-compatibility-with-initialization-based-versions), which includes a compatibility matrix for implementors. Each binding page describes its transport-specific detection mechanics.