Skip to content

fix(hyperdx): tolerate JSON-encoded array/number params from MCP transport#432

Merged
JonasJesus42 merged 1 commit intomainfrom
vibegui/fix-hdx-mcp-param-serialization
May 7, 2026
Merged

fix(hyperdx): tolerate JSON-encoded array/number params from MCP transport#432
JonasJesus42 merged 1 commit intomainfrom
vibegui/fix-hdx-mcp-param-serialization

Conversation

@vibegui
Copy link
Copy Markdown
Contributor

@vibegui vibegui commented May 7, 2026

Summary

A real HyperDX MCP session against the deployed worker (sites-hyperdx.decocache.com/mcp) hit repeated zod validation failures because the MCP transport was JSON-encoding structured params before delivering them:

  • QUERY_CHART_DATAseries rejected as string (expected "array", received "string") — 6+ failures
  • GET_LOG_DETAILSgroupBy rejected as string — 2–3 failures
  • SEARCH_LOGSlimit rejected as string — 1 failure

Some MCP bridges stringify nested arrays/numbers, which is awkward for the agent to recover from. The fix is to make our input schemas tolerant on both shapes.

Changes

  • New hyperdx/server/lib/coerce.ts: tiny helpers
    • arr(schema)z.preprocess that JSON-parses string inputs that look like arrays/objects, then defers to the inner schema
    • num()z.coerce.number()
  • Wrap every input array/number across HyperDX tools (hyperdx.ts, dashboards.ts, alerts.ts) and shared schemas (types.ts)
  • Output schemas untouched — issue is one-directional (client → server)
  • Mirrors the pattern already in vtex/server/tools/custom/reorder-collection.ts
  • Adds coerce.test.ts (12 tests) covering passthrough, JSON parsing, malformed fallthrough, optional/default, nested object arrays, numeric coercion, and end-to-end queryChartDataInputSchema parsing of stringified series + nested stringified groupBy

Test plan

  • bun test (47 pass, 0 fail across hyperdx)
  • bun run build (compiles cleanly)
  • Smoke test: queryChartDataInputSchema.parse({ series: '[{...}]', granularity: '5 minute' }) succeeds
  • Smoke test: { groupBy: '["service","level"]', limit: "100" } parses to { groupBy: ["service","level"], limit: 100 }
  • After merge + deploy, retry the failing calls from the original session against the live MCP

🤖 Generated with Claude Code


Summary by cubic

Allows HyperDX tools to accept JSON-encoded arrays/objects and numeric strings from some MCP transports, fixing validation errors on inputs like series, groupBy, and limit. Improves compatibility with real MCP sessions without changing outputs.

  • Bug Fixes
    • Added arr() and num() coercion helpers in hyperdx/server/lib/coerce.ts to parse JSON-looking strings and numeric strings before validating with zod.
    • Applied to all array/number inputs in hyperdx.ts, dashboards.ts, alerts.ts, and shared schemas in types.ts. Output schemas unchanged.
    • Added coerce.test.ts with unit tests and an end-to-end parse test for queryChartDataInputSchema.

Written for commit 4a22a81. Summary will update on new commits.

…sport

Some MCP transport bridges JSON-stringify structured params (arrays, objects)
and numeric params before delivering them to the server. Real session reports:

  - QUERY_CHART_DATA: series rejected (expected array, received string) — 6+ failures
  - GET_LOG_DETAILS: groupBy rejected (expected array, received string) — 2-3 failures
  - SEARCH_LOGS: limit rejected (expected number, received string)

Add a small coerce helper (arr() / num()) and wrap every array and number
input field across the HyperDX tools so they accept either the raw type or
a JSON/numeric string. Mirrors the same pattern already in
vtex/server/tools/custom/reorder-collection.ts.

Adds unit tests for the helper and the queryChartDataInputSchema.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JonasJesus42 JonasJesus42 merged commit 7f9dde1 into main May 7, 2026
2 checks passed
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.

2 participants