Skip to content

Conversation

@findleyr
Copy link
Contributor

@findleyr findleyr commented Nov 5, 2025

This PR is the result of spending a few hours going through and attempting to implement SEP 1442
(modelcontextprotocol/modelcontextprotocol#1442).

Implemented:

  • skipping initialization
  • new protocol version and session ID treatment
  • server/discover
  • unsupported version errors
  • new _meta fields
  • client capability embedding

Still TODO:

  • client-initiated streams
  • ergonomics and documentation for handling capabilities from application code
  • many, many more tests (and corresponding bug fixes)

This is very much quick and dirty, though I learned a lot about the SEP in the process. Tests pass, albeit largely because I configure the client to keep initialization, or downgrade the protocol version.

Notably, server->client requests do work in the context of an uninitialized session.

Additional observations will be noted in PR comments.

This PR is the result of spending a few hours going through and
attempting to implement SEP 1442
(modelcontextprotocol/modelcontextprotocol#1442).

Implemented:
 - skipping initialization
 - new protocol version and session ID treatment
 - server/discover
 - unsupported version errors
 - new _meta fields
 - client capability embedding

Still TODO:
 - client-initiated streams
 - ergonomic and documentation for handling capabilities from
   application code
 - many, many more tests (and corresponding bug fixes)

This is very much quick and dirty, though I learned a lot about the SEP
in the process. Tests pass, albeit largely because I configure the
client to keep initialization, or downgrade the protocol version.

Notably, server->client requests do work in the context of an
uninitialized session.

Additional observations will be noted in PR comments.
@findleyr
Copy link
Contributor Author

findleyr commented Nov 5, 2025

Here are my raw, mostly unfiltered notes from implementing this SEP. (I did delete a few where I was just confused).

**Protocol Version negotiation **

  • Is the client allowed to change protocol versions within a given session? I assume not. (Answer: yes!)
  • Do all server->client requests made within the context of a client->server request have to have the same protocol version?
  • What if I get an error saying use protocol version B, and then another (later) error saying to use protocol version C. Do we allow that?
  • Why MUST the error message be “Unsupported protocol version”. The code and data describe the semantics.

Session negotiation

  • Nit: InvalidSessionError and SessionRequiredError both duplicate UnsupportedVersionError. They should be distinguished, and have distinguished error codes.
  • Why is InvalidSessionError a 400 over HTTP. Shouldn’t it be a 404 (Not Found)? In what cases would a session ID be invalid?
  • What is the client supposed to do when it receives a SessionRequiredError? Previously streamable semantics were dictated by HTTP error codes, but 400 does not have clear semantics attached to it.
  • The section on per-request sessions is a little vague. I assume that the client is permitted to use its own UUID for the session ID. What is the lifespan of that session? Does it need to be explicitly deleted by a DELETE request?
    For now, I hold it open only for the duration of the request that created it.

Capability negotiation

  • I think it’s a mistake to have server capabilities sent in an initial response message in the “client/capabilities” stream, which is another type of standalone stream. This seems like mixing transport and protocol in an unclean way. It’s also inconsistent with other stream semantics: the standalone stream not having any responses on it, and the ordinary POST request streams terminate with their response. Why not just have the client initialize the session, in this case?

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.

1 participant