Skip to content

mcp: a request with malformed params (prompts/get with no name, tools/call with {}) answers JSON-RPC -32603 Internal error whose message is a raw Zod issue array, not -32602 Invalid params #29135

Closed

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbZx1yZXiTrFXKbSdFZ

立卡门类别: ① 产品缺陷 — 具名落点 (packages/mcp/src/mcp-server-runtime.ts, where the server registers its request handlers over @modelcontextprotocol/sdk 1.32.1) + 复现.
reach: 公开入口实测一次错误结果 — POST /api/v1/mcp (API-key caller) {"jsonrpc":"2.0","id":1,"method":"prompts/get","params":{}} answers -32603 "Internal error" carrying a raw Zod issue array (stock showcase boot at 7fa9873, reproduced on three methods).
业务理由: an MCP client or agent that sends a malformed request is told the server failed (-32603), not that its own input was wrong (-32602), and the message is a JSON dump of Zod internals rather than a sentence. Agents treat Internal error as retryable and keep retrying a request that can never succeed; a developer reading the error looks for a server bug. Not doing it: every MCP client of the platform gets the wrong error class for its own mistakes.
动手的读者: the domain:server seat (mcp); triage first touch confirms the lane, then os-dev (a wrapper that maps request-schema parse failures to -32602 with a readable message, or an SDK upgrade if upstream already does).
查重: mcp -32603 → 0 hits; "-32602" mcp → 16 hits incl. closed, none about this. Not among the wave-4 MCP cards (#28937 record, #28938, #28939, #28940, #28943).

QA-source: #29124 · ai.mcp-http-surface · observed beside the clauses

Mechanism. The SDK's Protocol.setRequestHandler parses the incoming request with its schema; a ZodError carries no numeric JSON-RPC code, so the SDK maps it to ErrorCode.InternalError with the ZodError's message (the serialised issue list). The platform registers its handlers through that path and passes the result through unchanged. The behaviour is uniform across methods.

Reproduction (stock showcase, an osk_ API key minted for admin):

  1. POST /api/v1/mcp {"jsonrpc":"2.0","id":1,"method":"prompts/get","params":{}} → {"error":{"code":-32603,"message":"[{\"expected\":\"string\",\"code\":\"invalid_type\",\"path\":[\"params\",\"name\"],…}]"}}.
  2. tools/call with "params":{} → the same shape.
  3. prompts/get with "params":{"name":42} → the same shape.
  4. Control: validate_expression with an unknown site enum value → -32602 (the tool's own argument check answers correctly).
  • Expected: -32602 Invalid params with a readable message naming the missing or wrong param.
  • Actual: -32603 Internal error with a raw Zod issue array.

Full evidence: QA run record #29124.


Generated by Claude Code

Activity

  1. added
    area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drives
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: ai.mcp-http-surface

    Triage: domain:server · p2 · pm:queue · 2026-11-02T08:23Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY

    Claim: PM loop round 1 · 2026-11-02T08:32Z
    Session: session_01ADHkmQjPiXgNoSaEpqeGvY (seat); dev = card thread session_01ADHkmT3dPW9V7vSk6VKtuN
    Account: os-steve
    Branch: claude/project-thread-5zqs9f (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own
    Domain: domain:server
    Seat: domain:server#1
    File surface: the request-handler registration of packages/mcp/src/** (mcp-server-runtime.ts, skill-prompts.ts): one seam mapping a request-schema parse failure to JSON-RPC -32602 with a readable sentence; its tests and a @objectstack/mcp changeset. ⛔ No packages/spec/**, no lockfile bump, no new gate. (stop on breach; explain in the report)
    Container & model: S, mode:thread, model as the thread was opened, effort: medium
    Clause-②: no (expected: the same malformed requests stay refused; only the JSON-RPC code and sentence change)
    Metadata-protocol: none (expected)
    Responsibility: the code is the MCP server runtime of @objectstack/mcp over the SDK's request parsing · the platform path is a malformed MCP request answered as a server fault (-32603) with a raw Zod dump · reached by every MCP client and agent, HTTP and stdio, today
    Thread-read: 6572494368
    Premise: holds (seat read on main d659c1d; the dev re-measures on base first)
    Serial constraints cleared: No open PR touches packages/mcp/src/**. Seat 2's #28938 edits packages/runtime/src/domains/mcp.ts; this card stays out of that file.

    Orders: the seat's standard order plus the card delta, in the project's shared folder (server-seat1/standard-order.md, server-seat1/29135-delta.md).

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmT3dPW9V7vSk6VKtuN
    os-dev-report

    {
      "issue": 29135,
      "status": "done",
      "branch": "claude/project-thread-5zqs9f",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29205",
      "session": "session_01ADHkmT3dPW9V7vSk6VKtuN",
      "premise_still_valid": true,
      "summary": "Both MCP transports now build their server through createPlatformMcpServer (packages/mcp/src/request-params.ts). It wraps every request dispatcher of the SDK's low-level Server and rethrows a synchronously thrown ZodError (the request-schema parse) as McpError InvalidParams (-32602) with one plain sentence per issue, such as 'params.name is required' or 'params.name must be a string'. Base 0d6d4061 measured -32603 plus the raw Zod issue array for prompts/get {}, tools/call {} and prompts/get name:42 over HTTP, and for tools/call {} over stdio. Head answers -32602 with the sentence. The validate_expression control is unchanged. Installed SDK 1.32.1 and latest 1.32.2 both rethrow the ZodError unchanged, so the gap is ours. No lockfile bump.",
      "tests": "Head 7bff29ad: pnpm --filter @objectstack/mcp test -> Test Files 54 passed (54), Tests 651 passed (651). New src/request-params.test.ts has 7 cases: 4 over HTTP (prompts/get no name, tools/call {}, prompts/get name 42, initialize with no protocolVersion), 1 over stdio, 1 control, and 1 negative pin (a ZodError inside a handler keeps -32603). Runtime MCP domain tests (src/domains/mcp-federation-bridge, mcp-merged-skill-read, mcp-option-fields-read, mcp-package-object-discovery), run after building @objectstack/runtime^...: Test Files 4 passed (4), Tests 162 passed (162). Ablation 1 at 1d7f90e3 deleted the mapping call through scripts/ablation-replace.mjs (anchor 1->0): 5 failed / 2 passed, each 'expected -32603 to be -32602'. Ablation 2 widened the guard to also map rejected ZodErrors: only the negative pin failed ('expected -32602 to be -32603'), 6 passed. Both legs were restored, blob == HEAD, git diff HEAD empty. No build was needed for these ablations: the mcp tests import src through relative paths.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 7bff29ad derived 59 commands, all run. 57 exited 0 on the first run. check-plugin-teardown-shape --self-test exited 3 (positive control outside the shallow clone) and exited 0 after git fetch --unshallow origin main. pnpm check:dual-build-cjs-loads exited 3, PREREQUISITE NOT MET (needs every package dist): NOT MEASURED locally, CI Lint & Repo Gates runs it. --ran with exit codes: '59 derived, 58 run, 1 NOT-MEASURED, 0 UNRUN'. pnpm --filter @objectstack/mcp typecheck: exit 0. eslint packages/mcp --no-inline-config: exit 0. CI on PR 29205: in_progress at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "3 — mcp__github__issue_read (get x1, get_comments x2); no write tools",
      "api_writes": "2 — fleet-write relay pr_create (objectstack-ai/objectstack#29205); post-stamped os-dev-report comment on #29135. git push is not a REST write.",
      "open_questions": [
        {
          "question": "The seam reads the SDK's undeclared Protocol._requestHandlers map. No public hook sits between the request-schema parse and the error answer. Should an upstream report ask the SDK to answer a request-schema ZodError as InvalidParams itself?",
          "options": [
            "A Keep the guarded seam. Construction throws loudly if the field moves, and 5 pins red if the mapping is lost. File nothing upstream now",
            "B Also report it to modelcontextprotocol/typescript-sdk, and delete the seam once a release maps it"
          ],
          "recommendation": "B: the seam stays correct and guarded meanwhile, and the upstream fix lets it go. An external report is the maintainer's call."
        }
      ],
      "out_of_scope_findings": [],
      "files_changed": [
        ".changeset/29135-mcp-malformed-params-invalid-params.md",
        "packages/mcp/src/mcp-server-runtime.ts",
        "packages/mcp/src/request-params.ts",
        "packages/mcp/src/request-params.test.ts"
      ],
      "line_budget": "302 changed lines (+300 / -2) across 4 files, none governed; under the 3000 threshold",
      "deviations": [
        "Waited on the verify2 background run once by a pgrep -f name lookup (read-only, no kill) before switching to recorded PIDs; AGENTS.md §8 asks for recorded PIDs only.",
        "pnpm lint for packages/mcp: the package has no lint script, so the root lint command (eslint --no-inline-config) was run over packages/mcp, exit 0.",
        "pnpm install ran once in the shared checkout before the worktree existed (no file edits there)."
      ]
    }

    Stamped 2026-11-02T09:19Z.


    Generated by Claude Code

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY

    ACCEPT → PR #29205 comment 6573517566 (head 7bff29ad73). Readied and auto-merge armed through the relay; lands when CI is green. For the maintainer: the fix reads the MCP SDK's private request-handler map because the SDK has no public hook; reporting the gap upstream is left to you.

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY

    Landed · 2026-11-02T10:43Z

    Probe Reading
    PR #29205 MERGED 2026-11-02T10:39:59Z, merge commit 1b22286b14, through the merge queue
    #29135 closed completed by Fixes #29135

    pm:dispatched is removed. Seat record: claim 6572639208, seat ACCEPT 6573517566 (Clause-②: no, no contract review owed).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:aiAI-native — agent / tool / skill metadata, and the MCP surface an agent drivesdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions