Skip to content

fix: --output json emits valid JSON instead of util.inspect#89

Open
shawnduggan wants to merge 2 commits intosteipete:mainfrom
shawnduggan:fix/json-output-valid-json
Open

fix: --output json emits valid JSON instead of util.inspect#89
shawnduggan wants to merge 2 commits intosteipete:mainfrom
shawnduggan:fix/json-output-valid-json

Conversation

@shawnduggan
Copy link

@shawnduggan shawnduggan commented Feb 28, 2026

Summary

mcporter call <server.tool> --output json outputs util.inspect() format (unquoted keys, single quotes, [Object] placeholders) instead of valid JSON when wrapped.json() returns null.

This breaks programmatic consumers like OpenClaw's qmd memory backend, which JSON.parse()s stdout and gets SyntaxError: Expected property name or '}' in JSON at position 4.

Root cause

In printCallOutput (output-utils.ts), the json case falls back to printRaw() when wrapped.json() returns null. printRaw() calls util.inspect(raw, { depth: 2 }), which is not valid JSON.

This happens when an MCP server returns structuredContent with fields other than .json/.data (e.g. qmd returns { results: [...] }) — tryParseJson doesn't recognize it, json() returns null, and the fallback emits inspect output.

Fix

In the json output case, try JSON.stringify(raw) before falling back to printRaw(). This ensures --output json always emits valid JSON without affecting auto/text/markdown output modes.

Test plan

  • Existing result-utils.test.ts tests pass (16/16)
  • Existing cli-output-utils.test.ts tests pass (1/1)
  • TypeScript compiles cleanly
  • Manual test: mcporter call qmd.search --args '{"query":"test"}' --output json now emits parseable JSON

Fixes #80

When `wrapped.json()` returns null (e.g. when structuredContent has
fields other than .json/.data like qmd's .results), the json output
mode fell through to printRaw() which uses util.inspect() — producing
output with unquoted keys, single quotes, and [Object] placeholders
that is not valid JSON.

Two fixes:
1. tryParseJson now returns structured objects directly when they don't
   have .json/.data wrappers (they are already parsed data)
2. printCallOutput json case falls back to JSON.stringify(raw) before
   printRaw, ensuring valid JSON output

Fixes steipete#80
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e499d05ae1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +104 to +106
// Return the object itself — it is already a parsed structure (e.g. structuredContent
// with a results array from MCP servers like qmd).
return value;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep auto output from treating any structured object as JSON

Returning every object from tryParseJson makes wrapped.json() succeed for responses like { structuredContent: { text: "..." } }, and printCallOutput's auto mode checks json() before markdown()/text() (src/cli/output-utils.ts), so default calls now print JSON objects instead of the human-readable text/markdown they previously emitted. This widens the fix beyond --output json and regresses default CLI behavior for servers that include both content and non-wrapper structuredContent fields.

Useful? React with 👍 / 👎.

Returning every object from tryParseJson makes wrapped.json() succeed
for responses like { structuredContent: { text: "..." } }, causing
auto mode to print JSON instead of human-readable text/markdown.

The output-utils.ts fix (JSON.stringify fallback in the json case) is
sufficient on its own — it only affects --output json without changing
default CLI behavior.
shawnduggan added a commit to shawnduggan/openclaw-docker that referenced this pull request Feb 28, 2026
mcporter 0.7.3's --output json emits util.inspect() instead of valid
JSON, causing OpenClaw's qmd memory search to fail with a JSON parse
error. Disable until fix lands (PR steipete/mcporter#89).
Jah-yee added a commit to Jah-yee/mcporter that referenced this pull request Mar 3, 2026
Issue steipete#89: When wrapped.json() returns null, fallback to JSON.stringify(raw)
instead of util.inspect which produces invalid JSON.

This ensures --output json always outputs valid JSON that can be parsed.
@Cotch22
Copy link

Cotch22 commented Mar 6, 2026

+1

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.

call's --output json flag does not output valid json

2 participants