modelcontextprotocol / modelcontextprotocol/typescript-sdk

Claude.AI hangs with 408 timeout when MCP tool response JSON contains U+2028 (LINE SEPARATOR) or U+2029 (PARAGRAPH SEPARATOR)

Open
#2,155 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug fix proposed P2 ready for work
Dominant language
TypeScript
Stars
13.4k
Forks
2.2k
Avg merge
3d 15h
Merged PRs (30d)
4

Description

Summary

Claude.AI times out with 408 (Waited 300.0 seconds) for certain MCP tool calls, even though the MCP server logs show a successful and fast 200 response.
This appears to happen when upstream JSON data includes raw Unicode line/paragraph separators in string fields:

  • U+2028 LINE SEPARATOR
  • U+2029 PARAGRAPH SEPARATOR

Environment

  • Client: Claude.AI (web)
  • Transport: MCP Streamable HTTP via POST /mcp
  • Server runtime: Node.js + TypeScript
  • MCP SDK: @modelcontextprotocol/sdk ^1.29.0
  • Hosting: Railway
  • Backend API source: KEXP public API

Actual Behavior

  • Claude.AI tool call hangs and eventually returns 408 timeout.
  • Server logs show:
    • Request received
    • Tool executed
    • 200 response returned quickly
  • Issue is reproducible with one specific record containing unusual Unicode content, while adjacent records work normally.

Expected Behavior

  • Tool call should succeed and return parsed response.
  • If parsing fails client-side, client should fail fast with a parse error, not hang until timeout.

Repro (Minimal)

Create a minimal MCP tool that returns JSON containing raw U+2028 in a string value.

Example server snippet
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = new McpServer({ name: 'unicode-repro', version: '1.0.0' });

server.tool('repro_u2028', 'Returns JSON with U+2028 in a string', {}, async () => {
  const payload = {
    comment: 'Line one.\u2028Line two.'
  };

  return {
    content: [
      {
        type: 'text',
        text: JSON.stringify(payload)
      }
    ]
  };
});

const transport = new StdioServerTransport();
await server.connect(transport);
Repro steps
  1. Connect this MCP server to Claude.AI.
  2. Invoke the repro_u2028 tool.
  3. Observe timeout behavior.
  4. Change the payload so separators are escaped in transport text (for example replacing raw U+2028 with escaped sequence form before parse/forward).
  5. Re-run and observe successful response.

Why this seems important

U+2028 and U+2029 are valid in JSON text, but historically treated as line terminators in JavaScript contexts.
A parser/transport boundary handling bug could cause a stall instead of a deterministic parse error.

Server-Side Workaround Confirmed

Sanitizing response text before JSON.parse resolved the issue in production for the affected records.

const text = await response.text();
const sanitized = text
  .replace(/\u2028/g, '\\u2028')
  .replace(/\u2029/g, '\\u2029');
const data = JSON.parse(sanitized);

Request

Please investigate Claude.AI MCP response parsing/transport handling for payloads containing U+2028 and U+2029, and return a deterministic error or successful parse instead of timeout behavior.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the Streamable HTTP POST /mcp response path and JSON parsing boundary, using the supplied repro_u2028 tool with raw U+2028 and U+2029. Trace the response handling and add coverage for both separators. Done means a successful parsed tool response or an immediate deterministic parse error instead of a timeout.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.