diff --git a/examples/server/src/elicitationFormExample.ts b/examples/server/src/elicitationFormExample.ts index 70ff8ecb5..3bb14cf4d 100644 --- a/examples/server/src/elicitationFormExample.ts +++ b/examples/server/src/elicitationFormExample.ts @@ -362,13 +362,25 @@ async function main() { await transport.handleRequest(req, res, req.body); return; + } else if (sessionId) { + // Session ID provided but not found - per spec, return 404 to signal + // client should start a new session + res.status(404).json({ + jsonrpc: '2.0', + error: { + code: -32_000, + message: 'Session not found' + }, + id: null + }); + return; } else { - // Invalid request - no session ID or not initialization request + // No session ID and not an initialization request - return 400 res.status(400).json({ jsonrpc: '2.0', error: { code: -32_000, - message: 'Bad Request: No valid session ID provided' + message: 'Bad Request: Session ID required' }, id: null }); @@ -397,8 +409,12 @@ async function main() { // Handle GET requests for SSE streams const mcpGetHandler = async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } @@ -412,8 +428,12 @@ async function main() { // Handle DELETE requests for session termination const mcpDeleteHandler = async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } diff --git a/examples/server/src/elicitationUrlExample.ts b/examples/server/src/elicitationUrlExample.ts index e72845f1a..677969fa0 100644 --- a/examples/server/src/elicitationUrlExample.ts +++ b/examples/server/src/elicitationUrlExample.ts @@ -605,13 +605,25 @@ const mcpPostHandler = async (req: Request, res: Response) => { await transport.handleRequest(req, res, req.body); return; // Already handled + } else if (sessionId) { + // Session ID provided but not found - per spec, return 404 to signal + // client should start a new session + res.status(404).json({ + jsonrpc: '2.0', + error: { + code: -32_000, + message: 'Session not found' + }, + id: null + }); + return; } else { - // Invalid request - no session ID or not initialization request + // No session ID and not an initialization request - return 400 res.status(400).json({ jsonrpc: '2.0', error: { code: -32_000, - message: 'Bad Request: No valid session ID provided' + message: 'Bad Request: Session ID required' }, id: null }); @@ -642,8 +654,12 @@ app.post('/mcp', authMiddleware, mcpPostHandler); // Handle GET requests for SSE streams (using built-in support from StreamableHTTP) const mcpGetHandler = async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } @@ -681,8 +697,12 @@ app.get('/mcp', authMiddleware, mcpGetHandler); // Handle DELETE requests for session termination (according to MCP spec) const mcpDeleteHandler = async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } diff --git a/examples/server/src/jsonResponseStreamableHttp.ts b/examples/server/src/jsonResponseStreamableHttp.ts index fa0e3a300..a82e073e6 100644 --- a/examples/server/src/jsonResponseStreamableHttp.ts +++ b/examples/server/src/jsonResponseStreamableHttp.ts @@ -128,13 +128,25 @@ app.post('/mcp', async (req: Request, res: Response) => { await server.connect(transport); await transport.handleRequest(req, res, req.body); return; // Already handled + } else if (sessionId) { + // Session ID provided but not found - per spec, return 404 to signal + // client should start a new session + res.status(404).json({ + jsonrpc: '2.0', + error: { + code: -32_000, + message: 'Session not found' + }, + id: null + }); + return; } else { - // Invalid request - no session ID or not initialization request + // No session ID and not an initialization request - return 400 res.status(400).json({ jsonrpc: '2.0', error: { code: -32_000, - message: 'Bad Request: No valid session ID provided' + message: 'Bad Request: Session ID required' }, id: null }); diff --git a/examples/server/src/simpleStreamableHttp.ts b/examples/server/src/simpleStreamableHttp.ts index 75308beff..0bdcdfba0 100644 --- a/examples/server/src/simpleStreamableHttp.ts +++ b/examples/server/src/simpleStreamableHttp.ts @@ -595,13 +595,25 @@ const mcpPostHandler = async (req: Request, res: Response) => { await transport.handleRequest(req, res, req.body); return; // Already handled + } else if (sessionId) { + // Session ID provided but not found - per spec, return 404 to signal + // client should start a new session + res.status(404).json({ + jsonrpc: '2.0', + error: { + code: -32_000, + message: 'Session not found' + }, + id: null + }); + return; } else { - // Invalid request - no session ID or not initialization request + // No session ID and not an initialization request - return 400 res.status(400).json({ jsonrpc: '2.0', error: { code: -32_000, - message: 'Bad Request: No valid session ID provided' + message: 'Bad Request: Session ID required' }, id: null }); @@ -636,8 +648,12 @@ if (useOAuth && authMiddleware) { // Handle GET requests for SSE streams (using built-in support from StreamableHTTP) const mcpGetHandler = async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } @@ -667,8 +683,12 @@ if (useOAuth && authMiddleware) { // Handle DELETE requests for session termination (according to MCP spec) const mcpDeleteHandler = async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } diff --git a/examples/server/src/simpleTaskInteractive.ts b/examples/server/src/simpleTaskInteractive.ts index 1b8532525..97fe19942 100644 --- a/examples/server/src/simpleTaskInteractive.ts +++ b/examples/server/src/simpleTaskInteractive.ts @@ -679,10 +679,19 @@ app.post('/mcp', async (req: Request, res: Response) => { await server.connect(transport); await transport.handleRequest(req, res, req.body); return; + } else if (sessionId) { + // Session ID provided but not found - per spec, return 404 + res.status(404).json({ + jsonrpc: '2.0', + error: { code: -32_000, message: 'Session not found' }, + id: null + }); + return; } else { + // No session ID and not an initialization request - return 400 res.status(400).json({ jsonrpc: '2.0', - error: { code: -32_000, message: 'Bad Request: No valid session ID' }, + error: { code: -32_000, message: 'Bad Request: Session ID required' }, id: null }); return; @@ -704,8 +713,12 @@ app.post('/mcp', async (req: Request, res: Response) => { // Handle GET requests for SSE streams app.get('/mcp', async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } @@ -716,8 +729,12 @@ app.get('/mcp', async (req: Request, res: Response) => { // Handle DELETE requests for session termination app.delete('/mcp', async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; } diff --git a/examples/server/src/standaloneSseWithGetStreamableHttp.ts b/examples/server/src/standaloneSseWithGetStreamableHttp.ts index 1fd351ef1..f20b4df6a 100644 --- a/examples/server/src/standaloneSseWithGetStreamableHttp.ts +++ b/examples/server/src/standaloneSseWithGetStreamableHttp.ts @@ -66,13 +66,25 @@ app.post('/mcp', async (req: Request, res: Response) => { // Handle the request - the onsessioninitialized callback will store the transport await transport.handleRequest(req, res, req.body); return; // Already handled + } else if (sessionId) { + // Session ID provided but not found - per spec, return 404 to signal + // client should start a new session + res.status(404).json({ + jsonrpc: '2.0', + error: { + code: -32_000, + message: 'Session not found' + }, + id: null + }); + return; } else { - // Invalid request - no session ID or not initialization request + // No session ID and not an initialization request - return 400 res.status(400).json({ jsonrpc: '2.0', error: { code: -32_000, - message: 'Bad Request: No valid session ID provided' + message: 'Bad Request: Session ID required' }, id: null }); @@ -99,8 +111,12 @@ app.post('/mcp', async (req: Request, res: Response) => { // Handle GET requests for SSE streams (now using built-in support from StreamableHTTP) app.get('/mcp', async (req: Request, res: Response) => { const sessionId = req.headers['mcp-session-id'] as string | undefined; - if (!sessionId || !transports[sessionId]) { - res.status(400).send('Invalid or missing session ID'); + if (!sessionId) { + res.status(400).send('Bad Request: Session ID required'); + return; + } + if (!transports[sessionId]) { + res.status(404).send('Session not found'); return; }