Skip to content

Happy MCP server incompatible with @modelcontextprotocol/sdk 1.26.0 - returns HTTP 500 on OAuth discovery #162

@yichern

Description

@yichern

Summary

Happy CLI 0.13.0 is incompatible with @modelcontextprotocol/sdk version 1.26.0. When Claude Code attempts to connect to the Happy MCP server, it receives HTTP 500 errors on the OAuth discovery endpoint, causing authentication to fail.

Environment

  • Happy CLI: 0.13.0
  • Claude Code: 2.1.34
  • Node.js: v22.22.0
  • Platform: Linux (Ubuntu)
  • Working MCP SDK version: 1.25.3
  • Broken MCP SDK version: 1.26.0

How Claude Code Connects to MCP Servers

When Claude Code connects to an HTTP-based MCP server, it makes multiple sequential HTTP requests:

  1. OAuth Discovery - GET /.well-known/oauth-authorization-server

    • Claude Code first checks if the server requires OAuth authentication (per MCP Authorization spec)
    • Expects either valid OAuth metadata or HTTP 404 (not supported)
  2. MCP Initialize - POST with JSON-RPC initialize method

    • After OAuth check, sends the actual MCP handshake
  3. Tool Discovery - POST with JSON-RPC tools/list method

    • Discovers available tools like change_title
  4. Ongoing tool calls - POST with JSON-RPC

    • Each tool invocation is another HTTP request

Root Cause

MCP SDK 1.26.0 introduced breaking changes (release notes):

"Stateless transport.handleRequest() throws if called more than once"

In startHappyServer.ts, a single StreamableHTTPServerTransport instance is created and reused for all incoming HTTP requests:

const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: undefined
});
await mcp.connect(transport);

const server = createServer(async (req, res) => {
    try {
        await transport.handleRequest(req, res);  // Throws on 2nd+ call in SDK 1.26.0
    } catch (error) {
        res.writeHead(500).end();  // Returns 500 for any error
    }
});

With SDK 1.26.0, either:

  • The transport throws on the OAuth discovery request (unrecognized route that it can't handle)
  • Or it throws on any subsequent request (transport already used)

Either way, the catch block returns HTTP 500, which Claude Code interprets as a server error and fails authentication.

Steps to Reproduce

  1. Install happy-coder 0.13.0 (npm will resolve MCP SDK to 1.26.0)
  2. Start a Happy session: happy
  3. Run /mcp in Claude Code
  4. Attempt to authenticate with Happy MCP server

Expected Behavior

  • OAuth discovery endpoint should return HTTP 404 (not supported)
  • MCP connection should succeed
  • mcp__happy__change_title tool should be available

Actual Behavior

  • OAuth discovery endpoint returns HTTP 500
  • Claude Code shows: Error: HTTP 500 trying to load OAuth metadata from http://127.0.0.1:XXXXX/.well-known/oauth-authorization-server
  • MCP authentication fails
  • Cannot use Happy MCP tools

Diagnostic Evidence

Session MCP server (broken - SDK 1.26.0):

$ curl -v http://127.0.0.1:43527/.well-known/oauth-authorization-server
< HTTP/1.1 500 Internal Server Error
< content-type: text/plain; charset=UTF-8

Daemon server (works - uses Fastify with proper route handling):

$ curl -v http://127.0.0.1:42695/.well-known/oauth-authorization-server
< HTTP/1.1 404 Not Found
< content-type: application/json; charset=utf-8
{"message":"Route GET:/.well-known/oauth-authorization-server not found","error":"Not Found","statusCode":404}

Version comparison:

MCP SDK Version Works?
1.25.3 ✅ Yes
1.26.0 ❌ No

Workaround

Downgrade MCP SDK to 1.25.3:

cd $(npm root -g)/happy-coder
sudo npm install @modelcontextprotocol/sdk@1.25.3 --save-exact
happy daemon stop && happy daemon start
# Start a new happy session to test

However, this drops the changes in @modelcontextprotocol/sdk@1.26.0 that were made to address GHSA-345p-7cg4-v4c7

Suggested Fix

  1. Short-term: Pin @modelcontextprotocol/sdk to ~1.25.3 in package.json until a proper fix is implemented

  2. Long-term: Update startHappyServer.ts to follow the SDK 1.26.0 patterns:

    • Create a new transport instance per request, OR
    • Use the session-based transport pattern from the updated SDK examples
    • Handle non-MCP routes (like OAuth discovery) explicitly and return 404

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions