
kcp-agent — KCP navigation planner
no.cantara由 cantara.no 發布v0.12.0更新於 Oct 25, 2026
Deterministic, fail-closed planner for KCP knowledge manifests: kcp_plan, kcp_load, kcp_validate.
概覽
本機 MCP 伺服器,為任務規劃應載入 KCP 知識清單中的哪些單元,採失敗即關閉的閘門並輸出可稽核的載入計畫。
- 可以做什麼
- 針對知識清單規劃任務:在信任、時效、受眾、憑證與預算閘門下選擇、排序並略過單元,並附上原因,可選擇追蹤聯邦子清單產生樹狀或決策軌跡。載入計畫及合格單元的內容,交由呼叫端助理自己的模型綜合回答,並可對已持有的單元去重。驗證清單,回報結構性錯誤與警告。重播已儲存的計畫產物,檢查清單位元組是否已漂移。
- 適用情境
- 適用於希望助理以確定性方式瀏覽已發布的 knowledge.yaml,並說明每個單元為何被載入或略過的場合,而非臨時檢索文件。適合需要可稽核、受預算或存取閘門控管的知識庫,以及核對舊計畫是否仍與目前清單一致。
- 執行需求
- 以本機 stdio 程序執行,從 npm 套件 kcp-agent 安裝,用 npx 或建置後指令列啟動。需要一份知識清單,可為路徑、目錄或 HTTPS 位址。規劃與載入不需 API 金鑰;僅遠端清單或聯邦需要網路存取,私有或明文 HTTP 主機預設被封鎖,除非明確允許。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 kcp-agent — KCP navigation planner,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
kcp-agent
🧾 See it run — interactive KCP playground · read the reveal
The reference agent for the Knowledge Context Protocol.
The Arena → — the real planner, bundled unmodified, running live in your browser, head-to-head against the usual suspects. The most deterministic agents in the world. Every decision defensible.
KCP defines how knowledge declares itself so agents can navigate it. kcp-agent is the other
half: the agent that consumes KCP end to end. Given a task and a knowledge.yaml, it produces an
inspectable load plan — which units to load and in what order, which to skip and exactly why,
how it selects sub-manifests across a federation, and what the whole thing costs — and then,
optionally, answers the task from only those units.
The valuable, novel core is LLM-free and deterministic. The plan is an audit-before-action artifact — the trusted-render principle ("a manifest may influence what an agent knows, never what it does") extended to the whole agent loop. Only the final synthesis step calls a model.
Install
Native executables
CI cross-compiles self-contained binaries (no Node/Deno required on the target) for
Linux x64/arm64, macOS x64/arm64, and Windows x64 — grab them from a release or from the
kcp-agent-natives artifact on any CI run. To build one yourself:
Use
plan — the inspectable load plan (no API key)
Each stage maps onto a layer of the spec: query scoring (§15), temporal validity (§4.22), agent
attestation (§3.2), federation context + agent_identity (§3.6), and payment / rate-limits
(§4.14/§4.15). A restricted unit the agent can't attest for is listed but marked not
load-eligible — fail-closed, with the reason attached.
Budgeting the context window. Tokens are the actually-scarce resource when feeding a model,
so --context-budget <n> names it — a token ceiling that works exactly like the money --budget:
greedy by score, and a unit that would blow the ceiling is skipped with the arithmetic in the
reason (over context budget: 1,240 tokens would exceed remaining 800 of 4,000), while a smaller
lower-scored unit still gets its chance. Since the planner works on metadata before fetching
(audit-before-action), a unit's size comes from a declared size_tokens (faithful) or bytes/4
(a flagged estimate); a unit that declares neither is admitted but counted unmeasured (the
projection is a lower bound) — unless --strict, which excludes it fail-closed. --context-budget
composes with --budget: a unit must fit both ceilings.
Machine-readable plans
Use --json when another agent or integration consumes a plan. The output preserves the plan fields
at the top level and adds:
kind is plan, tree (when --follow is used), or trace (when --trace is used). Human-readable
output is not a compatibility surface. Successful JSON commands exit 0; planner or manifest errors
write diagnostics to stderr and exit non-zero.
ask — plan, then answer via Claude
ask runs the same planner, loads only the load-eligible units, and asks Claude to answer from
them — treating unit content as knowledge, never as instructions. Needs @anthropic-ai/sdk (an
optional dependency) and a key; plan needs neither.
ask --loop — the audited critique loop
The deterministic scorer is lexical, so a task phrased differently from the publisher's vocabulary
can miss relevant units. --loop closes that gap without surrendering determinism — the model
proposes, the plan disposes:
A fast critic model (default claude-haiku-4-5, --loop-model to change) sees a metadata
digest of the plan — ids, intents, scores, skip reasons, never unit content — and proposes extra
lowercase search terms. A deterministic gate sanitizes, dedupes, and caps them; the task string is
extended; the planner re-plans from scratch. The loop converges when the critic runs dry, a round
adds no units, or --max-rounds (default 3) is reached. Then synthesis answers the original
task from the final plan's eligible units.
What the critic can never do: open an access gate, alter trust/temporal/audience decisions, or
spend money — terms only affect relevance scoring, nothing is loaded or paid for until the loop has
converged, and the final plan's budget arithmetic gates spending exactly as in single-shot mode.
Every round is recorded (proposed terms, accepted, rejected, units added, the full re-planned
artifact) — with --json the chain of plans is the audit log.
The same loop is available as a library (runLoop / askLoop, with an injectable critic), and
skills/kcp-navigator/SKILL.md packages the discipline as a
portable skill for agents that drive the CLI themselves.
ask --ground — verify the answer, surface what it can't substantiate
The plan's fail-closed gates decide what may be loaded; grounding extends the same discipline to what may be asserted. After synthesis, each claim in the answer is checked by a separate verifier — a distinct model call from the generator — that must attribute the claim to one of the loaded units or return nothing. The result is a two-part artifact:
A claim grounds only if the cited unit was actually loaded and its content hash matches — so a verifier that mis-attributes (or is prompt-injected into) citing a unit that was never loaded can never ground a claim: attribution is a proposal, grounding is adjudicated. Unsupported claims are surfaced, never silently dropped — the honest half of "every decision defensible". Each surfaced gap is also a signal to the publisher: the task needed evidence the manifest didn't provide. The surfaced list is capped to guard against a compromised generator flooding it with spurious gaps.
--ground-rounds <n> closes the loop: a surfaced gap seeds reformulation terms, the agent
re-navigates to try to find the missing evidence, and re-grounds — up to n rounds. Termination is
guaranteed by three independent bounds, any one of which halts: the term gate is absorbing (a
term accepted once is known forever, so re-navigation can only add units from the finite eligible
set), the round cap, and a progress guard (a round that adds no new unit halts). Oscillation
is impossible — the loaded set grows monotonically or the loop stops. Every terminal state that
isn't grounded (partial-unsupported, partial-budget, partial-rounds) still surfaces the
remaining gaps. A compromised verifier can, at worst, widen navigation within the eligible set — it
can never cross a gate, name a URL, or spend past the budget.
assess — gate what may be acted on
The plan's gates decide what may be loaded; grounding decides what may be asserted;
assess() decides whether a conclusion clears a confidence threshold before it is acted on.
It runs downstream of synthesis — confidence is a property of the output, which is exactly why it
structurally cannot be gate #14 in the pre-selection cascade.
Same trust posture as grounding: confidence is a proposal (the answer's own
Confidence: 0.82-style self-report via extractSelfReport, and/or an injected evaluator's
judgment); the gate adjudicates deterministically — min-aggregated by default, fail-closed
on anything unmeasurable. Raw signals[] are preserved verbatim on every verdict so thresholds
can be calibrated against real outcomes over time. The verdict reuses the gates'
binary-plus-written-reason contract but is a separate downstream artifact — DecisionTrace and
the conformance vectors are untouched.
The enforcement side lives in kcp-harness: its
harness_assess MCP tool runs this gate and routes failed verdicts on critical tasks to a
named human via its approval tickets, with the verdict embedded as evidence.
kind: skill — governed procedures, gated separately from knowledge
Spec §4.3a (v0.26.1) adds a second class of unit alongside plain knowledge: kind: skill marks
something an agent could do — a runbook, a script, a procedure — not just read. Skills fail
closed by default: a kind: skill unit is not invoke-eligible unless the manifest carries an
explicit load_eligible: true grant, bounded by an action_scope (tools, paths,
capabilities it may touch). This runs as its own gate, skill_eligibility, inserted into the
pre-selection cascade right after relevance — the cascade is fourteen gates, not thirteen.
An ungranted skill is still planned — the agent can see it exists and why it matched a task,
same audit-before-action posture as every other gate — it is simply withheld (loadEligible: false), or dropped entirely under --strict, attributed to skill_eligibility specifically
rather than the generic strict cutoff. Planning a skill is always safe; invoking one is a
separate, explicitly-granted decision. See The Governed Skill
demo below, and the conformant-implementation guide
for the exact gate contract a port must reproduce.
Demos — twenty scenarios, no mocks
Every fact each demo narrates is parsed or computed from the shipping CLI's and library's real
output — nothing is hardcoded — and test/demos.test.ts runs all twenty in CI, so the narration is
itself a regression suite. Everything is offline; no API key needed.
This repo describes itself
The repository dogfoods KCP: knowledge.yaml at the root declares the README,
the source modules, the demo manifest, and the CI workflow as knowledge units, and federates to
the KCP spec's own manifest. So the agent
can navigate its own repo:
test/manifest.test.ts keeps the manifest honest — parseable, pointing at files that exist, and
planning sensibly.
Options
test/docs.test.ts keeps this table honest: every flag parseArgs accepts must appear here
and in the cli.ts header, and vice versa.
validate — lint a knowledge.yaml
Errors are structural problems that mislead or fail an agent (duplicate ids, unsafe or missing
paths, superseded_by pointing nowhere, attestation requirements no agent can ever satisfy);
warnings are declarations that weaken navigation (no triggers, expired units with no successor).
Exit code 1 on errors — run it in the CI of any repo that publishes a manifest.
replay — re-verify a saved plan or grounded answer
A plan --json artifact pins the manifest's sha256 and echoes every planner input. replay
re-fetches each manifest (every node of a --follow tree), compares the bytes, re-runs the
pure planner with the saved inputs, and reports identical or drifted — per manifest,
with the fields that moved. A plan is evidence; replay is the cross-examination. Editing the
artifact by hand is also drift: the recomputed plan won't match it.
replay auto-detects a grounded-answer artifact (from ask --ground --json) and
cross-examines it claim-by-claim instead: each grounded claim's cited unit is re-read and its
sha256 re-compared to the pinned one — still-grounded, drifted (bytes changed), or
gone (unit removed) — exit 1 if any citation no longer holds, because a stale answer must
not read as verified. With --check-gaps it re-navigates today's manifest to see whether a
previously-surfaced gap now closes (the manifest grew the missing evidence since the answer)
— gaps have a lifecycle, and a memory is a plan you can re-verify against a moved world.
remember / recall — episodic memory as replayable plans
A memory here is not a summary or an embedding — it is the plan/grounded-answer artifact itself,
stripped of the one thing that would make it dangerous to keep: the unit bytes. Caching
restricted or paid content in the memory log would let a later recall read it without re-passing
the access gate, so remember keeps only what replay needs — each unit's id, path, sha256,
and the citation table — and drops every content field. Entries are hash-addressed by their
content-stripped artifact, so recording the same answer twice is idempotent.
recall matches past episodes by lexical task-term overlap (the same tokenizer the planner
scores with), ranked by overlap. Because the bytes are gone, a recalled episode carries no
freshness claim on its own: with --replay each hit is re-verified against today's manifests —
valid (every cited unit holds its pinned bytes), drifted (a citation moved — exit 1), or
unverifiable (the replay could not run). Without --replay, every hit is reported
unverifiable — memory never falsely claims a stale answer is still true. A memory is a plan you
can re-verify against a moved world.
memory-validated reuse — a determinism-preserving cache
Passing --memory <dir> to plan or ask turns the episode log into a cache whose
correctness rests on the same property everything else does: a plan is a pure function of
(manifest bytes, task, options). The rule is recall (exact match) + replay (freshness) =
reuse, and everything short of that is fail-closed.
plan --memory records each plan and, if a prior episode ran with the same task, manifest,
and options, reports whether today's manifest is byte-identical (♻ provably identical) or
has drifted since — a determinism/audit signal, never a silent reuse across a sha change.
The cache key includes the effective --as-of date, so an unpinned plan is only reuse-eligible
within the same day; a run under different capabilities (--role, --budget, …) is a different
plan, not a hit.
ask --ground --memory is where reuse pays off: before calling the model it looks for a cached
grounded answer for the identical request and replays it — re-reading every cited unit and
re-checking its pinned sha256. Only if every citation still holds is the stored answer
returned (♻ reused, no model call); if any cited unit drifted or is gone, the answer is
re-computed, never served stale. Because ingest already stripped the unit bytes, a recalled
answer can never smuggle restricted content past the next access gate — reuse re-reads the units
through the guard, live. A memory is a plan you can re-verify against a moved world.
mcp — serve the planner to any MCP client
Exposes four tools: kcp_plan (the inspectable load plan), kcp_load (the plan plus the
content of load-eligible units, so the calling agent's own model synthesizes — kcp-agent never
needs an API key here), kcp_validate, and kcp_replay (cross-examine a saved plan artifact
over the wire). kcp_plan/kcp_load take the CLI's full capability surface — role,
methods, credentials, attest, budget — so attestation and credential gates answer for
any MCP client exactly as they do on the command line. The borrowing agent doesn't have to be
deterministic; it just has to ask someone who is. Register it in e.g. Claude Code:
Session dedup. kcp_load accepts a known argument — the units the caller already holds,
as [{id, sha256}]. A unit whose sha still matches comes back as an unchanged stub (bytes
withheld, sha confirmed) instead of re-serving its content, saving the caller's context window
across a multi-turn session; the response reports deduped and bytesSaved. This is the
caller-side of episodic memory, kept in character: the server stays stateless (the caller's
window is the session), a stub is emitted only on an exact sha match — any drift re-serves
the fresh bytes — and because kcp_load re-plans and so re-gates every call, a unit the caller
has since lost access to is simply absent, never smuggled back as a stub.
knowledge.yaml is llms.txt grown up
llms.txt solved the easy half of the same problem — telling an agent what a site contains — and publishers adopted it. It is a flat link list, and that is all it can ever be.
Same site, both ways:
Convert an existing one — deterministic, no model call, and it never overwrites a manifest you already have:
kcp-agent discover <url> also checks /llms.txt before falling back to crawling, and
points you at the upgrade.
What the upgrade buys, none of which llms.txt can express:
The conversion marks every one of those as a TODO rather than inventing it. A converted manifest that silently claimed an audience or a validity window would be asserting something you never said.
Signatures
A manifest may declare a signing block (scheme ed25519, key + detached signature URLs — see
the spec repo's own manifest). When
present, kcp-agent verifies the signature over the exact manifest bytes before planning:
an invalid signature always fails closed; an unverifiable one (key unreachable) is a
warning unless --require-signature. Supported: JSON signature envelopes
({algorithm, public_key, signature}), raw base64/hex signatures, and PEM / SPKI-DER / raw-32-byte
keys. Pin a publisher key with --trust-key so the manifest can't attest for itself.
The network boundary
A manifest is untrusted input that chooses URLs the agent then fetches — federation refs,
signature and key locations, remote unit content. Every remote read funnels through one guarded
fetch (src/fetch.ts), fail-closed by default:
- SSRF / confused deputy —
https://only for remote; loopback, private, link-local, and cloud-metadata addresses (e.g.169.254.169.254) are refused. Hostnames are DNS-resolved and every address checked; redirects are followed manually so a public host can't bounce the agent into a private one.--allow-private-hostsopts in for local/internal manifests. - Fan-out — depth and cycles were already bounded;
--max-nodes(default 64) now caps the total manifests a single--followwill fetch, so one hostile hub can't fan out to millions. - Response size — every read is streamed against an 8 MiB ceiling and aborted past it, with a whole-exchange timeout, so a hostile endpoint can't exhaust memory.
Over MCP the guard is on by default — a foreign client is exactly the untrusted-caller case.
Writing triggers agents can find
The scorer is lexical and deterministic — intent, triggers, and id/path are matched against the task's terms; there is no model and no embedding. That's the feature (reproducible, auditable, free), and it has an honest consequence: a unit is only findable through the words its manifest declares. A real miss from the field:
The unit's triggers were [datacenter, power grid, capacity, Nordics] and its intent never said
"infrastructure" — zero lexical overlap, score 0, skipped. The fix belongs in the manifest, not
the planner:
- Write triggers for the questions agents ask, not the nouns in the content. "infrastructure", "energy costs", "where does the compute run" — the phrasings of tasks — beat article vocabulary.
- Spend intent words on question terms too: intent is scored, so "How the power grid limits sovereign compute infrastructure" is findable where "Live Nordic datacenter power-grid feed" is not.
- Run
kcp-agent planwith your expected tasks against your own manifest before publishing — the skip reasons show exactly what a real agent would miss and why.
Library
Design
- Deterministic planner (
src/planner.ts) — pure functions, fully unit-tested (npm test), no I/O and no model. The plan is reproducible and auditable. - Self-contained KCP client (
src/client.ts) — parsesknowledge.yamlfrom a path, directory, or HTTPS URL. No dependency on the spec repo's internals. - Federation follower (
src/follow.ts) — the async shell around the pure planner: fetches eligible refs recursively, fail-closed, with cycle detection and per-hop signature verification. - Signature verification (
src/verify.ts) — ed25519 over exact manifest bytes via WebCrypto. - Synthesis layer (
src/synthesize.ts) — the only part that calls a model; loads only the planned units and answers the task. - Confidence gate (
src/assess.ts) — post-synthesis: adjudicates self-reported and/or evaluator confidence against a caller-supplied threshold, deterministically, fail-closed. - MCP server (
src/mcp.ts) — dependency-free JSON-RPC over stdio.
Spec conformance
The agent targets KCP 0.25 and consumes the subset below end to end. (The spec repo's own
manifest currently declares kcp_version: 0.21 — the manifests are compatible for these layers.)
Every row is pinned to the CI tests that enforce it in
docs/conformance.json — rendered as
the Receipts on the site — and
test/docs.test.ts fails the build if a referenced test disappears or is renamed.
Conformance vectors
vectors/ freezes the planner's decisions as portable
(manifest, task, options) → expected outcome fixtures — the deterministic core's behavior as
data, not code. test/vectors.test.ts proves the reference planner reproduces every one; any
second implementation (a Go/Rust port for a 2–5 MB static binary, or a third party's) is
conformant iff it does the same. Two independent implementations that pass the same vectors
validate the spec, not just the code — the strongest proof a protocol is unambiguous. The corpus
is generated from the reference planner (npm run gen:vectors) so the expected outcomes are never
hand-written, and is proposed upstream as the normative KCP conformance suite.
Not yet consumed: dependency chains between units, hints.load_strategy, compliance/audit blocks.
Guides
- Quickstart — your first ten minutes — install → plan → ask → validate → serve → replay, end to end.
- Make your repo navigable in 10 minutes — from nothing to a manifest real plans run against, kept honest in CI.
- Sign your manifest — ed25519 over exact bytes, envelopes, key pinning, and the fail-closed lifecycle.
- Wire the planner into Claude Code —
kcp_plan/kcp_load/kcp_validateover MCP, no API key needed. - Give your agent a memory — record answers as replayable, byte-free episodes; recall by task, verify by replay, reuse only while they hold.
- Cut context cost with session dedup — how an MCP
caller passes
knownunits tokcp_loadand stops re-spending its context window. - Build a conformant implementation — the planner pipeline as a spec, and how to validate a second (e.g. Go) implementation against the vectors.
License
Apache-2.0 · Proposed by eXOReaction AS, hosted under Cantara.
來源:README.md,提交 ba88b3c
工具
0版本歷史
1- v0.12.0最新Sep 16, 2026
評分
已滿足適用檢查項的 40%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
請在儲存庫或註冊中心條目中宣告授權條款。