-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Bug Description
Happy's MCP server (which provides the change_title tool) returns 500 errors on every request after startup, causing the mcp__happy__change_title tool to never register in Claude Code.
Root Cause
In startHappyServer() (dist/index-B3gQr6vs.mjs:4779), the StreamableHTTPServerTransport is created with sessionIdGenerator: void 0 (stateless mode):
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: void 0
});
await mcp.connect(transport);
const server = createServer(async (req, res) => {
try {
await transport.handleRequest(req, res);
} catch (error) {
logger.debug("Error handling request:", error);
if (!res.headersSent) {
res.writeHead(500).end();
}
}
});In @modelcontextprotocol/sdk v1.26.0 (the version Happy ships), stateless mode makes the transport single-use. After handling one request, subsequent calls to handleRequest() throw:
"Stateless transport cannot be reused across requests. Create a new transport per request."
This is from webStandardStreamableHttp.js:139-140:
if (!this.sessionIdGenerator && this._hasHandledRequest) {
throw new Error('Stateless transport cannot be reused across requests. Create a new transport per request.');
}The thrown error is caught by Happy's server handler, which returns an empty 500 response. Claude Code then sees the MCP server as broken, the change_title tool never registers, and ToolSearch finds nothing.
Expected Behavior
The MCP server should handle multiple requests throughout the session lifetime, allowing change_title to be discovered and called.
Suggested Fixes
Either:
- Create a new transport per request (what stateless mode requires):
const server = createServer(async (req, res) => {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: void 0
});
await mcp.connect(transport);
try {
await transport.handleRequest(req, res);
} catch (error) { ... }
});- Use stateful mode by providing a
sessionIdGenerator:
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID()
});Environment
- happy-coder: 0.13.0
- @modelcontextprotocol/sdk: 1.26.0
- Claude Code: 2.1.39
- macOS (darwin arm64)
- Node: v25.2.1
Reproduction
Every session started via Happy exhibits this behavior. The symptom from the user's perspective is:
ToolSearch query: "select:mcp__happy__change_title"
→ "No matching deferred tools found"
The daemon log shows the MCP server starting successfully, but any curl to the server returns 500:
curl -v -X POST http://127.0.0.1:<port>/ \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{...},"id":1}'
# → HTTP/1.1 500 Internal Server Error (empty body)