@@ -97,7 +97,9 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
97
97
console . log ( "Connected to SSE transport" ) ;
98
98
return transport ;
99
99
} else if ( transportType === "streamable - http ") {
100
- const headers : HeadersInit = { } ;
100
+ const headers : HeadersInit = {
101
+ Accept : "text/event-stream, application/json"
102
+ } ;
101
103
102
104
for ( const key of STREAMABLE_HTTP_HEADERS_PASSTHROUGH ) {
103
105
if ( req . headers [ key ] === undefined ) {
@@ -127,9 +129,10 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
127
129
128
130
let backingServerTransport : Transport | undefined ;
129
131
130
- app . get ( "/sse" , async ( req , res ) => {
132
+
133
+ app . get ( "/mcp" , async ( req , res ) => {
131
134
try {
132
- console . log ( "New SSE connection" ) ;
135
+ console . log ( "New streamable-http connection" ) ;
133
136
134
137
try {
135
138
await backingServerTransport ?. close ( ) ;
@@ -149,9 +152,7 @@ app.get("/sse", async (req, res) => {
149
152
150
153
console . log ( "Connected MCP client to backing server transport" ) ;
151
154
152
- const webAppTransport = new SSEServerTransport ( "/message" , res ) ;
153
- console . log ( "Created web app transport" ) ;
154
-
155
+ const webAppTransport = new SSEServerTransport ( "/mcp" , res ) ;
155
156
webAppTransports . push ( webAppTransport ) ;
156
157
console . log ( "Created web app transport" ) ;
157
158
@@ -181,6 +182,114 @@ app.get("/sse", async (req, res) => {
181
182
}
182
183
} ) ;
183
184
185
+ app . post ( "/mcp" , async ( req , res ) => {
186
+ try {
187
+ const sessionId = req . query . sessionId ;
188
+ console . log ( `Received message for sessionId ${ sessionId } ` ) ;
189
+
190
+ const transport = webAppTransports . find ( ( t ) => t . sessionId === sessionId ) ;
191
+ if ( ! transport ) {
192
+ res . status ( 404 ) . end ( "Session not found" ) ;
193
+ return ;
194
+ }
195
+ await transport . handlePostMessage ( req , res ) ;
196
+ } catch ( error ) {
197
+ console . error ( "Error in /mcp route:" , error ) ;
198
+ res . status ( 500 ) . json ( error ) ;
199
+ }
200
+ } ) ;
201
+
202
+ app . get ( "/stdio" , async ( req , res ) => {
203
+ try {
204
+ console . log ( "New connection" ) ;
205
+
206
+ try {
207
+ await backingServerTransport ?. close ( ) ;
208
+ backingServerTransport = await createTransport ( req ) ;
209
+ } catch ( error ) {
210
+ if ( error instanceof SseError && error . code === 401 ) {
211
+ console . error (
212
+ "Received 401 Unauthorized from MCP server:" ,
213
+ error . message ,
214
+ ) ;
215
+ res . status ( 401 ) . json ( error ) ;
216
+ return ;
217
+ }
218
+
219
+ throw error ;
220
+ }
221
+
222
+ console . log ( "Connected MCP client to backing server transport" ) ;
223
+
224
+ const webAppTransport = new SSEServerTransport ( "/message" , res ) ;
225
+ webAppTransports . push ( webAppTransport ) ;
226
+
227
+ console . log ( "Created web app transport" ) ;
228
+
229
+ await webAppTransport . start ( ) ;
230
+ ( backingServerTransport as StdioClientTransport ) . stderr ! . on ( "data" , ( chunk ) => {
231
+ webAppTransport . send ( {
232
+ jsonrpc : "2.0" ,
233
+ method : "notifications/stderr" ,
234
+ params : {
235
+ content : chunk . toString ( ) ,
236
+ } ,
237
+ } ) ;
238
+ } ) ;
239
+
240
+ mcpProxy ( {
241
+ transportToClient : webAppTransport ,
242
+ transportToServer : backingServerTransport ,
243
+ } ) ;
244
+
245
+ console . log ( "Set up MCP proxy" ) ;
246
+ } catch ( error ) {
247
+ console . error ( "Error in /stdio route:" , error ) ;
248
+ res . status ( 500 ) . json ( error ) ;
249
+ }
250
+ } ) ;
251
+
252
+ app . get ( "/sse" , async ( req , res ) => {
253
+ try {
254
+ console . log ( "New SSE connection. NOTE: The sse transport is deprecated and has been replaced by streamable-http" ) ;
255
+
256
+ try {
257
+ await backingServerTransport ?. close ( ) ;
258
+ backingServerTransport = await createTransport ( req ) ;
259
+ } catch ( error ) {
260
+ if ( error instanceof SseError && error . code === 401 ) {
261
+ console . error (
262
+ "Received 401 Unauthorized from MCP server:" ,
263
+ error . message ,
264
+ ) ;
265
+ res . status ( 401 ) . json ( error ) ;
266
+ return ;
267
+ }
268
+
269
+ throw error ;
270
+ }
271
+
272
+ console . log ( "Connected MCP client to backing server transport" ) ;
273
+
274
+ const webAppTransport = new SSEServerTransport ( "/message" , res ) ;
275
+ webAppTransports . push ( webAppTransport ) ;
276
+
277
+ console . log ( "Created web app transport" ) ;
278
+
279
+ await webAppTransport . start ( ) ;
280
+
281
+ mcpProxy ( {
282
+ transportToClient : webAppTransport ,
283
+ transportToServer : backingServerTransport ,
284
+ } ) ;
285
+
286
+ console . log ( "Set up MCP proxy" ) ;
287
+ } catch ( error ) {
288
+ console . error ( "Error in /sse route:" , error ) ;
289
+ res . status ( 500 ) . json ( error ) ;
290
+ }
291
+ } ) ;
292
+
184
293
app . post ( "/message" , async ( req , res ) => {
185
294
try {
186
295
const sessionId = req . query . sessionId ;
0 commit comments