AcceptedStandards Track
| Field | Value |
|---|---|
| SEP | 2260 |
| Title | Require Server requests to be associated with a Client request. |
| Status | Accepted |
| Type | Standards Track |
| Created | 2026-02-16 |
| Author(s) | MCP Transports Working Group |
| Sponsor | @CaitieM20 - Caitie McCaffrey |
| PR | #2260 |
Abstract
This SEP clarifies thatroots/list, sampling/createMessage, and
elicitation/create requests MUST be associated with an originating
client-to-server request (e.g., during tools/call, resources/read, or
prompts/get processing). Standalone server-initiated requests of these types
outside notifications MUST NOT be implemented.
Although not enforced in the current MCP Data Layer, logically these requests
MUST be associated with a valid client-to-server JSON-RPC Request Id.
The operational server-to-client Ping is excepted from this restriction.
Motivation
Current Specification
The current specification uses SHOULD language in the transport layer: In context of responding to a POST Request in the Streamable HTTP transport (2025-11-25/basic/transports.mdx:121-L123):For the optional GET SSE Stream (2025-11-25/basic/transports.mdx:146-L148):
- “The server MAY send JSON-RPC requests and notifications before sending the JSON-RPC response. These messages SHOULD relate to the originating client request.”
Although the GET stream allows “unsolicited” requests, its use is entirely optional and cannot be relied upon by MCP Server authors.
- “The server MAY send JSON-RPC requests and notifications on the stream.”
- “These messages SHOULD be unrelated to any concurrently-running JSON-RPC request from the client.”
Design Intent
The design intent of MCP Server Requests is to operate reactively nested within other MCP operations:- Sampling enables servers to request LLM assistance while processing a tool call, resource request, or prompt
- Elicitation enables servers to gather additional user input needed to complete an operation
- List Roots enables servers to identify shared storage locations
“Sampling in MCP allows servers to implement agentic behaviors, by enabling LLM calls to occur nested inside other MCP server features.”However, the normative requirements don’t enforce this constraint.
Simplification Benefits
Making this constraint explicit:- Simplifies transport implementations - Transports don’t need to support arbitrary server-initiated request/response flows, which require a persistent connection from Server to Client; they only need request-scoped bidirectional communication
- Clarifies user experience - Users understand that sampling/elicitation happens because they initiated an action, not spontaneously
- Reduces security surface - Ensures client has context for what scope the additional requested information will be used for. This allows clients to make better informed decisions on whether to provide the requested info.
- Aligns with practice - Based on a scan of GitHub all existing implementations already follow this pattern, except one repo owned by the SEP author with a contrived scenario.
Specification Changes
1. Add Warning Blocks to Feature Documentation
Inclient/sampling.mdx (after existing security warning):
client/elicitation.mdx (after existing security warning):
client/roots.mdx (in User Interaction Model section):
basic/utilities/ping.mdx (In Overview section):
2. Clarify Transport Layer Constraints
Inbasic/transports.mdx, POST-initiated SSE streams (line ~121):
basic/transports.mdx, GET-initiated standalone SSE streams (line ~147):
Backward Compatibility
Impact Assessment
This change is expected to have minimal to no impact on existing implementations:- Common usage patterns are preserved - Sampling/elicitation within tool execution, resource reading, and prompt handling remain fully supported
- No known implementations affected - Research conducted on GitHub has shown only one implementation of this pattern. This singular implementation is owned by the SEP author.
What’s Disallowed
The following pattern, which was never explicitly documented or recommended, is now explicitly prohibited:What Remains Supported
The canonical pattern remains fully supported:Implementation Guidance
For Server Implementers
No changes required if your server:- Only uses server-to-client requests within tool handlers
- Only uses server-to-client requests within resource/prompt handlers
- Uses server-to-client requests synchronously as part of processing a client request
- Attempts to initiate server-to-client requests on standalone HTTP GET streams
- Attempts to send server-to-client requests requests independent of client operations
- Has background tasks that try to invoke server-to-client requests
Timeout Considerations
When an MCP Server initiates a “nested” request inside a client request, the duration of the parent request extends to include the user’s response time. Implementers MUST ensure that:- Transport timeouts (e.g. HTTP Request Timeout) are sufficient to accommodate “Human-in-the-loop” delays, which may be unbounded.
- Short timeouts enforced by infrastructure (e.g. Load Balancers) may result in
connection termination before the user responds. For Streamable HTTP,
transport-level SSE keepalive mechanisms SHOULD be used to keep
connections alive and reset timers;
pingrequests MAY additionally be used for protocol-level responsiveness checks.
For Client Implementers
No changes required - Clients should already handle sampling/elicitation requests in the context of their own outbound requests. Potential to simplify implementations if out-of-band is currently supported. Clients recieving server-to-client requests with no associated outbound request SHOULD respond with a-32602 (Invalid Params) error.
For Transport Implementers
Future transport implementations can rely on the guarantee that:- Sampling/elicitation requests only occur within the scope of a client-initiated request
- Transports don’t need to support arbitrary server-initiated request/response flows on standalone channels
- Request correlation and lifecycle management is simplified
Timeline
(This SEP intends to serve as a public notice of the change prior to future protocol versions that will not be compatible with this usage)Alternatives Considered
1. Soft Deprecation
Use SHOULD NOT language to discourage but not prohibit the pattern. Rejected because: The behavior was never intentionally supported, and leaving it ambiguous prevents transport simplification.2. Keep Current Ambiguity
Leave the existing SHOULD language unchanged. Rejected because: This blocks future transport implementations and leaves implementers uncertain about whether the pattern is supported.3. Create a Capability Flag
Add asampling.standalone or similar capability for servers that want this behavior.
Rejected because: This adds complexity for a use case with no known demand, and contradicts the “nested” design principle.
References
- Current sampling documentation:
/specification/draft/client/sampling.mdx - Current elicitation documentation:
/specification/draft/client/elicitation.mdx - Transport specification:
/specification/draft/basic/transports.mdx - User interaction model discussion in client concepts documentation