
Kaval
io.github.usekaval由 GitHub 账号 usekaval 发布v0.8.2更新于 Oct 24, 2026
Verify the facts an agent's action depends on before it acts — ALLOW, REVIEW, or BLOCK.
概览
Kaval 在 AI 智能体执行操作前核验该操作所依赖的事实,返回 ALLOW、REVIEW 或 BLOCK 及签名回执,是托管 Kaval API 的轻量客户端。
- 可以做什么
- 检查即将执行的操作或一组声明,返回决策、逐条事实状态和签名回执;按回执 id 获取完整签名文档,并在事后上报实际结果以供校准。管理被监视来源:注册网址、具名权威机构或推送文档,列出、更新、绑定抽取模式,并删除来源以释放工作区名额。处理合同:创建私有 PDF 上传目标,将文本或文档排队抽取,查看状态,列出抽取出的声明与抽取问题,并批准、更正或拒绝声明。运行绑定模式的抽取:注册 JSON Schema,发起按发布方和周期的一次性抽取,查看运行状态与结果,列出月度打包。
- 适用场景
- 适用于智能体即将执行重要操作、需要确认其依据的事实仍然成立时,或需要该决策的可审计签名记录时。也适合从被监视的发布方文档中抽取结构化记录并审核合同声明的团队。
- 运行要求
- 以 npm 包形式通过 stdio 在本机运行(npx @usekaval/mcp),仅限桌面端。需要在 KAVAL_API_KEY 中提供 Kaval API 密钥;KAVAL_BASE_URL 可选,用于指向自建或预发布 API。需要能访问 Kaval API 的网络;无需模型或搜索密钥。
安装
在 SourceWeft 中
- 打开 控制台中的 Kaval,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
@usekaval/mcp
Before an AI agent acts, Kaval verifies the facts that action depends on and answers ALLOW, REVIEW, or BLOCK with a signed receipt. This package exposes that as an MCP server.
Policy engines decide whether an action is permitted under the rules; Kaval verifies whether the facts those rules depend on are still true.
This package is a thin client over the hosted Kaval API. All compilation, grounding, and retrieval run server-side, so you bring just a Kaval API key — no model or search keys, no local engine.
0.6 was a breaking release. Nine tools became seven (before later portfolio/extraction tools landed), and everything removed folded into
check; the API answers410 tool_retiredfor the old routes and this server translates that into an error that tells the agent to callcheck. See Migrating from 0.5.
Run it
It speaks MCP over stdio. Point any MCP client at it.
Client config
Tools
Resources
The server publishes these JSON resources:
kaval://bulletinskaval://bulletins/extraction-attemptskaval://training-jobskaval://training-feedbackkaval://contracts/{contract_id}kaval://contracts/{contract_id}/claimskaval://contracts/{contract_id}/extraction-issueskaval://bulletins/{source_version_id}kaval://bulletins/extraction-attempts/{source_version_id}kaval://fact-imports/{import_id}kaval://training-jobs/{job_id}
The training resources are read-only. Feedback review and consent require training:manage.
Bulletin extraction status is read-only. MCP does not expose the operator requeue control.
MCP does not start training or promote a model.
check
Or skip extraction entirely by naming the facts:
The response:
mode: "fast" answers only from stored state and reports anything unknown as unknown;
"standard" (default) may research a stale or novel fact within max_wait_ms. A fact that misses
the budget comes back unknown — it does not warm the next check, because that check recompiles
the action and asks about different fact fingerprints.
The budget. The API's own default is 100000 ms, because a cold action check with several novel
premises routinely needs 50–100s of live research. MCP cannot spend that: an MCP client cancels a
tool call after 60s. So this server sends max_wait_ms: 45000 explicitly and caps the argument
there, and gives its HTTP client a 55s deadline so the timeout fires here — as
{"error":"timeout"} with a recovery move — rather than as a cancelled request. Pass a smaller
max_wait_ms when a bounded REVIEW beats waiting; 0 disables research entirely, which is what
mode: "fast" does. Direct HTTP and SDK callers are not bound by any of this and get the full
100000.
A fact already backed by a watched source is answered from stored state with zero model calls and
zero fetches, so calling check on every consequential action is cheap. A fact Kaval has
never seen has to be researched first, and that takes seconds.
Keeping checks warm
add_source is what makes a check a database read instead of a research run. Registering the name
of an authority is usually enough:
Kaval resolves that to the pages that publish it and watches them adaptively. kind: "url" watches
one page; kind: "push" is a document your own system sends to POST /v1/events. Registering is
optional — a source a check cites is auto-watched — but registering first is what makes the first
check on a fact fast.
That auto-watching is why remove_source exists. Capacity is two ceilings, not one:
- up to 200 active
registered/resolvedsources per workspace (auto-registered citations count here; discovered children do not) - up to 200 active
discoveredchildren per parent
Only deletion frees a slot — pausing does not. An agent that registers per task and never removes will eventually fill the workspace registered/resolved ceiling, after which new citations are dropped silently and checks that used to be warm go back to researching. Remove what a task registered when the task is done.
Extractions
create_extraction_schema registers a JSON Schema; bind its id to a watched source with
update_source({ id, extraction_schema_id }) and every document that lands on that source afterward
is extracted against the schema automatically — no polling. Pass reprocess: true to also
fill-missing re-extract versions that already ran under another schema; those webhooks carry
source_change: "schema_changed" (join the original extract on source_version_id). For a one-off
run against a publisher + period instead of waiting for the next document, call create_extraction_run
directly. Either way,
get_extraction_run / list_extraction_runs report the run's lifecycle
(processing → retry → succeeded / review_required / failed), and
list_extraction_packages lists the monthly PDF + manifest rollups each publisher/period is packaged
into. Each package's pdf_href is a durable Kaval URL — GET (or HEAD) it and follow the 302
to a short-lived signed PDF (MCP does not expose a separate download tool; use HTTP with redirects).
get_source_version_content fetches the canonical text (or format: "sections") an extraction run
was computed from.
This is the schema-bound successor to the free-text bulletin tools (list_bulletins, get_bulletin,
list_bulletin_extraction_attempts, get_bulletin_extraction_attempt), which are soft-deprecated but
keep working.
Delta webhooks are not an agent tool
Watched sources are only half the mechanism: when a source changes, Kaval re-evaluates the dependent
facts and pushes a fact_state.delta webhook naming what flipped; a source with a bound extraction
schema also pushes extraction.document (and, monthly, extraction.package) with the
extracted records (nested evidence on each record) and optional section page/bbox for PDF highlighting.
extraction_run.period is the publication / newsletter month. Those subscriptions are
deliberately not exposed as MCP tools. They are
one-time deployment configuration — each mints a standing outbound callback bound to an https
endpoint and a signing secret that must be stored, which is a deploy-time decision for a human or a
service, not an in-loop choice for an agent that owns neither the endpoint nor the secret.
Configure them once from the SDK (kaval.subscribeFactStateDeltas({ callback_url }) /
kaval.subscribeExtractions({ callback_url }) in Node, kaval.subscribe_fact_state_deltas(…) /
kaval.subscribe_extractions(…) in Python), from POST /v1/webhooks with
subscription_kind: "fact_state" or "extraction" (policy_update is rejected on create), or from
the dashboard. The agent then just
calls check (or reads list_extraction_runs), and it is already fast and already current.
Migrating from 0.5
Status mapping: current + act: true → decision: "ALLOW" with every fact holds;
stale/contradicted → a fact changed (REVIEW or BLOCK by materiality);
unsupported/insufficient/conflicting → a fact unknown (REVIEW, or BLOCK if critical).
A 0.5 client calling a removed route gets 410 {"error":"tool_retired","replacement":"/v1/check"},
which this server surfaces as {"error":"tool_retired","message":"this capability was folded into the check tool …","status":410}.
Idempotency
Contract uploads, contract creation, claim reviews, fact imports, create_extraction_schema,
create_extraction_run, and verify carry operation keys. The server creates a key when you omit
one. Reuse the returned key after an ambiguous failure.
check deliberately carries none: it is a read of current state, so a retry recomputes rather than
replays and cannot double-count.
Tool errors
A failed tool call returns isError: true and a JSON body naming what happened, so an agent can
branch on it rather than parse prose.
Signed receipts
Check receipts are Ed25519-signed and self-derivable: because the decision table is published, the
receipt's own fact list re-derives the verdict offline, byte for byte, with no server. Verify one
with @usekaval/kaval/verify — a dependency-free subpath of the Node SDK this package already
depends on, plus the kaval-receipt-verify CLI that SDK ships. It answers cryptographic validity,
key trust, and freshness separately, needs no Kaval account and no API key, and reads the public
keys from the unauthenticated GET /v1/proof-verification-keys/:kid — or from a keyset you archived
beside the receipt, which is the fully offline path.
check returns only { id, signature, signed_at }. Call get_receipt with that id for the
document that was actually signed — every fact with its state, the evidence basis under it (source
locator, content digest and what the digest covers, fetch and publication time), the decision-rule
version, and the signing key id. That is the artifact to attach to a BLOCK you escalate.
Honest boundaries: demo results carry no organizational authority; a production ALLOW requires
a customer-bound action policy and applicable empirical calibration; REVIEW is never permission to
act.
Environment
Both are declared in server.json and smithery.yaml, so a registry install can point at a
self-hosted deployment rather than only at the hosted API.
The marketing site uses KAVAL_API_URL for its /api/verify proxy — not KAVAL_BASE_URL.
Programmatic use
This package is primarily a CLI (kaval-mcp). It also exports the server factory for embedding:
Or pass your own configured client:
Use delete_extraction_schema with { "id": "<schema-id>" } to delete an unused schema.
Deletion removes the schema from lists and selectors. Historical extraction records retain its definition.
If an active watched source uses the schema, the API returns 409 schema_in_use.
Use rename_extraction_schema with { "id": "<schema-id>", "name": "New name" } to rename a schema.
Its definition and hash remain unchanged.
来源:packages/mcp/README.md,提交 e482bf8
工具
0版本历史
1- v0.8.2最新Sep 16, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分