Skip to content

fix(tools): unescape over-escaped quotes in 5 tool descriptors causing invalid JSON in tools/list#444

Open
NavinAgrawal wants to merge 1 commit into
justrach:mainfrom
NavinAgrawal:fix/tools-list-over-escaped-json-descriptors
Open

fix(tools): unescape over-escaped quotes in 5 tool descriptors causing invalid JSON in tools/list#444
NavinAgrawal wants to merge 1 commit into
justrach:mainfrom
NavinAgrawal:fix/tools-list-over-escaped-json-descriptors

Conversation

@NavinAgrawal

Copy link
Copy Markdown

Problem

The tool descriptors for run_swarm, run_agents, review_fix_loop, run_agent, and run_task (lines 221-225 of src/tools.zig) have quotes over-escaped at the source level. Because they sit inside a Zig multi-line raw string (each line prefixed with \\, contents are literal with no escape processing), each backslash in the source becomes a literal backslash in the JSON output. The result is tools/list responses with invalid JSON starting around byte 12805 (offset varies by build), which any standard JSON parser rejects.

Concretely: lines 188-220 use the correct form \\{"name":"X",...} (literal \\ prefix, then plain quotes), but lines 221-225 wrote \\{\"name\":\"X\",...} (extra backslashes before every quote). At runtime, those extra backslashes flow through the raw-string literal unchanged and end up in the emitted JSON, breaking parsing.

Repro

REPO_PATH=$HOME ~/path/to/devswarm --mcp <<'EOF' | tail -n 1 | python3 -c 'import json,sys; json.loads(sys.stdin.read())'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
EOF

On unpatched v0.0.28 (and main HEAD e768863):

json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 12805 (char 12804)

Surfaces in real MCP brokers/clients as "upstream unavailable" errors with the same parser message. Observed via mcp-broker fronting multiple upstream MCP servers.

Fix

This PR collapses the over-escaped quote sequences in those five tool descriptors so the emitted JSON has valid single-backslash-quote escapes inside string values and unescaped quotes at the structural level. The other ~30 descriptors that already use the correct escaping are unchanged.

Verification

Rebuilt with Zig 0.15.2 and re-ran the same initialize + tools/list flow:

  • JSON parses cleanly
  • Tool count: 38 (matches what the binary exposes)
  • All five previously broken tools (run_swarm, run_agents, review_fix_loop, run_agent, run_task) listed with valid input schemas
  • Schemas correctly preserve inner JSON examples like {"finder":"haiku","fixer":"opus"} in the per_agent_model field

End-to-end confirmation via mcp-broker:

broker.search_tools 'swarm parallel agent'
broker.describe_tool devswarm.run_swarm
# Returns valid schema with proper inputSchema, including the per_agent_model example

Notes

  • The version constant in src/main.zig still says 0.0.28; left unchanged so this PR is purely the JSON fix.
  • No tests added since the existing test harness wasn't visible to me; happy to add a tools/list JSON-validity test if you point at the right harness.

…ew_fix_loop/run_agent/run_task descriptors

The tool descriptors for run_swarm (line 221), run_agents (222), review_fix_loop
(223), run_agent (224), and run_task (225) were written with quotes
triple-escaped at the source level. Because they sit inside a Zig
multi-line raw string (\\ prefix per line, contents are literal), each
backslash in the source becomes a literal backslash in the JSON output.
The result was tools/list responses with invalid JSON starting around
byte 12805 (varies by build), producing 'Expecting property name enclosed
in double quotes' errors in any MCP client that parses the response with
a standard JSON parser.

Reproduction (against v0.0.28 binary):
    REPO_PATH=$HOME devswarm --mcp <<< <initialize + tools/list>
    | python3 -c 'import json,sys; json.loads(sys.stdin.readlines()[1])'
    # JSONDecodeError at char ~12805

Fix collapses the over-escaped quote sequences in those five tool
descriptors so the emitted JSON has valid single-backslash-quote
escapes inside string values and unescaped quotes at the structural
level. The other ~30 descriptors that already used correct escaping
are unchanged.

Tested by rebuilding (zig 0.15.2) and running the same initialize +
tools/list flow - JSON parses cleanly, tool count is 38, all previously
broken tools (run_swarm etc.) are listed with valid input schemas.
@NavinAgrawal NavinAgrawal requested a review from justrach as a code owner May 29, 2026 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant