(agent-card cfg base skills)§7B's Agent Card, with every default the spec names.
skills[] comes from the toolkit's SkillSource — NEVER from the tools —
filtered to a2a.skills when given. The skill id is sanitized (§0.2); the
skill name is not. provider is present ONLY when configured (absent, not
null).
AMBIGUITY (§7B): unknown names in a2a.skills are undefined. §7C explicitly
says unknown mcp.tools names are ignored; we ignore them here too, by
symmetry — an untested asymmetry is exactly how six ports drift.
§7B's Agent Card, with every default the spec names. `skills[]` comes from the toolkit's SkillSource — NEVER from the tools — filtered to `a2a.skills` when given. The skill `id` is sanitized (§0.2); the skill `name` is not. `provider` is present ONLY when configured (absent, not null). AMBIGUITY (§7B): unknown names in `a2a.skills` are undefined. §7C explicitly says unknown `mcp.tools` names are ignored; we ignore them here too, by symmetry — an untested asymmetry is exactly how six ports drift.
(exposed-tools tk cfg)The tools this MCP profile exposes: mcp.tools filtered to exactly those
names, UNKNOWN NAMES IGNORED (§7C, explicit); omitted ⇒ every toolkit tool.
Sorted, so two runtimes cannot disagree on order.
============================ KNOWN SPEC DEFECT ============================
§7C says only that mcp.tools filters the LIST. Ported literally, a tool
excluded from tools/list is STILL CALLABLE through tools/call — which
turns what every reader takes for an allowlist into a cosmetic filter, on the
one surface (serve) whose whole job is exposing a toolkit to strangers.
This function is therefore AUTHORITATIVE FOR CALLS TOO: tools/call resolves
the tool out of this same filtered set, so an excluded tool answers -32602
exactly like a tool that does not exist. Spike S21 made the same call. It is a
deliberate, security-motivated deviation from a literal reading, it is
reported upward, and §7C needs a sentence — not six ports each guessing.
The tools this MCP profile exposes: `mcp.tools` filtered to exactly those names, UNKNOWN NAMES IGNORED (§7C, explicit); omitted ⇒ every toolkit tool. Sorted, so two runtimes cannot disagree on order. ============================ KNOWN SPEC DEFECT ============================ §7C says only that `mcp.tools` filters the LIST. Ported literally, a tool excluded from `tools/list` is STILL CALLABLE through `tools/call` — which turns what every reader takes for an allowlist into a cosmetic filter, on the one surface (`serve`) whose whole job is exposing a toolkit to strangers. This function is therefore AUTHORITATIVE FOR CALLS TOO: `tools/call` resolves the tool out of this same filtered set, so an excluded tool answers -32602 exactly like a tool that does not exist. Spike S21 made the same call. It is a deliberate, security-motivated deviation from a literal reading, it is reported upward, and §7C needs a sentence — not six ports each guessing.
(file-store dir)§7B "file:<dir>" — one <id>.json per task.
§7B `"file:<dir>"` — one `<id>.json` per task.
(memory-store)The default store. A store is a plain map of two closures — not a protocol, not a record: those are the two things guaranteed to differ across hosts.
The default store. A store is a plain map of two closures — not a protocol, not a record: those are the two things guaranteed to differ across hosts.
(resolve-store store)§7B resolveStore(store?): nil | "memory" ⇒ in-memory (default);
"file:<dir>" ⇒ a file store; anything else is used as-is.
§7B `resolveStore(store?)`: nil | "memory" ⇒ in-memory (default); "file:<dir>" ⇒ a file store; anything else is used as-is.
(serve tk {:keys [port host a2a mcp skills store on-task on-call] :as opts})SPEC §7B/§7C toolkit.serve(addr, {client, a2a?, mcp?, onTask?, onCall?}).
(serve tk {:port 0 :a2a {…} :mcp {…} :skills … :run f})
opts
:port :host passed to koine.server (:port 0 ⇒ an OS-assigned port)
:a2a §7B profile map, or nil/absent ⇒ NO A2A routes
:mcp §7C profile map, or nil/absent ⇒ NO /mcp
:skills the SkillSource the Agent Card advertises
:client/:run the fulfilment (see run-fn-of)
:store §7B TaskStore (see resolve-store)
:on-task fires on a terminal Task state
:on-call fires per inbound tools/call
Returns a ServeHandle: {:url :port :stop! :store :handle}. stop! is also
available as a fn of the handle.
SPEC §7B/§7C `toolkit.serve(addr, {client, a2a?, mcp?, onTask?, onCall?})`.
(serve tk {:port 0 :a2a {…} :mcp {…} :skills … :run f})
opts
:port :host passed to koine.server (`:port 0` ⇒ an OS-assigned port)
:a2a §7B profile map, or nil/absent ⇒ NO A2A routes
:mcp §7C profile map, or nil/absent ⇒ NO /mcp
:skills the SkillSource the Agent Card advertises
:client/:run the fulfilment (see `run-fn-of`)
:store §7B TaskStore (see `resolve-store`)
:on-task fires on a terminal Task state
:on-call fires per inbound `tools/call`
Returns a ServeHandle: `{:url :port :stop! :store :handle}`. `stop!` is also
available as a fn of the handle.(stop! handle)Shut a ServeHandle down. Idempotent, like koine's.
Shut a ServeHandle down. Idempotent, like koine's.
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 |