Liking cljdoc? Tell your friends :D

toolnexus.mcp


answer->elicit-resultclj/s

(answer->elicit-result answer)

SPEC §10 — a resolved §10 Answer as an MCP ElicitResult. ok ⇒ accept carrying data as content; otherwise reason:"declined" ⇒ decline and anything else (cancelled, expired, absent) ⇒ cancel.

SPEC §10 — a resolved §10 Answer as an MCP `ElicitResult`.
`ok` ⇒ accept carrying `data` as content; otherwise `reason:"declined"` ⇒
decline and anything else (cancelled, expired, absent) ⇒ cancel.
sourceraw docstring

connectclj/s

(connect server)
(connect server {:keys [wait-for] :as conn-opts})

SPEC §2 — reach the server, initialize, notifications/initialized, tools/list. Returns a CONNECTION:

{:name … :status "connected"|"disabled"|"failed" :tools [Tool…] :transport … :server-info … :error {…}}

Never throws. §0.3: a server that fails to connect is recorded failed and the caller carries on with the servers that did work.

EXIT vs EOF — ANSWERED, as of koine 0.8.0. When a stdio peer stops talking, read-line! returns nil, and that alone cannot say whether the child exited, crashed, or merely closed stdout while still running. This port used to report a bare peer-eof for all three, and distinguished a dead peer from a quiet one with a kill! timeout — a guess dressed as a policy, wrong in both directions: too short kills a slow peer, too long hangs on a dead one.

koine.process/exit-code replaces the guess with an observation: nil = has not exited, a number = the status. The close reason is now peer-exited (status N) where the status is known, and :exit-code is on the connection for a caller whose retry logic needs to tell a crash from a hang.

ONE TRAP, MEASURED RATHER THAN REASONED: exit-code must NOT be read the instant EOF arrives. A child running sh -c 'echo …>&2; exit 3' reported nil on 4 of 5 runs at that moment — closing stdout and the reaper recording the status are different events, and EOF wins the race. Read naively, that turns a do-not-know-yet into a confident still-running, which is a worse answer than the peer-eof it replaced. This layer waits up to ~250 ms for the reaper, and if the status is still unknown it SAYS unknown rather than guessing alive.

Note that alive? is still not consulted for this. It answers a different question, and koine reads its own reaper for exit rather than cljgo's native :exit-code so there is ONE source of truth for has-it-exited — two would drift. The child's stderr ring remains attached to the failure, because a status code says THAT it died and the stderr says WHY.

SPEC §2 — reach the server, `initialize`, `notifications/initialized`,
`tools/list`. Returns a CONNECTION:

  {:name … :status "connected"|"disabled"|"failed" :tools [Tool…]
   :transport … :server-info … :error {…}}

Never throws. §0.3: a server that fails to connect is recorded `failed` and
the caller carries on with the servers that did work.

EXIT vs EOF — ANSWERED, as of koine 0.8.0. When a stdio peer stops talking,
`read-line!` returns nil, and that alone cannot say whether the child exited,
crashed, or merely closed stdout while still running. This port used to report
a bare `peer-eof` for all three, and distinguished a dead peer from a quiet
one with a `kill!` timeout — a guess dressed as a policy, wrong in both
directions: too short kills a slow peer, too long hangs on a dead one.

`koine.process/exit-code` replaces the guess with an observation: nil = has
not exited, a number = the status. The close reason is now `peer-exited
(status N)` where the status is known, and `:exit-code` is on the connection
for a caller whose retry logic needs to tell a crash from a hang.

ONE TRAP, MEASURED RATHER THAN REASONED: exit-code must NOT be read the
instant EOF arrives. A child running `sh -c 'echo …>&2; exit 3'` reported nil
on 4 of 5 runs at that moment — closing stdout and the reaper recording the
status are different events, and EOF wins the race. Read naively, that turns
a do-not-know-yet into a confident still-running, which is a worse answer
than the `peer-eof` it replaced. This layer waits up to ~250 ms for the reaper,
and if the status is still unknown it SAYS unknown rather than guessing
alive.

Note that `alive?` is still not consulted for this. It answers a different
question, and koine reads its own reaper for exit rather than cljgo's native
`:exit-code` so there is ONE source of truth for has-it-exited — two would
drift. The child's stderr ring remains attached to the failure, because a
status code says THAT it died and the stderr says WHY.
sourceraw docstring

default-timeout-msclj/s

SPEC §0.3 — the per-phase budget when a server does not state one.

SPEC §0.3 — the per-phase budget when a server does not state one.
sourceraw docstring

disconnectclj/s

(disconnect connection)

Close a connection's transport. Idempotent, never throws, and BOUNDED — for stdio it kills rather than politely waits, because an unkillable disconnect is how one wedged server takes the host down with it.

Close a connection's transport. Idempotent, never throws, and BOUNDED — for
stdio it kills rather than politely waits, because an unkillable disconnect is
how one wedged server takes the host down with it.
sourceraw docstring

disconnect-allclj/s

(disconnect-all result)

Close every connection a from-config opened.

Close every connection a `from-config` opened.
sourceraw docstring

elicitation->requestclj/s

(elicitation->request params)

SPEC §10 — an MCP elicitation/create params object as a §10 Request.

The id is opaque and per-process (js/src/mcp.ts builds it from a timestamp and a counter, and no port compares ids with another). Uniqueness is the only property anything depends on, so the counter — not the clock — is what guarantees it here.

SPEC §10 — an MCP `elicitation/create` params object as a §10 Request.

The id is opaque and per-process (js/src/mcp.ts builds it from a timestamp and
a counter, and no port compares ids with another). Uniqueness is the only
property anything depends on, so the counter — not the clock — is what
guarantees it here.
sourceraw docstring

expand-headersclj/s

(expand-headers headers)

SPEC §0.3 — remote headers VALUES expand ${ENV_VAR} from the environment. The expanded value is used and NEVER logged. Callers may report the SHAPE (header-shape) and nothing else.

SPEC §0.3 — remote `headers` VALUES expand ${ENV_VAR} from the environment.
The expanded value is used and NEVER logged. Callers may report the SHAPE
(`header-shape`) and nothing else.
sourceraw docstring

from-configclj/s

(from-config config)
(from-config config conn-opts)

SPEC §2 — the whole source in one call. config is a JSON string or a map.

Returns {:tools [Tool…] :statuses {name -> "connected"|"disabled"|"failed"} :connections [conn…] :errors {name -> message}}.

Servers are connected in name order, one at a time. Not because serial is better — it is slower — but because it is DETERMINISTIC, and §0's whole premise is that two runtimes given the same fixture produce the same output. A tool-name collision resolved by whichever server answered first is exactly the kind of drift this repo exists to prevent.

SPEC §2 — the whole source in one call. `config` is a JSON string or a map.

Returns `{:tools [Tool…] :statuses {name -> "connected"|"disabled"|"failed"}
:connections [conn…] :errors {name -> message}}`.

Servers are connected in name order, one at a time. Not because serial is
better — it is slower — but because it is DETERMINISTIC, and §0's whole
premise is that two runtimes given the same fixture produce the same output.
A tool-name collision resolved by whichever server answered first is exactly
the kind of drift this repo exists to prevent.
sourceraw docstring

header-shapeclj/s

(header-shape raw expanded)

The only thing about headers that may leave this process: which keys exist, and whether ${ENV} expansion CHANGED anything. Never a value, and never a length — a length leaks a secret's size.

The only thing about headers that may leave this process: which keys exist,
and whether ${ENV} expansion CHANGED anything. Never a value, and never a
length — a length leaks a secret's size.
sourceraw docstring

http-transportclj/s

(http-transport server)
(http-transport {:keys [url headers]} {:keys [wait-for]})

The remote leg. Identical shape to stdio-transport, which is the point: every line above §2 is written once.

The remote leg. Identical shape to `stdio-transport`, which is the point:
every line above §2 is written once.
sourceraw docstring

mcp-tool-nameclj/s

(mcp-tool-name server-name remote-name)

SPEC §0.2 — sanitize(server)_sanitize(tool).

SPEC §0.2 — sanitize(server)_sanitize(tool).
sourceraw docstring

parse-configclj/s

(parse-config config)

SPEC §0.3 / §2 — a JSON string or an already-parsed map becomes a vector of server maps, sorted by name so two hosts cannot disagree about order.

Accepts mcpServers | servers | mcp; with no wrapper the object itself is the server map, minus the reserved sibling keys.

SPEC §0.3 / §2 — a JSON string or an already-parsed map becomes a vector of
server maps, sorted by name so two hosts cannot disagree about order.

Accepts `mcpServers` | `servers` | `mcp`; with no wrapper the object itself is
the server map, minus the reserved sibling keys.
sourceraw docstring

server-request-responseclj/s

(server-request-response wait-for msg)

The response to ONE server-initiated JSON-RPC request, or nil when the message is not one.

Satisfied INLINE, as §10 requires: the in-flight tools/call resumes when this returns, and nothing re-executes. With no wait-for the client never advertised elicitation, so a request for it is simply an unknown method — a clean refusal rather than a hang. A host callback that THROWS becomes a cancel: §0.3's isolation rule does not stop at the reverse-request boundary.

The response to ONE server-initiated JSON-RPC request, or nil when the
message is not one.

Satisfied INLINE, as §10 requires: the in-flight `tools/call` resumes when
this returns, and nothing re-executes. With no `wait-for` the client never
advertised `elicitation`, so a request for it is simply an unknown method —
a clean refusal rather than a hang. A host callback that THROWS becomes a
cancel: §0.3's isolation rule does not stop at the reverse-request boundary.
sourceraw docstring

shape-resultclj/s

(shape-result result)

SPEC §0.4, all three branches: isError ⇒ error ToolResult carrying the joined text structuredContent ⇒ output is the JSON encoding of it (text ignored) else ⇒ the joined text parts

koine's write-str sorts keys, so the structured branch is byte-identical on both hosts — which is what makes §0's cross-language byte comparison possible at all.

SPEC §0.4, all three branches:
   isError            ⇒ error ToolResult carrying the joined text
   structuredContent  ⇒ output is the JSON encoding of it (text ignored)
   else               ⇒ the joined text parts

koine's `write-str` sorts keys, so the structured branch is byte-identical on
both hosts — which is what makes §0's cross-language byte comparison possible
at all.
sourceraw docstring

stderrclj/s

(stderr connection)

The connection's recent child stderr (stdio only; [] for remote). The reason koine drains it: it is the only thing that explains why a server died.

The connection's recent child stderr (stdio only; [] for remote). The reason
koine drains it: it is the only thing that explains why a server died.
sourceraw docstring

stdio-transportclj/s

(stdio-transport server)
(stdio-transport {:keys [command cwd environment]} {:keys [wait-for]})

Spawn the child and hand back a transport. §2: merged env = process env + environment, in cwd. koine's spawn drains stderr into a bounded ring from the first instant, which is why a verbose server no longer deadlocks on a full pipe, and why :stderr below can explain a crash.

Spawn the child and hand back a transport. §2: merged env = process env +
`environment`, in `cwd`. koine's `spawn` drains stderr into a bounded ring
from the first instant, which is why a verbose server no longer deadlocks on a
full pipe, and why `:stderr` below can explain a crash.
sourceraw docstring

toolsclj/s

(tools x)

The Tools of a connection, or of a from-config result.

The Tools of a connection, or of a `from-config` result.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close