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
{{ message }}
Repository navigation
createMcpHonoApp: JSON body middleware has a size limit but no time limit (stalled body holds the request open) #3131
createMcpHonoApp's JSON body middleware bounds how many bytes it reads (maxRequestBodySize) but not how long the body takes to arrive. A client that sends part of a body and then stalls keeps the request open with no response from the middleware. The only limit is the underlying HTTP server's own timeout (for Node, server.requestTimeout, 300 s by default).
import{serve}from'@hono/node-server';import{createMcpHonoApp}from'@modelcontextprotocol/hono';import{request}from'node:http';constapp=createMcpHonoApp({host: '127.0.0.1'});app.all('/mcp',(c)=>c.text('unreachable while the body is stalled'));constserver=serve({fetch: app.fetch,port: 0,hostname: '127.0.0.1'},({ port })=>{constreq=request(`http://127.0.0.1:${port}/mcp`,{method: 'POST',headers: {'Content-Type': 'application/json','Content-Length': '100'},},(res)=>console.log('responded',res.statusCode));req.write('{');// 1 of 100 declared bytes, then nothingsetTimeout(()=>{console.log('still open after 3s');req.destroy();server.close();},3000);});
Output: still open after 3s. The request is held until the client leaves or the server's timeout fires.
Expected
An option to bound body arrival time (for example a bodyTimeoutMs), answering 408 and closing the connection when it expires. The readRequestBody helper in @modelcontextprotocol/server could accept an AbortSignal for the same purpose, so adapters can supply their own deadline.
Impact
Low for a loopback development server. For a deployed server, each stalled request holds a connection and a handler slot until the server's timeout.
I am not asking for a particular design, only noting that the size limit has no time counterpart. We document the gap and rely on the server timeout meanwhile.
I would like to work on this if the scope aligns. Proposed narrow main/v2 scope:
Add optional, cancellation-aware request-body reading while preserving existing callers and the 4 MiB default size limit.
Add an opt-in bodyTimeoutMs policy only at the Hono adapter boundary; keep the unconfigured default unchanged.
Map an expired configured deadline to HTTP 408, retain 400 for malformed completed JSON and 413 for oversized bodies, and ensure reader/listener/timer cleanup without dispatching partial requests.
Add deterministic unit and streaming integration coverage for pre-abort, pending-read abort, timeout, cleanup, isolation, and no later tool execution.
I would not extend deadline policy to the other HTTP entry points without separate approval. I also noticed open PR #3028 touches requestBody.ts for the Firefox no-stream fallback; I will rebase/coordinate so this work does not overwrite it.
Could a maintainer confirm this approach and assign the issue before I begin significant implementation?
Activity
fix: serve the local MCP helper with the upstream Hono adapter
Ben-Home commentedon Oct 30, 2026
Muzzy5150 commentedon Oct 31, 2026
I would like to work on this if the scope aligns. Proposed narrow
main/v2 scope:bodyTimeoutMspolicy only at the Hono adapter boundary; keep the unconfigured default unchanged.I would not extend deadline policy to the other HTTP entry points without separate approval. I also noticed open PR #3028 touches
requestBody.tsfor the Firefox no-stream fallback; I will rebase/coordinate so this work does not overwrite it.Could a maintainer confirm this approach and assign the issue before I begin significant implementation?