Skip to content

Accept omitted params per JSON-RPC 2.0 §4 - #106

Merged
ghostbuster91 merged 3 commits into
mainfrom
i104
May 29, 2026
Merged

ghostbuster91 merged 3 commits into
mainfrom
i104

Conversation

@ghostbuster91

@ghostbuster91 ghostbuster91 commented May 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #104.

Problem

Per JSON-RPC 2.0 §4 the params member MAY be omitted. The dispatcher
rejected any request whose params field was absent (or null) with
-32600 InvalidRequest "Missing payload", making spec-compliant clients
unable to call parameterless methods (e.g. the official MCP TypeScript
SDK calling tools/list).

Approach

  1. Payload.Empty sentinel = Payload(Json.obj()).
  2. RequestMessage.params / NotificationMessage.params change from
    Option[Payload] to Payload — None is no longer expressible.
  3. RawMessage.toMessage normalizes an absent/null wire params
    to Payload.Empty.
  4. RawMessage.from elides the params field on the wire when it
    equals Payload.Empty (spec treats omitted and {} as equivalent).
  5. MessageDispatcher drops the now-impossible None branches —
    the pattern match shrinks from 6 cases to 4.

The earlier commits in this PR are intermediate iterations of the same
fix; happy to squash before merging.

Binary compatibility

This is a binary-breaking change to public case-class signatures
(InputMessage.RequestMessage / NotificationMessage). MIMA isn't
configured with previous artifacts so CI won't catch it — worth calling
out in release notes / version bump.

Test plan

  • core/test and core3/test — RawMessageSpec covers wire-layer
    decoding (omitted / null / notification) and serialization elision.
  • fs2/test and fs23/test — end-to-end tests via FS2Channel
    parsing raw JSON for the three relevant shapes.
  • smithy4sTests/test and smithy4sTests3/test — existing suite
    still green.
  • scalafmtCheckAll.

🤖 Generated with Claude Code

ghostbuster91 and others added 3 commits May 27, 2026 12:39
Per JSON-RPC 2.0 §4 the `params` member MAY be omitted. The dispatcher
now normalizes an absent or null `params` to an empty object before
running the endpoint codec, so parameterless methods are reachable from
spec-compliant clients (e.g. MCP TypeScript SDK calling `tools/list`).
Push the empty-params default down from `MessageDispatcher` into
`RawMessage.toMessage`, so absent/null `params` is normalized to `{}`
as the JSON message is decoded. The dispatcher keeps its original
pattern match; the `None` branches are now only reachable via direct
programmatic construction.

Tests parse messages from raw JSON to exercise the wire-layer fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace `params: Option[Payload]` on `RequestMessage` and
`NotificationMessage` with `params: Payload`, introducing a
`Payload.Empty` (= `{}`) sentinel. The wire decoder normalizes
absent/null params to `Payload.Empty`; the encoder elides the field
when it equals `Payload.Empty` (per spec, omitted and empty-object
params are equivalent).

This removes the dead "Missing payload" branches from the dispatcher
and the wire-vs-programmatic construction inconsistency.

Binary-breaking: case class signatures changed.
@ghostbuster91 ghostbuster91 changed the title I104 Accept omitted params per JSON-RPC 2.0 §4 May 27, 2026
@ghostbuster91
ghostbuster91 marked this pull request as ready for review May 27, 2026 12:04
@ghostbuster91
ghostbuster91 merged commit c7484d9 into main May 29, 2026
3 checks passed
@ghostbuster91
ghostbuster91 deleted the i104 branch May 29, 2026 14:29
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.

Server rejects requests with omitted params as -32600 Missing payload

2 participants