You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm encountering an issue where McpServer.connect(transport) appears to return null or undefined instead of a valid ServerConnection object when using StreamableHTTPServerTransport. This subsequently prevents the transport's request listener from being set, leading to "Method not found" errors for all MCP calls (including mcp.describe).
Environment:
@modelcontextprotocol/sdk Version:1.11.4 (also observed with 1.11.0)
Express.js Version:4.19.2(Please update if different)
TypeScript Version:5.4.5(Please update if different)
Problem Description:
In my application, which uses Express.js, I'm setting up an McpServer with StreamableHTTPServerTransport. The primary issue is that the synchronous call to server.connect(transport) seems to complete without throwing an immediate error, but the returned value assigned to our connection variable is observed to be null or undefined through logging.
Because the connection object is not valid:
The transport.setRequestListener(...) call, which normally happens inside McpServer.connect(), is likely not being effectively executed for the transport instance.
When transport.handleRequest(...) is later called, transport.requestListener is undefined.
This results in either:
A "Method not found" JSON-RPC error if sessionIdGenerator for StreamableHTTPServerTransport is undefined.
A "Bad Request: Server not initialized" JSON-RPC error (HTTP 400) if sessionIdGenerator is explicitly set (e.g., to randomUUID), as transport.handleRequest has a specific check for this.requestListener.
The core problem is that McpServer.connect() is not returning a valid ServerConnection object as expected by its type signature, thus breaking the link with the transport.
My Application Code Structure:
Here's a simplified representation of the relevant parts of my application code where the issue is observed.
1. src/mcp/mcpServer.ts:
import{McpServer}from"@modelcontextprotocol/sdk/server/mcp.js";import{StreamableHTTPServerTransport}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{Application,Request,Response}from"express";importloggerfrom"../logger";// My application's logger (e.g., Winston)// import { randomUUID } from "crypto"; // If using randomUUID for sessionIdGeneratorasyncfunctiongetCountryList(){return[{name: "United States",code: "US"},{name: "Canada",code: "CA"},];}// Original problematic approach: Factory function called per requestfunctiongetServer(): McpServer{constserver=newMcpServer({name: "AppTools",version: "1.0.0"});server.tool("country-list","Returns a list of all countries in the system",{},async()=>{constcountries=awaitgetCountryList();return{content: [{type: "resource",resource: {mimeType: "application/json",text: JSON.stringify(countries)},},],};});logger.info("Registered tool 'country-list' on new server instance.");returnserver;}exportfunctionsetupMCPServer(app: Application){app.post("/mcp",async(req: Request,res: Response)=>{try{constserver=getServer();// Problem: New server instance on every requestconsttransport=newStreamableHTTPServerTransport({sessionIdGenerator: undefined,// Also tested with randomUUID});logger.info("Connecting transport to server (per-request instance)...");console.log("Connecting transport to server (per-request instance)...");// For visibility// Problem: 'await' on a synchronous function.// This is where 'connection' effectively becomes null/undefined based on logs.constconnection=awaitserver.connect(transport);if(connection){logger.info("server.connect seemed to return a truthy connection object.");console.log("server.connect seemed to return a truthy connection object.");}else{logger.error("CRITICAL: server.connect returned null or undefined.");console.error("CRITICAL: server.connect returned null or undefined.");}logger.info("Transport supposedly connected to server.");console.log("Transport supposedly connected to server.");awaittransport.handleRequest(req,res,req.body);logger.info("Request handled successfully by transport.");console.log("Request handled successfully by transport.");}catch(error: any){logger.error("Error handling MCP request:",{message: error.message,stack: error.stack});console.error("Error handling MCP request:",error);if(!res.headersSent){res.status(500).json({jsonrpc: "2.0",error: {code: -32603,message: "Internal server error"},id: req.body?.id||null,});}}});app.get("/mcp",(req: Request,res: Response)=>{res.status(405).json({jsonrpc: "2.0",error: {code: -32000,message: "Method Not Allowed. Use POST."},id: null});});app.delete("/mcp",(req: Request,res: Response)=>{res.status(405).json({jsonrpc: "2.0",error: {code: -32000,message: "Method Not Allowed. Use POST."},id: null});});logger.info("Original MCP routes configured.");}
src/app.ts (How setupMCPServer is called):
importexpressfrom"express";import*asmcpServerSetupfrom"./mcp/mcpServer";// Path to the mcpServer.ts aboveimportloggerfrom"./logger";// My application's loggerconstapp=express();constport=process.env.API_PORT;app.use(express.json());try{mcpServerSetup.setupMCPServer(app);logger.info("Main MCP server setup completed.");}catch(error){logger.error("Failed to set up main MCP server:",error);process.exit(1);}app.listen(port,()=>{logger.info(`Main Server is running at http://localhost:${port}`);logger.info(`Main MCP server available at http://localhost:${port}/mcp`);});
The curl command receives a "Method not found" error:
{"jsonrpc":"2.0","id":"test-country","error":{"code":-32601,"message":"Method not found"}}
Server logs show the CRITICAL: server.connect returned null or undefined. message (or similar if connection logging is added).
Expected Behavior:
McpServer.connect(transport) should return a valid ServerConnection object. The curl command should successfully invoke the AppTools.country-list method or mcp.describe.
Debugging Notes & Attempts:
We have confirmed that McpServer.connect is a synchronous method, so the await in my original code is incorrect.
Even when correcting my application structure to use a singleton McpServer instance and calling server.connect(transport) synchronously (as demonstrated in separate minimal tests), the core issue of connect() returning null/undefined persisted. This suggests the problem is not solely due to my initial incorrect usage patterns but might indicate a deeper issue within the SDK's connect logic when interacting with StreamableHTTPServerTransport.
Could you please investigate why McpServer.connect() might be failing to establish a proper connection and return null/undefined in this scenario with StreamableHTTPServerTransport?
Thank you for your time and assistance!
The text was updated successfully, but these errors were encountered:
Hello MCP SDK Team,
I'm encountering an issue where
McpServer.connect(transport)
appears to returnnull
orundefined
instead of a validServerConnection
object when usingStreamableHTTPServerTransport
. This subsequently prevents the transport's request listener from being set, leading to "Method not found" errors for all MCP calls (includingmcp.describe
).Environment:
@modelcontextprotocol/sdk
Version:1.11.4
(also observed with1.11.0
)v20.16.0
4.19.2
(Please update if different)5.4.5
(Please update if different)Problem Description:
In my application, which uses Express.js, I'm setting up an
McpServer
withStreamableHTTPServerTransport
. The primary issue is that the synchronous call toserver.connect(transport)
seems to complete without throwing an immediate error, but the returned value assigned to ourconnection
variable is observed to benull
orundefined
through logging.Because the connection object is not valid:
transport.setRequestListener(...)
call, which normally happens insideMcpServer.connect()
, is likely not being effectively executed for the transport instance.transport.handleRequest(...)
is later called,transport.requestListener
isundefined
.sessionIdGenerator
forStreamableHTTPServerTransport
isundefined
.sessionIdGenerator
is explicitly set (e.g., torandomUUID
), astransport.handleRequest
has a specific check forthis.requestListener
.The core problem is that
McpServer.connect()
is not returning a validServerConnection
object as expected by its type signature, thus breaking the link with the transport.My Application Code Structure:
Here's a simplified representation of the relevant parts of my application code where the issue is observed.
1.
src/mcp/mcpServer.ts
:Steps to Reproduce (Using the application structure above):
Set up the project with the described files and relevant dependencies.
Compile TypeScript.
Start the server.
Send a POST request:
Or for mcp.describe:
Observed Behavior:
The curl command receives a "Method not found" error:
Server logs show the CRITICAL: server.connect returned null or undefined. message (or similar if connection logging is added).
Expected Behavior:
McpServer.connect(transport) should return a valid ServerConnection object. The curl command should successfully invoke the AppTools.country-list method or mcp.describe.
Debugging Notes & Attempts:
We have confirmed that McpServer.connect is a synchronous method, so the await in my original code is incorrect.
Even when correcting my application structure to use a singleton McpServer instance and calling server.connect(transport) synchronously (as demonstrated in separate minimal tests), the core issue of connect() returning null/undefined persisted. This suggests the problem is not solely due to my initial incorrect usage patterns but might indicate a deeper issue within the SDK's connect logic when interacting with StreamableHTTPServerTransport.
Could you please investigate why McpServer.connect() might be failing to establish a proper connection and return null/undefined in this scenario with StreamableHTTPServerTransport?
Thank you for your time and assistance!
The text was updated successfully, but these errors were encountered: