mcp: remove the StreamID type (#490)

The streamID type did not carry its weight. Remove it.

Fixes #484.
This commit is contained in:
Robert Findley 2025-09-18 12:01:07 -04:00 • committed by GitHub
commit 353d46ff86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -396,8 +396,8 @@ func (t *StreamableServerTransport) Connect(ctx context.Context) (Connection, er
jsonResponse: t.jsonResponse,
incoming: make(chan jsonrpc.Message, 10),
done: make(chan struct{}),
streams: make(map[StreamID]*stream),
requestStreams: make(map[jsonrpc.ID]StreamID),
streams: make(map[string]*stream),
requestStreams: make(map[jsonrpc.ID]string),
}
if t.connection.eventStore == nil {
t.connection.eventStore = NewMemoryEventStore(nil)
@ -442,14 +442,14 @@ type streamableServerConn struct {
// bound. If we deleted a stream when the response is sent, we would lose the ability
// to replay if there was a cut just before the response was transmitted.
// Perhaps we could have a TTL for streams that starts just after the response.
streams map[StreamID]*stream
streams map[string]*stream
// requestStreams maps incoming requests to their logical stream ID.
//
// Lifecycle: requestStreams persist for the duration of the session.
//
// TODO: clean up once requests are handled. See the TODO for streams above.
requestStreams map[jsonrpc.ID]StreamID
requestStreams map[jsonrpc.ID]string
}
func (c *streamableServerConn) SessionID() string {
@ -466,7 +466,7 @@ func (c *streamableServerConn) SessionID() string {
type stream struct {
// id is the logical ID for the stream, unique within a session.
// an empty string is used for messages that don't correlate with an incoming request.
id StreamID
id string
// If isInitialize is set, the stream is in response to an initialize request,
// and therefore should include the session ID header.
@ -500,7 +500,7 @@ type stream struct {
requests map[jsonrpc.ID]struct{}
}
func (c *streamableServerConn) newStream(ctx context.Context, id StreamID, isInitialize, jsonResponse bool) (*stream, error) {
func (c *streamableServerConn) newStream(ctx context.Context, id string, isInitialize, jsonResponse bool) (*stream, error) {
if err := c.eventStore.Open(ctx, c.sessionID, id); err != nil {
return nil, err
}
@ -517,10 +517,6 @@ func signalChanPtr() *chan struct{} {
return &c
}
// A StreamID identifies a stream of SSE events. It is globally unique.
// [ServerSession].
type StreamID string
// We track the incoming request ID inside the handler context using
// idContextValue, so that notifications and server->client calls that occur in
// the course of handling incoming requests are correlated with the incoming
@ -569,7 +565,7 @@ func (t *StreamableServerTransport) ServeHTTP(w http.ResponseWriter, req *http.R
// It returns an HTTP status code and error message.
func (c *streamableServerConn) serveGET(w http.ResponseWriter, req *http.Request) {
// connID 0 corresponds to the default GET request.
id := StreamID("")
id := ""
// By default, we haven't seen a last index. Since indices start at 0, we represent
// that by -1. This is incremented just before each event is written, in streamResponse
// around L407.
@ -669,7 +665,7 @@ func (c *streamableServerConn) servePOST(w http.ResponseWriter, req *http.Reques
// notifications or server->client requests made in the course of handling.
// Update accounting for this incoming payload.
if len(requests) > 0 {
stream, err = c.newStream(req.Context(), StreamID(randText()), isInitialize, c.jsonResponse)
stream, err = c.newStream(req.Context(), randText(), isInitialize, c.jsonResponse)
if err != nil {
http.Error(w, fmt.Sprintf("storing stream: %v", err), http.StatusInternalServerError)
return
@ -860,7 +856,7 @@ func (c *streamableServerConn) messages(ctx context.Context, stream *stream, per
// streamID and message index idx.
//
// See also [parseEventID].
func formatEventID(sid StreamID, idx int) string {
func formatEventID(sid string, idx int) string {
return fmt.Sprintf("%s_%d", sid, idx)
}
@ -868,17 +864,17 @@ func formatEventID(sid StreamID, idx int) string {
// index.
//
// See also [formatEventID].
func parseEventID(eventID string) (sid StreamID, idx int, ok bool) {
func parseEventID(eventID string) (streamID string, idx int, ok bool) {
parts := strings.Split(eventID, "_")
if len(parts) != 2 {
return "", 0, false
}
stream := StreamID(parts[0])
streamID = parts[0]
idx, err := strconv.Atoi(parts[1])
if err != nil || idx < 0 {
return "", 0, false
}
return StreamID(stream), idx, true
return streamID, idx, true
}
// Read implements the [Connection] interface.
@ -922,7 +918,7 @@ func (c *streamableServerConn) Write(ctx context.Context, msg jsonrpc.Message) e
//
// For messages sent outside of a request context, this is the default
// connection "".
var forStream StreamID
var forStream string
if forRequest.IsValid() {
c.mu.Lock()
forStream = c.requestStreams[forRequest]