Skip to content

feat: add SEP-1685 revisions proposal#16

Closed
gjz22 wants to merge 1 commit intomodelcontextprotocol:mainfrom
gjz22:sep-1685-revisions
Closed

feat: add SEP-1685 revisions proposal#16
gjz22 wants to merge 1 commit intomodelcontextprotocol:mainfrom
gjz22:sep-1685-revisions

Conversation

@gjz22
Copy link
Copy Markdown

@gjz22 gjz22 commented Feb 11, 2026

Summary

This proposal adds an optional state field to both ServerRequest and ServerResponse messages in the Model Context Protocol (MCP). This enables servers to implement stateless request flows, eliminating the requirement for durable state storage and significantly reducing operational complexity and cost.

Key Points

  • Primary motivation: elicitation requests in remote MCP servers where response times are unbounded (seconds to hours)
  • Enables stateless server implementations by allowing servers to encode context in the state field
  • Supports multi-round-trip interactions without server-side storage
  • Backward compatible: the state field is optional

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@markdroth markdroth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for writing this up!

I think we'll probably want to integrate this into #12 instead of having it be a separate SEP. But let's first come to consensus on how we want the state field to be represented.


## Abstract

This SEP proposes adding an optional `state` field to both `ServerRequest` and `ServerResponse` messages in the Model Context Protocol (MCP). The client MUST echo back the exact state value received in the request when sending the response. This change enables servers to implement stateless request flows, eliminating the requirement for durable state storage and significantly reducing operational complexity and cost. While this applies to all ServerRequests, the primary motivation is elicitation requests, where response times are unbounded and can range from seconds to hours, making stateful implementations particularly challenging for remote MCPs.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you mean ClientResult rather than ServerResponse:

https://github.com/modelcontextprotocol/modelcontextprotocol/blob/a0856fb02f1b1c9245768929cad7191b2f6698a3/schema/2025-11-25/schema.ts#L2537

I made the same mistake in the MRTR SEP, and Catie fixed it. :)

{
"id": 2,
"dependent_requests": {
"state": { "workItemId": 4522, "fields": { "System.State": "Resolved" } },
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually move it up to be a top-level field, not inside of the "dependent_requests" field. I think this is actually a separate (albeit synergistic) mechanism from dependent requests, and I could easily imagine cases where a server sends an incomplete request with state but without any dependent requests as a mechanism for shedding load from an individual server instance.

**Tradeoffs:**

- **Option 1** is simpler — one state per round-trip, less bookkeeping for clients, and the server can encode everything it needs in a single blob. However, if different requests are handled by different subsystems on the server, a single shared state may be awkward.
- **Option 2** is more flexible — each request is self-contained with its own state, which maps cleanly to the non-MRTR case where each `ServerRequest` carries its own `state`. However, it requires clients to track and echo back multiple state values per round-trip.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand what "more flexible" means here. What does this option allow a server to do that it can't do with option 1?

From my perspective, there are two separate things going on here, and I don't think we want to conflate them:

  1. How does the server pass state through the client to a subsequent request?
  2. How does the protocol identify individual dependent requests when it sees the responses?

I think that for (2), we want a very simple mechanism that ensures uniqueness, which is why #12 proposes using a map with simple string keys. I think that solves the problem in a simple and unambiguous way that is very easy for clients and servers to implement. I think that making the key something more complex than a string will make this harder to understand and harder to implement, and it does not provide enough benefit to be worth that trade-off.

For (1), I can't think of any case where the state will actually be associated with individual dependent requests. The two use-cases I can see here are the following:

  • A server first asks for X, then when it gets X, it asks for Y. In the request for Y, it will want to encode X in the state field, so that it does not need to ask for X again. Note that in this case, X and Y are totally independent requests, so storing the result of X in state associated with Y doesn't make any sense semantically.
  • A server may not actually need to ask for any info, but the server instance may need to shed load in the middle of processing a client-initiated request. It can do this by encoding its current state in the state field and sending an incomplete response, so that the client will try again and the load balancers can send the request to a different server instance. In this case, the server's incomplete response does not have any dependent requests, so there's no dependent request to associate the state with.

Are there other use cases here that I'm not thinking of in which the state will actually be associated with an individual dependent request?

@CaitieM20
Copy link
Copy Markdown
Contributor

This has been incorporated into #12

@CaitieM20 CaitieM20 closed this Feb 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants