@@ -117,26 +117,26 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
117
117
return
118
118
}
119
119
120
- var session * StreamableServerTransport
120
+ var transport * StreamableServerTransport
121
121
sessionID := req .Header .Get (sessionIDHeader )
122
122
if sessionID != "" {
123
123
h .transportMu .Lock ()
124
- session , _ = h .transports [sessionID ]
124
+ transport , _ = h .transports [sessionID ]
125
125
h .transportMu .Unlock ()
126
126
}
127
127
128
128
// TODO(rfindley): simplify the locking so that each request has only one
129
129
// critical section.
130
130
if req .Method == http .MethodDelete {
131
- if session == nil {
131
+ if transport == nil {
132
132
// => Mcp-Session-Id was not set; else we'd have returned NotFound above.
133
133
http .Error (w , "DELETE requires an Mcp-Session-Id header" , http .StatusBadRequest )
134
134
return
135
135
}
136
136
h .transportMu .Lock ()
137
- delete (h .transports , session .sessionID )
137
+ delete (h .transports , transport .sessionID )
138
138
h .transportMu .Unlock ()
139
- session .Close ()
139
+ transport .Close ()
140
140
w .WriteHeader (http .StatusNoContent )
141
141
return
142
142
}
@@ -149,7 +149,7 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
149
149
return
150
150
}
151
151
152
- if session == nil {
152
+ if transport == nil {
153
153
var state * SessionState
154
154
var err error
155
155
if sessionID != "" {
@@ -162,16 +162,15 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
162
162
http .Error (w , fmt .Sprintf ("SessionStore.Load(%q): %v" , sessionID , err ), http .StatusInternalServerError )
163
163
return
164
164
}
165
- session = NewStreamableServerTransport (sessionID , nil )
166
165
} else {
167
166
state = & SessionState {}
168
167
sessionID = randText ()
169
168
if err := h .opts .SessionStore .Store (req .Context (), sessionID , state ); err != nil {
170
169
http .Error (w , fmt .Sprintf ("SessionStore.Store, new session: %v" , err ), http .StatusInternalServerError )
171
170
return
172
171
}
173
- session = NewStreamableServerTransport (sessionID , nil )
174
172
}
173
+ transport = NewStreamableServerTransport (sessionID , nil )
175
174
server := h .getServer (req )
176
175
if server == nil {
177
176
http .Error (w , "no server available" , http .StatusBadRequest )
@@ -180,7 +179,8 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
180
179
// Pass req.Context() here, to allow middleware to add context values.
181
180
// The context is detached in the jsonrpc2 library when handling the
182
181
// long-running stream.
183
- _ , err = server .Connect (req .Context (), session , & ServerSessionOptions {
182
+ // TODO: rename SessionOptions to ConnectOptions?
183
+ _ , err = server .Connect (req .Context (), transport , & SessionOptions {
184
184
SessionID : sessionID ,
185
185
SessionState : state ,
186
186
SessionStore : h .opts .SessionStore ,
@@ -190,11 +190,14 @@ func (h *StreamableHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Reque
190
190
return
191
191
}
192
192
h .transportMu .Lock ()
193
- h .transports [session .sessionID ] = session
193
+ // Check in case another request with the same stored session ID got here first.
194
+ if _ , ok := h .transports [transport .sessionID ]; ! ok {
195
+ h .transports [transport .sessionID ] = transport
196
+ }
194
197
h .transportMu .Unlock ()
195
198
}
196
199
197
- session .ServeHTTP (w , req )
200
+ transport .ServeHTTP (w , req )
198
201
}
199
202
200
203
type StreamableServerTransportOptions struct {
0 commit comments