JSON-RPC dispatch for MCP.
Takes a parsed request map, returns a response map. No I/O and no transport concerns — which is what makes it testable without a socket.
JSON-RPC dispatch for MCP. Takes a parsed request map, returns a response map. No I/O and no transport concerns — which is what makes it testable without a socket.
(configure! opts)Adopt init!'s teaching-surface options. Called before the port opens,
so no initialize ever composes without them.
Adopt `init!`'s teaching-surface options. Called before the port opens, so no initialize ever composes without them.
(handle-payload payload)(handle-payload payload ctx)A parsed request body — one message or a batch of them. Returns the response payload, or nil when nothing in the batch warrants a reply.
A parsed request body — one message or a batch of them. Returns the response payload, or nil when nothing in the batch warrants a reply.
(probe)The sessionless identity GET /probe serves: who answers here, minting
nothing. :server is the fixed discriminator discovery tooling keys on;
:version reads server-info — a site the release checklist already
syncs, so no fifth version location; :describe is the init!-time
self-description, nil when unset. Consumers key on field presence, not
shape completeness — fields may accrete here without coordination.
The sessionless identity `GET /probe` serves: who answers here, minting nothing. `:server` is the fixed discriminator discovery tooling keys on; `:version` reads `server-info` — a site the release checklist already syncs, so no fifth version location; `:describe` is the `init!`-time self-description, nil when unset. Consumers key on field presence, not shape completeness — fields may accrete here without coordination.
The tool table. Each entry is its own MCP declaration plus a :handler, which is stripped before the entry is sent to the client.
The tool table. Each entry is its own MCP declaration plus a :handler, which is stripped before the entry is sent to the client.
(tools-changed? sid)Whether the tool set differs from what sid last fetched. Per session
(§11), and deliberately "last fetched", not "last announced": a lost
announcement re-announces on the next stream, and a client holding a
list from a previous server run is told to refresh on its first call —
the marker only advances when a tools/list actually serves the
current set (§4). The transport asks before closing each response
stream and announces tools/list_changed while the answer is yes —
the client re-fetches promptly (measured 2026-08-04, claude-code
2.1.220), which is what makes a reloaded tool table reach a live
session without a reconnect.
Whether the tool set differs from what `sid` last fetched. Per session (§11), and deliberately "last fetched", not "last announced": a lost announcement re-announces on the next stream, and a client holding a list from a previous server run is told to refresh on its first call — the marker only advances when a `tools/list` actually serves the current set (§4). The transport asks before closing each response stream and announces `tools/list_changed` while the answer is yes — the client re-fetches promptly (measured 2026-08-04, claude-code 2.1.220), which is what makes a reloaded tool table reach a live session without a reconnect.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |