Skip to content

v0.8.13

Choose a tag to compare

@panyam panyam released this 26 Oct 07:18
· 27 commits to main since this release

v0.8.13

The stateless wire now behaves like the session wire, and stdio serves it. Before this release a
SEP-2575 stateless request went through its own copy of four handlers, which skipped input-schema
validation, prompt-argument checks, timeouts and the completion cap (agni issue 1172), and it never
met the metrics or trace middleware, the static allowed roots, or panic recovery. Both wires now
run one request path and one method table, and each place they differ is an explicit branch. The
room bridge also gets two fixes agni's viewer tabs were waiting on (agni issue 1173).

Fixed (stateless wire)

  • tools/call, prompts/get, resources/read and completion/complete run the session
    handlers.
    The stateless wire's copies are gone, so a stray tool argument is now an
    isError result rather than a successful call, prompt arguments are checked against their
    schema (-32602), per-entry Timeouts and WithToolTimeout reach the handler, completion
    values are capped at 100, and handler errors carry the same prompt "x": prefix on both wires.
    (issue 1637, PR 1638)
  • stdio serves the stateless wire. A ClientModeStateless client over WithIOTransport used
    to get -32600 server not initialized, and an adaptive one failed Connect. stdio now routes
    each message by the same header-free classifier HTTP uses, and it no longer answers
    notifications, which it used to do with an id: null error frame before initialize.
    (issue 1637, PR 1639)
  • Adaptive clients fall back from session-only servers. A legacy-only mcpkit transport answers
    a session-less server/discover with -32601 instead of a 400, and the client's probe also
    reads a plain-text 400 (what go-sdk and the TypeScript SDK send) as "no stateless wire here". A
    400 carrying a JSON-RPC error such as -32020 stays fatal. (issue 1637, PR 1639)
  • A stateless request gets the session wire's per-request path: the metrics and trace
    middleware, the Mcp-Method response header, WithContentChunkMethod,
    NotifyResourceUpdated, panic recovery (-32603 rather than a dropped connection, or a dead
    process over stdio), and the static WithAllowedRoots policy, which core.IsPathAllowed used to
    answer true for on this wire. server/discover now runs inside the middleware chain, as
    initialize does on the session wire. (issue 1625, PR 1644)
  • One method table for both wires. The stateless resources/list, resources/templates/list
    and prompts/list honour the cursor like the session wire (invisible until a page size is set,
    issue 1356), and WithNotifyInterceptor sees notifications a handler sends on the stateless SSE
    response. (issue 1625, PR 1645)

Changed

  • Breaking: server/stateless no longer holds a dispatcher. stateless.Dispatcher,
    stateless.New and the stateless.Backend interface are gone; the stateless dispatch lives in
    server now. server/stateless keeps Mode and its helpers, DiscoverResult, the
    subscriptions/listen frames, HTTPStatusForCode and RequestMetaFromContext, which is
    everything code outside server used. Nothing outside mcpkit implemented Backend, so no
    downstream repo needs edits. (issue 1625, PRs 1644 and 1645)
  • core.SetAllowedRoots and core.SetNotifyResourceUpdated work without a session. Same
    signatures; with no session in ctx they attach to the returned ctx instead of doing nothing.
    (PR 1644)
  • In dual mode _meta wins over the session id, written down and pinned by a test. A client
    that initialized at 2026-07-28 and sends the required _meta is served by the stateless
    dispatcher; ModeLegacyOnly still serves the session. No behaviour change. (issue 1628, PR 1642)

Changed (room bridge)

  • rooms-channel watches the room attach reports, from the result's
    structuredContent.resource, so an agent that attaches with the host's own argument through
    WithRoomOf gets room events. Before, it called watch("") and nothing arrived. detach reports
    resource too, and the front end's bridge client pins the session wire. (issue 1640, PR 1643)
  • @panyam/mcpkit-rooms surfaces refused tools. joinToolRoom takes onToolRefused and
    exposes refusedTools, for the notifications/rooms/tool_refused the bridge sends when it won't
    offer a page's tool. (issue 1641, PR 1643)
  • massrelay v0.3.3 in Go and npm. The page client turns reconnect off with
    reconnect: false, the opt-out 0.3.3 documents. (PR 1636)

Upgrading downstream

  • agni:
    • Go: github.com/panyam/mcpkit and the rooms modules (experimental/ext/rooms,
      …/rooms/massrelay, …/integrations/roomsevents) at v0.8.13.
    • The stateless-wire assertions from agni issue 1172 (schema validation, stdio stateless,
      adaptive fallback from a session-only server) should now pass against mcpkit.
    • Browser: @panyam/mcpkit-rooms@0.8.13 for onToolRefused (agni issue 1173).
  • Anything implementing stateless.Backend: nothing we know of. The interface is gone, so
    serve the stateless wire through server.WithStatelessMode as before.