Kaval について
Kavalは、エージェントの行動に関わる事実が現在も正しいかを確認するMCPサーバーです。ALLOW、REVIEW、BLOCKと署名付きレシートを返し、検証や文書抽出はホスト型APIで実行します。
主な機能
- 01ALLOW、REVIEW、BLOCKによる事実確認
- 02根拠の詳細を含む署名付きレシート
- 03契約書の取り込みと主張のレビュー
- 04ソース監視と事実の一括インポート
- 05スキーマに基づく文書抽出
活用シーン
- 01重要なエージェント操作の前に事実を確認
- 02判断の根拠を調査
- 03契約書から抽出した主張をレビュー
- 04監視対象の文書から構造化データを抽出
MCP 対応
MCPツールとJSONリソースを通じて、Kavalの確認、レシート、ソース管理、契約レビュー、抽出機能を提供します。ホスト型Kaval APIに接続します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @usekaval/mcpKAVAL_API_KEYシークレットBring-your-own Kaval bearer key (kv_live_…). Create one at https://usekaval.com.KAVAL_BASE_URLPoint at a self-hosted or staging Kaval API instead of the hosted one. Defaults to https://api.usekaval.com.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
@usekaval/mcp
AI エージェントがアクションを実行する前に、Kaval はそのアクションが依存する事実を検証し、署名付きレシートとともに ALLOW、REVIEW、または BLOCK を返します。このパッケージは、それを MCP サーバーとして公開します。
ポリシーエンジンは、ルールに基づいてアクションが許可されるかどうかを判断します。Kaval は、それらのルールが依存する事実が今も真実であるかを検証します。
このパッケージは、ホスト型 Kaval API を利用する薄いクライアントです。コンパイル、グラウンディング、検索はすべてサーバー側で実行されるため、必要なのは Kaval API キーだけです。モデルキーや検索キー、ローカルエンジンは必要ありません。
0.6 は破壊的変更を伴うリリースでした。 9 つのツールが 7 つになり(その後、ポートフォリオ/抽出ツールが追加されました)、削除された機能はすべて
checkに統合されました。API は古いルートに対して410 tool_retiredを返し、このサーバーはエージェントにcheckを呼び出すよう伝えるエラーに変換します。0.5 からの移行をご覧ください。
実行方法
npx -y @usekaval/mcp
stdio 経由で MCP と通信します。任意の MCP クライアントから接続してください。
クライアント設定
{
"mcpServers": {
"kaval": {
"command": "npx",
"args": ["-y", "@usekaval/mcp"],
"env": {
"KAVAL_API_KEY": "kv_live_…",
},
},
},
}
ツール
| ツール | 説明 |
|---|---|
check | 実際に処理を行うツールです。 これから実行するアクション(またはその根拠となる主張)を送信すると、事実ごとのステータスと署名済みレシートに加え、ALLOW/REVIEW/BLOCK を返します。 |
get_receipt | チェックの receipt.id に紐づく署名済みドキュメント全体です。事実ごとの根拠、判断ルールのバージョン、署名鍵が含まれます。ブロック時にエージェントが添付するものです。 |
prepare_contract_upload | 非公開の PDF アップロード先を作成します。 |
ingest_contract | 正規化されたテキスト、HTTPS ドキュメント、またはアップロード済み PDF を抽出キューに登録します。 |
get_contract | 契約の処理ステータス、候補件数、抽出上の問題の状態を取得します。 |
list_contract_claims | 正確な根拠箇所とともに、抽出された候補を一覧表示します。 |
list_contract_extraction_issues | 顧客による確認が必要な、決定論的な抽出失敗を一覧表示します。 |
review_contract_claim | 不変のバージョン管理のもとで、候補を1件承認、修正、または却下します。 |
import_facts | 確認済みの事実を最大400件、ウォームチェック用にキューへ登録します。 |
get_fact_import | 一括インポート1件と、各項目の結果をすべて取得します。 |
list_bulletins | 段階的に非推奨です — 支払者、ポリシー、コード、日付、ステータスで構造化された速報を絞り込みます。新しい連携には list_extraction_runs を使用してください。 |
get_bulletin | 段階的に非推奨です — フィールドの根拠とともに、構造化された速報を1件取得します。get_extraction_run を使用してください。 |
list_bulletin_extraction_attempts | 段階的に非推奨です — 顧客向けの速報抽出ステータスと失敗を一覧表示します。list_extraction_runs を使用してください。 |
get_bulletin_extraction_attempt | 段階的に非推奨です — ソースバージョン ID を指定して、速報の抽出試行を1件取得します。get_extraction_run を使用してください。 |
list_training_jobs | 読み取り専用のトレーニングと評価のステータスを一覧表示します。 |
get_training_job | 読み取り専用のトレーニングジョブを1件取得します。 |
list_training_feedback | 確認済みのフィードバックと、その有効なトレーニング利用状態を一覧表示します。 |
record_training_feedback_consent | 確認済みのフィードバック項目1件について、トレーニング利用の明示的な判断を記録します。 |
create_extraction_schema | Kaval が構造化レコードを抽出する対象となる JSON Schema を登録します。policy-update:manage が必要です。 |
list_extraction_schemas | このワークスペースに登録された抽出スキーマを一覧表示します。 |
create_extraction_run | 紐づけられたスキーマを使用して、発行元と期間を指定した単発の抽出実行を要求します。policy-update:manage が必要です。 |
get_extraction_run | ID を指定して抽出実行を1件取得します。ステータス、スキーマ、成功時の結果が含まれます。 |
list_extraction_runs | 発行元/期間/時刻のフィルターとカーソルページネーションを使用して抽出実行を一覧表示します。ネストされた document の詳細を含みます(省略するには expand_document: false を渡します)。 |
list_extraction_packages | 抽出実行がまとめられる、月次の PDF とマニフェストのパッケージを一覧表示します。 |
list_publishers | このワークスペースの請求アカウントに属する、組織所有の発行元を一覧表示します。 |
create_publisher | 組織所有の発行元を作成します(UUID が識別子となり、表示名は変更可能です)。 |
get_publisher | UUID を指定して、組織所有の発行元を1件取得します。 |
update_publisher | 組織所有の発行元の名前を変更します。UUID は変わりません。 |
add_source | Kaval に監視対象を指定します。publisher_id(組織の発行元 UUID)が必要です。URL、解決する権限機関の名称、またはプッシュするドキュメントを指定します。 |
list_sources | このワークスペースで Kaval が現在監視している対象を一覧表示します。チェックで参照された後に自動登録されたソースも含みます。 |
remove_source | ソースの監視を停止し、その登録を解除します。登録済み/解決済みのワークスペース枠を解放する唯一の方法です(自動登録された引用も対象です。検出された子ソースには、親ごとに別の上限が適用されます)。 |
update_source | 監視中のソースに抽出スキーマを紐づける(または紐づけを解除する)、および/または publisher_id を設定します。reprocess: true を渡すと、欠落分を補うために以前のバージョンを再抽出します。policy-update:manage が必要です。 |
get_source_version_content | 取得済みのソースバージョン1件のキャプチャ済みコンテンツを、未加工のテキストまたは分割済みの sections として取得します。 |
report_outcome | Kaval が精度を調整できるよう、以前のチェック(receipt.id で指定)の後に実際に起きた結果を報告します。 |
verify | 非推奨のパイロット版エイリアスです。結論1件と明示的な evidence_refs から、署名済みの ProofPacket レシートを生成します。check を使用してください。 |
リソース
サーバーは次の JSON リソースを公開します。
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}
トレーニングリソースは読み取り専用です。フィードバックのレビューと同意には training:manage が必要です。
公告の抽出ステータスは読み取り専用です。MCP ではオペレーターによる再キューイング操作を公開していません。
MCP ではトレーニングを開始したり、モデルを昇格させたりすることはできません。
check
// arguments
{
"action": "Approve this prior-authorization request at the in-network rate",
"context": "payer: Aetna; CPT 12345; plan HMO",
"materiality": "critical",
}
または、事実を指定して抽出を省略できます。
{
"claims": [
{
"subject": "Aetna",
"predicate": "requires_prior_auth_for",
"object": "CPT 12345",
"scope": { "plan": "HMO", "state": "CA" },
},
"The 2024 IBC is the current edition",
],
"mode": "fast",
}
レスポンス:
| フィールド | 意味 |
|---|---|
decision | ALLOW — すべての重要な事実が最新の証拠でも引き続き有効です。続行してください。REVIEW — 不明な点がある、再評価中である、または重要度が低〜中程度の変更があります。REVIEW は行動の許可を意味するものではありません。BLOCK — 重要度の高い、または重大な事実が変更されたか、重大な事実が不明です。 |
reason_codes | ALL_FACTS_HOLD、FACT_CHANGED、FACT_EXPIRED、FACT_UNKNOWN、SOURCE_UPDATED_PENDING_REVIEW、SOURCE_UNREACHABLE、NEW_FACT_UNVERIFIED、COMPILATION_UNCERTAIN のうち 1 つ以上 |
facts[] | { fingerprint, text, status: holds | changed | unknown, materiality, served_from_state, last_verified_at, sources[] } — どの認識が変わったのかを確認できます |
receipt | { id, signature, signed_at }。report_outcome に receipt.id を渡すか、get_receipt に渡すと、署名済みドキュメント全体を取得できます |
latency_ms | { compile, lookup, live, total } |
mode: "fast" は保存済みの状態のみで回答し、不明なものはすべて unknown として報告します。
"standard"(デフォルト)では、古くなった事実や新しい事実を max_wait_ms の範囲内で調査することがあります。予算内に収まらなかった事実は unknown として返されます。次のチェックが同じ事実を再確認するわけではないため、その調査結果が次のチェックを準備することはありません。次のチェックではアクションを再コンパイルし、異なる事実のフィンガープリントについて確認するからです。
予算について。 API 自体のデフォルト値は 100000 ms です。初回のアクションチェックでは、複数の新しい前提をリアルタイムで調査するのに、通常 50〜100 秒かかるためです。しかし、MCP ではそこまで待てません。MCP クライアントは 60 秒後にツール呼び出しをキャンセルします。そのため、このサーバーは max_wait_ms: 45000 を明示的に設定し、引数の上限もその値にしています。また、HTTP クライアントの期限を 55 秒に設定し、キャンセルされたリクエストではなく、このサーバー側でリカバリー方法とともに {"error":"timeout"} が返るようにしています。待つよりも時間を区切った REVIEW のほうが望ましい場合は、より小さい max_wait_ms を渡してください。0 を指定すると調査が完全に無効になり、mode: "fast" もこの設定を行います。直接 HTTP や SDK を使う呼び出し元にはこれらの制限は適用されず、100000 の全時間を利用できます。
ウォッチ対象のソースによって裏付けられた事実は、モデル呼び出しもフェッチも行わず、保存済みの状態から回答されます。そのため、重要なアクションのたびに check を呼び出しても低コストです。Kaval が一度も確認したことのない事実は、まず調査する必要があり、数秒かかります。
チェックを常に最新の状態に保つ
add_source を使うと、チェックは調査の実行ではなくデータベースの読み取りになります。通常は、情報源の 名前 を登録するだけで十分です。
{ "kind": "entity", "name": "Aetna", "intent": "payer policy bulletins" }
Kaval はその名前から公開元のページを特定し、適応的に監視します。kind: "url" は単一のページを監視します。kind: "push" は、独自のシステムが POST /v1/events に送信するドキュメントです。登録は任意です。チェックで引用された情報源は自動的に監視されます。ただし、事前に登録しておくと、その事実に対する 最初の チェックが速くなります。
自動監視があるため、remove_source が用意されています。容量には 1 つではなく、2 つの上限があります。
- ワークスペースごとに、アクティブな
registered/resolvedの情報源は最大 200 件(自動登録された引用もここに含まれます。検出された子情報源は含まれません) - 親情報源ごとに、アクティブな
discoveredの子情報源は最大 200 件
スロットを空けるには削除する必要があります。一時停止しても空きません。タスクごとに情報源を登録し、削除しないエージェントは、いずれワークスペースの registered / resolved の上限に達します。その後は新しい引用が通知されずに破棄され、これまで最新の状態を保っていたチェックも、再び調査を行うようになります。タスクで登録した情報源は、タスクの完了時に削除してください。
抽出
create_extraction_schema で JSON Schema を登録し、その id を update_source({ id, extraction_schema_id }) で監視対象の情報源に紐付けると、その後その情報源に届くすべてのドキュメントがスキーマに基づいて自動的に抽出されます。ポーリングは不要です。reprocess: true を指定すると、別のスキーマで実行済みの抽出に対しても、未入力の項目を補うための再抽出を行います。これらの Webhook には source_change: "schema_changed" が含まれます(元の抽出とは source_version_id で紐付けてください)。次のドキュメントを待たず、発行元と期間を指定して一度だけ実行するには、create_extraction_run を直接呼び出します。いずれの場合も、
get_extraction_run / list_extraction_runs は実行のライフサイクル(processing → retry → succeeded / review_required / failed)を報告し、
list_extraction_packages は各発行元/期間についてパッケージ化された月次 PDF とマニフェストの一覧を返します。各パッケージの pdf_href は有効期間の長い Kaval URL です。これに GET(または HEAD)を送信し、302 リダイレクト先の短時間有効な署名付き PDF にアクセスしてください(MCP には個別のダウンロードツールがありません。リダイレクトを有効にして HTTP を使用してください)。
get_source_version_content は、抽出の実行に使われた正規テキスト(または format: "sections")を取得します。
これは、フリーテキストの速報ツール(list_bulletins、get_bulletin、
list_bulletin_extraction_attempts、get_bulletin_extraction_attempt)をスキーマに基づく方式に置き換えるものです。これらのツールは段階的に非推奨となっていますが、引き続き動作します。
差分 Webhook はエージェント用ツールではありません
監視対象の情報源は仕組みの半分にすぎません。情報源が変更されると、Kaval は依存する事実を再評価し、何が変わったかを示す fact_state.delta Webhook を送信します。抽出スキーマが紐付けられた情報源の場合は、抽出レコード(各レコードにネストされた evidence を含む)と、PDF のハイライト用の任意のセクション page / bbox を含む extraction.document(および月次の extraction.package)も送信されます。
extraction_run.period は、発行物/ニュースレターの月を示します。これらのサブスクリプションは、意図的に MCP ツールとして公開されていません。 これらは一度だけ行うデプロイ時の設定です。それぞれ、https エンドポイントと署名シークレットに紐付いた継続的な送信コールバックを作成します。署名シークレットは保存する必要があります。エンドポイントもシークレットも管理していないエージェントがループ内で選択するものではなく、人間またはサービスがデプロイ時に決定するものです。
SDK(Node では kaval.subscribeFactStateDeltas({ callback_url }) /
kaval.subscribeExtractions({ callback_url })、Python では kaval.subscribe_fact_state_deltas(…) /
kaval.subscribe_extractions(…))、subscription_kind: "fact_state" または "extraction" を指定した POST /v1/webhooks(作成時に policy_update は拒否されます)、またはダッシュボードから、一度だけ設定してください。その後、エージェントは check(または list_extraction_runs の読み取り)を呼び出すだけで、すでに高速かつ最新の状態を利用できます。
0.5 からの移行
| 0.5 のツール | 0.6 |
|---|---|
currentness_check | check — { action } または { claims: ["…"] } |
currentness_verify | check — act === true ではなく decision === "ALLOW" に基づいて分岐します |
currentness_extract_and_check | check — 段落を action/context として渡します。Kaval が事実を自動でコンパイルします |
currentness_scan_store | check — { claims: [...] }。1 回の呼び出しにつき最大 20 件 |
currentness_monitor | add_source + fact_state の webhook サブスクリプション(上記を参照)— 差分がプッシュされます |
proof_audit | check — レシートそのものが証明です。get_receipt は署名済みドキュメントを返します |
proof_gate | check — ウォームパスでは保存済みの状態から再チェックするため、再適用する必要はありません |
report_outcome | report_outcome(変更なし。receipt.id を渡します) |
verify | verify。非推奨になりました → check に移行してください |
ステータスの対応関係:current + act: true → すべての事実が holds となる decision: "ALLOW";
stale/contradicted → 事実が changed(重要度に応じて REVIEW または BLOCK);
unsupported/insufficient/conflicting → 事実が unknown(REVIEW、または重大な場合は BLOCK)。
削除されたルートを呼び出す 0.5 クライアントには 410 {"error":"tool_retired","replacement":"/v1/check"} が返されます。
このサーバーはこれを {"error":"tool_retired","message":"this capability was folded into the check tool …","status":410} として表面化させます。
冪等性
契約のアップロード、契約の作成、クレームのレビュー、事実のインポート、create_extraction_schema、
create_extraction_run、および verify には操作キーが含まれます。省略した場合、サーバーがキーを作成します。
結果が不明な失敗の後は、返されたキーを再利用してください。
check には意図的にキーが含まれません。現在の状態を読み取るため、再試行時には再実行され、
二重にカウントされることはありません。
ツールエラー
ツール呼び出しが失敗すると、isError: true と発生した内容を示す JSON 本文が返されるため、
エージェントは文章を解析するのではなく、それに基づいて分岐できます。
error | 対処方法 |
|---|---|
any API code (unauthorized, subscription_required, bad_request, …) | status と API の message を含めてそのまま返されます |
tool_retired | 410 — メッセージに、呼び出したルートに代わるルートが記載されています |
timeout | mode: "fast" またはより小さい max_wait_ms で再試行してください |
network_unreachable | API には到達していません — KAVAL_BASE_URL とネットワークアクセスを確認してください |
request_ambiguous | 結果が不明な冪等呼び出しです。返された idempotency_key を使って再試行してください |
署名済みレシート
チェックのレシートには Ed25519 署名が付与され、単独で検証できます。判定テーブルが公開されているため、レシート自体のファクトリストからサーバーなしでオフライン再計算すると、バイト単位で同じ判定が得られます。@usekaval/kaval/verify を使って検証できます。これは、このパッケージがすでに依存している Node SDK の依存関係のないサブパスです。また、SDK には kaval-receipt-verify CLI も含まれています。暗号学的な有効性、鍵の信頼性、新しさを個別に判定し、Kaval アカウントも API キーも必要ありません。公開鍵は、認証不要の GET /v1/proof-verification-keys/:kid から取得するか、レシートと一緒にアーカイブした鍵セットから読み込みます。後者は完全オフラインで検証できる方法です。
npx -p @usekaval/kaval kaval-receipt-verify verify receipt.json \
--key-url https://api.usekaval.com/v1/proof-verification-keys
check が返すのは { id, signature, signed_at } のみです。実際に署名されたドキュメントを取得するには、その id を使って get_receipt を呼び出します。そこには、状態を含むすべてのファクト、その根拠となるエビデンス(ソースのロケーター、コンテンツダイジェストとその対象、取得時刻と公開時刻)、判定ルールのバージョン、署名鍵 ID が記載されています。エスカレーションする BLOCK に添付するのは、この成果物です。
誠実に示す制約: デモの結果に組織としての権限はありません。本番環境で ALLOW を得るには、顧客にひも付いたアクションポリシーと、該当する実証的なキャリブレーションが必要です。REVIEW は、決して行動の許可を意味しません。
環境変数
| 変数 | 必須 | 用途 |
|---|---|---|
KAVAL_API_KEY | はい | ホストされた Kaval API 用の Bearer キー(https://usekaval.com で作成できます) |
KAVAL_BASE_URL | いいえ | API ベース URL の上書き(セルフホスト/ステージング)。デフォルトは https://api.usekaval.com です |
どちらも server.json と smithery.yaml で宣言されているため、レジストリからインストールする際に、ホストされた API だけでなくセルフホストのデプロイ先も指定できます。
マーケティングサイトは /api/verify プロキシに KAVAL_API_URL を使用し、KAVAL_BASE_URL は使用しません。
プログラムからの使用
このパッケージは主に CLI(kaval-mcp)として使用します。埋め込み用のサーバーファクトリーもエクスポートしています。
import { createMcpServer, createClientFromEnv } from "@usekaval/mcp";
const server = createMcpServer(createClientFromEnv());
// connect `server` to your own MCP transport
または、独自に設定したクライアントを渡します。
import { createMcpServer } from "@usekaval/mcp";
import { Kaval } from "@usekaval/kaval";
const server = createMcpServer(
new Kaval({ apiKey: process.env.KAVAL_API_KEY }),
);
未使用のスキーマを削除するには、{ "id": "<schema-id>" } を指定して delete_extraction_schema を使用します。削除すると、スキーマはリストやセレクターに表示されなくなります。過去の抽出レコードには、その定義が保持されます。アクティブな監視対象ソースでそのスキーマを使用している場合、API は 409 schema_in_use を返します。
スキーマ名を変更するには、{ "id": "<schema-id>", "name": "New name" } を指定して rename_extraction_schema を使用します。定義とハッシュは変更されません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。