Skip to content

refactor(connection): dedupe fetch-tools' tool mapping, fix STDIO output-schema leniency - #5555

Open
pedrofrxncx wants to merge 1 commit into
mainfrom
refactor/dedupe-fetch-tools-schema-leniency-w4
Open

refactor(connection): dedupe fetch-tools' tool mapping, fix STDIO output-schema leniency#5555
pedrofrxncx wants to merge 1 commit into
mainfrom
refactor/dedupe-fetch-tools-schema-leniency-w4

Conversation

@pedrofrxncx

@pedrofrxncx pedrofrxncx commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Source: reduction + bug found while auditing apps/api/src/tools/connection/fetch-tools.ts for hardening issues (SSRF is already covered by open PR #5516 — not duplicated here).

What/why: The HTTP, SSE, and STDIO tool-fetch branches each hand-rolled an identical block mapping MCP-listed tools to our stored ToolDefinition shape. Collapsed the three into one mapListedTools() helper (net -38/+24 in the file). Unifying it surfaced a real inconsistency: HTTP and SSE relaxed outputSchema with additionalProperties: true, but STDIO stored it verbatim.

Failure scenario / regression: apps/api/src/tools/registry/schema.ts documents why this matters — MCP clients re-validate a tool's structuredContent with Ajv, which enforces additionalProperties: false by default and rejects extra fields with -32602: Structured content does not match the tool's output schema. A STDIO-backed dev connection (local-mode only) whose tool returns any field not modeled in its declared outputSchema would hit that rejection, while the identical HTTP/SSE tool would not — same tool shape, transport-dependent breakage. Now all three transports get the same leniency.

Verification: added apps/api/src/tools/connection/fetch-tools.test.ts, a unit test for the extracted pure mapListedTools() helper covering: empty list → null, outputSchema gets additionalProperties: true merged in, and no outputSchema stays undefined. Reviewer can run:

bun test apps/api/src/tools/connection/fetch-tools.test.ts

Locally ran: bun run fmt, cd apps/api && bunx tsc --noEmit (clean), the targeted test above (3 pass), and bunx oxlint on both changed files (0 warnings/errors). Full CI validates the rest.


Summary by cubic

Deduped MCP tool-to-ToolDefinition mapping in fetch-tools and aligned outputSchema leniency across HTTP, SSE, and STDIO. Prevents STDIO-only Ajv revalidation errors when tools return extra fields.

  • Bug Fixes

    • STDIO now relaxes outputSchema with additionalProperties: true, matching HTTP/SSE and avoiding -32602 rejections for extra fields.
  • Refactors

    • Added mapListedTools() and reused it in all transports to remove three near-identical mappings.
    • Added apps/api/src/tools/connection/fetch-tools.test.ts to cover empty lists, schema leniency, and absent outputSchema.

Written for commit ee51c35. Summary will update on new commits.

Review in cubic

…put-schema leniency

Reduction: HTTP/SSE/STDIO each hand-rolled the identical MCP-tool-to-ToolDefinition
mapping (3 near-identical blocks) — collapsed into one mapListedTools() helper.

While unifying it, fixed a real inconsistency it exposed: HTTP/SSE relaxed
outputSchema with additionalProperties: true, but STDIO stored it verbatim.
MCP clients re-validate tool structuredContent with Ajv (additionalProperties:
false by default per apps/api/src/tools/registry/schema.ts's documented
pattern), so a STDIO-backed tool returning any field its outputSchema doesn't
model gets rejected with -32602 "Structured content does not match the tool's
output schema" — a failure HTTP/SSE tools don't hit for the same shape.

Net: -38/+24 in fetch-tools.ts, plus a new unit test for the extracted helper.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 2 files

Re-trigger cubic

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.

1 participant