Summary
When an agent uses the documented JSON-payload form —
safeoutputs <tool> . < payload.json
printf '{...}' | safeoutputs <tool> .
— and the payload is not valid JSON, mcp_cli_bridge.cjs silently discards the parse
error and falls through to flag parsing. Flag parsing finds no flags, so the bridge logs:
[warning] [safeoutputs] No arguments provided for '<tool>'; showing command help instead of calling the tool
and prints the command help.
The message is inaccurate in a way that actively misleads. Arguments were provided and
stdin was read; the payload simply failed JSON.parse. An agent reading that output
concludes the CLI does not implement stdin at all — which is what happened to us, twice,
including one agent that filed a bug against its own tooling saying exactly that.
Why this matters more for agents than for humans
A human sees "no arguments provided", looks at their command line, and spots the typo. An
agent sees it, believes the documented interface is unavailable, and abandons the work it
has already done. In our case the payload was a code-review verdict assembled by the model:
Markdown prose containing backticks, quotes and backslashes, embedded into a single-line
JSON string. That is exactly the input most likely to produce invalid JSON, and the least
likely to be diagnosed from a help screen.
Measured in one repository over two weeks: 92 failed runs, each discarding a completed
review. Three sampled payloads, all invalid, all reported as "no arguments provided":
2871 bytes -> Expecting ',' delimiter: line 1 column 2159
6464 bytes -> Invalid \escape: line 1 column 5801
6121 bytes -> Expecting ',' delimiter: line 1 column 1399
The stdin path itself is fine
Worth stating plainly, since it took us a while to establish: JSON mode works. A run in
the same workflow, same version, same invocation shape, with valid JSON on stdin was
accepted and emitted normally. --body . per-field stdin also works and read 5678 bytes in
another run. There is no bug in readStdinSync() or in hasStdinJsonPayload() — the only
defect is the swallowed exception and the misleading message that follows it.
Location
actions/setup/js/mcp_cli_bridge.cjs, in parseToolArgs (v0.86.2, around lines 770–785):
if (trimmedStdin) {
try {
const parsed = JSON.parse(trimmedStdin);
...
} catch {
// Not valid JSON; fall through to normal flag-based argument parsing.
}
}
The fall-through is reasonable when args contains real flags. It is not reasonable when
args is exactly ['.'], because . is unambiguously a request for JSON-payload mode —
there is nothing to fall through to, and the resulting help screen describes a failure
that did not occur.
Reproduction
printf '{"body":"a "quote" breaks it"}' | safeoutputs add_comment .
# observed: "No arguments provided for 'add_comment'; showing command help"
# expected: a JSON parse error naming the offending position
Suggested fix
When args is ['.'] (or empty with piped stdin) and JSON.parse throws, fail with the
parse error rather than falling through:
Error: stdin is not valid JSON: Invalid \escape at line 1 column 5801.
JSON payload mode was requested with '.'. Pass --key value flags instead, or correct the JSON.
Two smaller things would each have saved us independently:
Bridge invoked: argumentCount=N counts argv only, so a JSON-mode call always logs
argumentCount=1. Logging whether stdin was read, and how many bytes, would make the
distinction visible in run logs.
- The "no arguments provided" wording could be reserved for the case where genuinely
nothing was supplied.
Priority
Low urgency for us — we have routed around it by having agents pass Markdown through
--body . and never hand-assemble JSON, which is more robust anyway. Raising it because
the diagnostic sends agents to a confident wrong conclusion, and because the generated
prompt preamble recommends the JSON form to every agent:
For multiple or complex arguments, pipe a JSON object on stdin using `.` as the sentinel:
printf '{"item_number":42,"body":"### Title\n\nBody."}' | safeoutputs add_comment .
Version: v0.86.2. Happy to open a PR against parseToolArgs if the suggested direction
looks right.
Summary
When an agent uses the documented JSON-payload form —
— and the payload is not valid JSON,
mcp_cli_bridge.cjssilently discards the parseerror and falls through to flag parsing. Flag parsing finds no flags, so the bridge logs:
and prints the command help.
The message is inaccurate in a way that actively misleads. Arguments were provided and
stdin was read; the payload simply failed
JSON.parse. An agent reading that outputconcludes the CLI does not implement stdin at all — which is what happened to us, twice,
including one agent that filed a bug against its own tooling saying exactly that.
Why this matters more for agents than for humans
A human sees "no arguments provided", looks at their command line, and spots the typo. An
agent sees it, believes the documented interface is unavailable, and abandons the work it
has already done. In our case the payload was a code-review verdict assembled by the model:
Markdown prose containing backticks, quotes and backslashes, embedded into a single-line
JSON string. That is exactly the input most likely to produce invalid JSON, and the least
likely to be diagnosed from a help screen.
Measured in one repository over two weeks: 92 failed runs, each discarding a completed
review. Three sampled payloads, all invalid, all reported as "no arguments provided":
The stdin path itself is fine
Worth stating plainly, since it took us a while to establish: JSON mode works. A run in
the same workflow, same version, same invocation shape, with valid JSON on stdin was
accepted and emitted normally.
--body .per-field stdin also works and read 5678 bytes inanother run. There is no bug in
readStdinSync()or inhasStdinJsonPayload()— the onlydefect is the swallowed exception and the misleading message that follows it.
Location
actions/setup/js/mcp_cli_bridge.cjs, inparseToolArgs(v0.86.2, around lines 770–785):The fall-through is reasonable when
argscontains real flags. It is not reasonable whenargsis exactly['.'], because.is unambiguously a request for JSON-payload mode —there is nothing to fall through to, and the resulting help screen describes a failure
that did not occur.
Reproduction
Suggested fix
When
argsis['.'](or empty with piped stdin) andJSON.parsethrows, fail with theparse error rather than falling through:
Two smaller things would each have saved us independently:
Bridge invoked: argumentCount=Ncounts argv only, so a JSON-mode call always logsargumentCount=1. Logging whether stdin was read, and how many bytes, would make thedistinction visible in run logs.
nothing was supplied.
Priority
Low urgency for us — we have routed around it by having agents pass Markdown through
--body .and never hand-assemble JSON, which is more robust anyway. Raising it becausethe diagnostic sends agents to a confident wrong conclusion, and because the generated
prompt preamble recommends the JSON form to every agent:
Version: v0.86.2. Happy to open a PR against
parseToolArgsif the suggested directionlooks right.