@@ -43,7 +43,6 @@ export type StreamableHTTPClientTransportOptions = {
43
43
* for receiving messages.
44
44
*/
45
45
export class StreamableHTTPClientTransport implements Transport {
46
- private _activeStreams : Map < string , ReadableStreamDefaultReader < EventSourceMessage > > = new Map ( ) ;
47
46
private _abortController ?: AbortController ;
48
47
private _url : URL ;
49
48
private _requestInit ?: RequestInit ;
@@ -134,33 +133,28 @@ export class StreamableHTTPClientTransport implements Transport {
134
133
}
135
134
136
135
// Successful connection, handle the SSE stream as a standalone listener
137
- const streamId = `standalone-sse-${ Date . now ( ) } ` ;
138
- this . _handleSseStream ( response . body , streamId ) ;
136
+ this . _handleSseStream ( response . body ) ;
139
137
} catch ( error ) {
140
138
this . onerror ?.( error as Error ) ;
141
139
throw error ;
142
140
}
143
141
}
144
142
145
- private _handleSseStream ( stream : ReadableStream < Uint8Array > | null , streamId : string ) : void {
143
+ private _handleSseStream ( stream : ReadableStream < Uint8Array > | null ) : void {
146
144
if ( ! stream ) {
147
145
return ;
148
146
}
149
-
150
147
// Create a pipeline: binary stream -> text decoder -> SSE parser
151
148
const eventStream = stream
152
149
. pipeThrough ( new TextDecoderStream ( ) )
153
150
. pipeThrough ( new EventSourceParserStream ( ) ) ;
154
151
155
152
const reader = eventStream . getReader ( ) ;
156
- this . _activeStreams . set ( streamId , reader ) ;
157
-
158
153
const processStream = async ( ) => {
159
154
try {
160
155
while ( true ) {
161
156
const { done, value : event } = await reader . read ( ) ;
162
157
if ( done ) {
163
- this . _activeStreams . delete ( streamId ) ;
164
158
break ;
165
159
}
166
160
@@ -181,7 +175,6 @@ export class StreamableHTTPClientTransport implements Transport {
181
175
}
182
176
}
183
177
} catch ( error ) {
184
- this . _activeStreams . delete ( streamId ) ;
185
178
this . onerror ?.( error as Error ) ;
186
179
}
187
180
} ;
@@ -190,7 +183,7 @@ export class StreamableHTTPClientTransport implements Transport {
190
183
}
191
184
192
185
async start ( ) {
193
- if ( this . _activeStreams . size > 0 ) {
186
+ if ( this . _abortController ) {
194
187
throw new Error (
195
188
"StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically." ,
196
189
) ;
@@ -214,16 +207,6 @@ export class StreamableHTTPClientTransport implements Transport {
214
207
}
215
208
216
209
async close ( ) : Promise < void > {
217
- // Close all active streams
218
- for ( const reader of this . _activeStreams . values ( ) ) {
219
- try {
220
- reader . cancel ( ) ;
221
- } catch ( error ) {
222
- this . onerror ?.( error as Error ) ;
223
- }
224
- }
225
- this . _activeStreams . clear ( ) ;
226
-
227
210
// Abort any pending requests
228
211
this . _abortController ?. abort ( ) ;
229
212
@@ -292,8 +275,7 @@ export class StreamableHTTPClientTransport implements Transport {
292
275
if ( hasRequests ) {
293
276
if ( contentType ?. includes ( "text/event-stream" ) ) {
294
277
// For streaming responses, create a unique stream ID based on request IDs
295
- const streamId = `req-${ requestIds . join ( '-' ) } -${ Date . now ( ) } ` ;
296
- this . _handleSseStream ( response . body , streamId ) ;
278
+ this . _handleSseStream ( response . body ) ;
297
279
} else if ( contentType ?. includes ( "application/json" ) ) {
298
280
// For non-streaming servers, we might get direct JSON responses
299
281
const data = await response . json ( ) ;
@@ -321,7 +303,9 @@ export class StreamableHTTPClientTransport implements Transport {
321
303
*/
322
304
async openSseStream ( ) : Promise < void > {
323
305
if ( ! this . _abortController ) {
324
- this . _abortController = new AbortController ( ) ;
306
+ throw new Error (
307
+ "StreamableHTTPClientTransport not started! Call connect() before openSseStream()." ,
308
+ ) ;
325
309
}
326
310
await this . _startOrAuthStandaloneSSE ( ) ;
327
311
}
0 commit comments