Skip to content

mcp: codedb_bundle should fall through to inline args when arguments={}, plus diagnostic hints #424

@justrach

Description

@justrach

Problem

Real-world MCP clients (forge agent runtimes among them) sometimes send sub-ops inside codedb_bundle with empty arguments and the actual args sitting inline at the op level — e.g.:

{"ops":[{"tool":"codedb_outline","arguments":{},"path":"src/main.zig"}]}

The current dispatcher sees "arguments" is present, treats it as authoritative even though it's empty, and reports missing 'path' argument with received keys: [] — even though path is right there in the op.

The diagnostic is also unhelpful in this state: received keys: [] tells the user "you sent nothing" but doesn't suggest the inline-args fallback that would route around their broken client wrapper.

Steps to reproduce

$ (printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}'; \
   sleep 1; \
   printf '%s\n' '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"codedb_bundle","arguments":{"ops":[{"tool":"codedb_outline","arguments":{},"path":"src/main.zig"}]}}}'; \
   sleep 1) | codedb mcp 2>/dev/null

Bundle reports:

error: all 1 bundle op(s) failed
--- [0] codedb_outline ---
error: missing 'path' argument
received keys: []

Failing tests (3)

test "issue-424-B: bundle falls through to inline args when arguments is empty object" { ... }
test "issue-424-D: received-keys diagnostic hints at inline-args workaround when empty" { ... }
test "issue-424-A: bundle envelope errors carry the 'error:' prefix consistently" { ... }

All three fail on main at e7f177be (v0.2.5805).

Expected

  1. B (medium): when arguments is present but is an empty object, the dispatcher should fall through to inline-args mode rather than treating the empty object as authoritative. Sending {tool, arguments:{}, path} should be equivalent to {tool, path}.
  2. D (medium): when received keys: is empty, append a hint pointing at the inline-args shape so a user with a broken client wrapper can self-recover.
  3. A (low): the bundle dispatcher's "op must be an object" and "missing 'tool' field" errors should be prefixed with error: for consistency with per-tool handlers and the TTY summary parser at mcp.zig:3373.

Fix

In handleBundle (src/mcp.zig ~1843):

  • When op_obj.get("arguments") returns an empty object, treat it the same as when arguments is absent — use op_obj as the inline source.
  • In appendBundleArgKeysDiagnostic (src/mcp.zig ~1710), when the args map is empty, append a one-line hint like (empty — try inline shape: {"tool":"...","path":"..."}).
  • Add error: prefix to the two malformed-envelope branches.

Related

This is a follow-on to #423 (which deduped the diagnostic) and #422 (which made the descriptor explicit about arguments vs args). #422/#423 made the output less misleading for human readers; this issue makes the behaviour tolerant of one common client serialization bug, plus actionable when it can't be fixed server-side.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:p2Medium priority

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions