feat(mcp-cli-bridge): stdin JSON payload mode for multi-argument tool calls#29636
feat(mcp-cli-bridge): stdin JSON payload mode for multi-argument tool calls#29636
Conversation
When reading from stdin, support two new modes:
- '.' sentinel: `safeoutputs add_comment . < payload.json`
- no args with piped stdin: `echo '{...}' | safeoutputs add_comment`
The piped JSON object's properties are extracted as tool arguments,
with schema key normalization applied. This makes it easy for agents
to pass complex multi-argument payloads like add-comment without
shell quoting issues.
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d4d45a9b-d190-45d3-9b19-16b0ac40c0b1
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d4d45a9b-d190-45d3-9b19-16b0ac40c0b1 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot optimize for agentic tool calling efficiency. Update builtin prompt to explain this behavior. |
There was a problem hiding this comment.
Pull request overview
Adds a stdin JSON payload mode to mcp_cli_bridge so entire multi-argument tool inputs can be piped as a single JSON object (via . sentinel or implicitly when stdin is piped and no args are provided), improving ergonomics for complex/multiline payloads.
Changes:
- Introduces
hasStdinJsonPayload(args)to detect JSON-payload stdin usage (['.']or[]with non-TTY stdin). - Extends
parseToolArgsto parse stdin as a JSON object (with schema-key normalization) before falling back to flag parsing. - Updates
main()to pre-read stdin for JSON payload mode, and adds/updates Vitest coverage for the new behavior.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/mcp_cli_bridge.cjs | Adds JSON-payload stdin mode detection and parsing, and wires stdin pre-read into main(). |
| actions/setup/js/mcp_cli_bridge.test.cjs | Adds test coverage for JSON payload mode triggers, parsing behavior, and key normalization/type preservation. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 1
| if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) { | ||
| for (const [key, value] of Object.entries(parsed)) { | ||
| const canonicalKey = resolveSchemaPropertyKey(key, schemaProperties, normalizedSchemaKeyMap, ambiguousNormalizedSchemaKeys); | ||
| result[canonicalKey] = value; | ||
| } |
🧪 Test Quality Sentinel ReportTest Quality Score: 77/100
Test Classification DetailsView All 14 Classified Tests
Flagged Tests — Requires ReviewNo tests were flagged for behavioral quality issues. All 14 new tests verify observable, user-facing contracts of the new i️ Test Inflation NoteFile: This is a mild overage and is not a serious concern here — the new feature has three distinct behavioral dimensions worth thorough coverage (sentinel detection, TTY detection, and JSON parsing variants). The 14 tests map cleanly onto distinct scenarios with no obvious redundancy. No action required, but worth being aware of. Scoring Breakdown
The missing edge-case points are because 6 tests cover only happy-path parsing scenarios (JSON object with valid keys). These are still good tests — they verify key behavioral invariants — but they don't include an error case. Adding one or two table-driven rows with invalid/boundary inputs to the parsing tests would push the score higher in future iterations. Language SupportTests analyzed:
Verdict
📖 Understanding Test ClassificationsDesign Tests (High Value) verify what the system does:
Implementation Tests (Low Value) verify how the system does it:
Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators. References: §25234542649
|
Adds documentation for the new JSON stdin payload mode (.sentinel), positions it as the preferred approach for multi-argument tool calls, and reorganises the stdin-piping section to distinguish between the full-payload mode and single-field - substitution. Agent-Logs-Url: https://github.com/github/gh-aw/sessions/9908e4bf-ffe8-4094-9fd7-978a8149566a Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in d081c45. Updated
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Agents generating complex multi-argument payloads (e.g.
add_commentwith a multiline body) had to rely on per-field-stdin substitution, which only covers one argument at a time. This adds a JSON payload mode so the entire argument object can be piped at once.Changes
hasStdinJsonPayload(args)— new exported predicate; returnstruewhen:args = ['.']— explicit sentinel (always reads stdin)args = []and!process.stdin.isTTY— implicit when stdin is pipedparseToolArgs— before the flag-parsing loop, checks for JSON payload mode: parsesstdinContentas a JSON object, applies schema key normalization (dash↔underscore), and returns properties directly. Falls through to normal parsing on invalid JSON or non-object input.main()—readStdinSync()is now also triggered byhasStdinJsonPayload, not justhasStdinPlaceholder.mcp_cli_tools_prompt.md— updated builtin agent prompt to document the JSON payload mode, position it as the preferred approach for multi-argument calls, and distinguish it from the single-field-substitution.Usage
Values from JSON preserve their native types — no string coercion is applied. Schema key normalization (e.g.
issue-number→issue_number) is applied to JSON keys.