TL;DR: A single tools/call whose arguments object is nested deeply enough does not just fail that one call: the whole memtrace mcp stdio session closes. The offending call gets no response, and every later request on the same connection also goes unanswered until the client reconnects. The boundary is sharp and reproducible: nesting depth 125 returns a normal error and the session keeps working, depth 126 ends it.
Environment
- memtrace 0.6.11, macOS arm64
memtrace mcp stdio server, one client connection
Repro
After initialize, send a tools/call whose arguments nests N levels deep, then send any normal follow-up call as a liveness probe:
1. tools/call name=find_symbol arguments={"x":{"x":{"x": ... }}} (N levels deep)
2. tools/call name=list_indexed_repositories (liveness sentinel)
N bomb call sentinel session
124 normal error answered ALIVE
125 normal error answered ALIVE <- last surviving depth
126 no response no response CLOSED
127 no response no response CLOSED
Server stderr at depth 126:
ERROR Error reading from stream: serde error recursion limit exceeded at line 1 column 715
Below the boundary the offending call returns a clean error and the session keeps serving. At depth 126 and beyond the connection is gone and the sentinel never gets a reply.
Expected
Return a JSON-RPC error for the offending call and keep the session open, the way depth 125 already does, instead of dropping the connection.
Actual
The session closes. The follow-up sentinel call, and any in-flight work on the same connection, gets no response. The process keeps running (no panic, no crash), so the cost is availability on that one connection: one malformed argument ends that client's session, with only a line of stderr to explain it.
Why it matters
A local stdio client is trusted, so the blast radius of the observed repro is small. The reason to fix it is robustness: a buggy client that accidentally sends a deeply nested argument loses its whole session and every queued request. If a non-stdio transport is ever exposed, the same input could have the same effect from a less trusted caller, which would make it a cheap denial-of-service. Worth bounding either way.
Ask
Keep the session alive when an argument is over-nested: return a JSON-RPC error for that one call instead of closing the connection. Depth 125 already returns a clean error, so reaching the same outcome a couple of levels deeper would settle it. Happy to send a PR.
TL;DR: A single
tools/callwhoseargumentsobject is nested deeply enough does not just fail that one call: the wholememtrace mcpstdio session closes. The offending call gets no response, and every later request on the same connection also goes unanswered until the client reconnects. The boundary is sharp and reproducible: nesting depth 125 returns a normal error and the session keeps working, depth 126 ends it.Environment
memtrace mcpstdio server, one client connectionRepro
After
initialize, send atools/callwhoseargumentsnests N levels deep, then send any normal follow-up call as a liveness probe:Below the boundary the offending call returns a clean error and the session keeps serving. At depth 126 and beyond the connection is gone and the sentinel never gets a reply.
Expected
Return a JSON-RPC error for the offending call and keep the session open, the way depth 125 already does, instead of dropping the connection.
Actual
The session closes. The follow-up sentinel call, and any in-flight work on the same connection, gets no response. The process keeps running (no panic, no crash), so the cost is availability on that one connection: one malformed argument ends that client's session, with only a line of stderr to explain it.
Why it matters
A local stdio client is trusted, so the blast radius of the observed repro is small. The reason to fix it is robustness: a buggy client that accidentally sends a deeply nested argument loses its whole session and every queued request. If a non-stdio transport is ever exposed, the same input could have the same effect from a less trusted caller, which would make it a cheap denial-of-service. Worth bounding either way.
Ask
Keep the session alive when an argument is over-nested: return a JSON-RPC error for that one call instead of closing the connection. Depth 125 already returns a clean error, so reaching the same outcome a couple of levels deeper would settle it. Happy to send a PR.