mcpField
F
Fetch SCITT receipts and on-chain anchors for offline verification

Fetch SCITT receipts and on-chain anchors for offline verification

本地服务
github.com安全01 周前更新

关于 Fetch SCITT receipts and on-chain anchors for offline verification

@forestrie/mcp-resolve 是用于获取 SCITT 收据及其验证材料的 MCP 服务,面向配合 @forestrie/mcp-verify 进行离线验证的用户。它从 SCITT 服务或区块链读取数据,并标明来源及其可支持的信任问题。

主要功能

  1. 01查询收据注册状态
  2. 02获取并解码 SCITT 收据
  3. 03获取日志创世文档和配置
  4. 04读取累加器与检查点历史
  5. 05获取合约 KS256 证明

适用场景

  1. 01为离线收据验证获取所需材料
  2. 02通过链上读取检查日志累加器
  3. 03核对收据注册状态与来源
  4. 04为合约根验证获取签名证明

MCP 相关

此 MCP 服务向 MCP 客户端提供 SCITT 配置、注册状态、收据、创世文档和链上数据的获取工具。它为 @forestrie/mcp-verify 提供验证材料;验证本身由该工具包在本地完成。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"dev-forestrie-resolve": {
"command": "npx",
"args": [
"-y",
"@forestrie/mcp-resolve"
],
"env": {
"FORESTRIE_BASE_URL": "<FORESTRIE_BASE_URL>",
"FORESTRIE_RPC_URL": "<FORESTRIE_RPC_URL>"
}
}
}
}
启动命令npx -y @forestrie/mcp-resolve
需要配置的环境变量
FORESTRIE_BASE_URLSCRAPI base URL used when a call omits baseUrl. Optional; the package ships no default and names no operator.
FORESTRIE_RPC_URLJSON-RPC endpoint used when a call omits rpcUrl: your own chain access. Optional; the package ships no default and names no provider.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npm@forestrie/mcp-resolve0.4.1

工具

7

收录的工具列表 · 更新于 1 周前

参数类型必填说明
baseUrlstring否任意 SCRAPI 基础 URL;省略时回退到 FORESTRIE_BASE_URL——软件包本身不会设置默认值

详细介绍

@forestrie/mcp-resolve

获取 SCITT 收据、其日志的创世文档及其链上累加器,并将它们交给 @forestrie/mcp-verify 进行验证——包括通过链上读取获取分视图答案。这个 MCP 服务会获取验证器要验证的材料:收据、创世文档、累加器快照、注册状态和服务配置。每个结果都会说明其字节的来源,以及它们能支持信任模型中的四个问题中的哪些问题。在 MCP 注册表中列为 dev.forestrie/resolve。

验证器完全在你的进程中运行,无需网络、账户、密钥或后端;它自身的规则是,安装它绝不能意味着存在网络依赖。因此,所有负责获取内容的部分都放在这里。

使用

{
  "mcpServers": {
    "forestrie-resolve": {
      "command": "npx",
      "args": ["-y", "@forestrie/mcp-resolve"],
      "env": {
        "FORESTRIE_BASE_URL": "https://api-a.forest-2.forestrie.dev",
        "FORESTRIE_RPC_URL": "https://<your-chain-rpc-endpoint>"
      }
    }
  }
}

两个环境变量都是可选的,且都由你提供。baseUrl 可以是任意 SCRAPI 基础 URL,rpcUrl 是你自己的链访问地址;调用时可以显式传入其中任意一个,只有调用未提供时才会使用环境变量值。该软件包不附带默认运营方或默认链提供方,也不会指定任何运营方或提供方。

有两个公开通道,它们是示例,并非默认值:

通道基础 URL服务 ID
Ahttps://api-a.forest-2.forestrie.devcanopy-dev-1
Bhttps://api-b.forest-2.forestrie.devcanopy-prod-1

需要 Node 20.11 或更高版本。

完整示例:一个收据,端到端

以下所有值都是公开的,其中会随版本变化的值来自验证器自身的 tarball。@forestrie/mcp-verify 会将每个版本注册到 Forestrie 日志中,并在 fixtures/self/ 下附带收据(其中的 docs/self-registration.md),因此发布的软件包包含一份声明、一张收据、一份创世文档和一个日志所有者密钥;本软件包可以获取这些内容,并针对在线通道进行验证。下面的运行大约需要四秒,最终通过公共 RPC 端点得出 split-view ok,无需密钥或账户。

坐标值来源
基础 URLhttps://api-a.forest-2.forestrie.dev上文的通道 A(示例,并非默认值)
引导日志e22c8d55-3f88-b2b5-f225-5d2c2441bcddforest 根;也可从创世文档中解码
发布日志da6f297c-4a0c-4c9a-b2ae-e701e558721d验证器注册版本的日志
内容哈希sha256(fixtures/self/statement.cose)tarball;fixtures/self/manifest.json 列出了相同的摘要
条目 IDfixtures/self/entry-id.txttarball;query_registration 也会返回该值
massif 高度无需手动输入位于 query_registration 返回的 receiptUrl 中
日志所有者密钥fixtures/self/log-key.xy.b64(base64 文本)tarball
链ID 84532(Base Sepolia),univocity 0xe22c8d553f88b2b5f2255d2c2441bcdd0d50cd58绑定在创世文档中;fetch_genesis 会对其解码

要在空目录中获取 tarball:

npm i @forestrie/mcp-verify
ls node_modules/@forestrie/mcp-verify/fixtures/self/
shasum -a 256 node_modules/@forestrie/mcp-verify/fixtures/self/statement.cose

运行日期为 2026-09-22、针对已发布的 0.5.0 bundle 执行时,每次调用返回的序列、JSON 参数和单行结果如下 (其 entry id 为 a0caa672b7030b000000000000000001;你的 entry id 以 entry-id.txt 中的内容为准):

  1. fetch_scitt_configuration {"baseUrl": "https://api-a.forest-2.forestrie.dev"} → 从 …/.well-known/scitt-configuration 获取了 SCITT 配置(serviceId canopy-dev-1)
  2. query_registration {"baseUrl": …, "bootstrapLogId": "e22c8d55-3f88-b2b5-f225-5d2c2441bcdd", "logId": "da6f297c-4a0c-4c9a-b2ae-e701e558721d", "contentHash": "<sha256 of statement.cose>"} → 注册完成;回执位于 https://api-a.forest-2.forestrie.dev/logs/e22c8d55-…/da6f297c-…/14/entries/a0caa672b7030b000000000000000001/receipt — status: "receipt-available",receiptUrl(其中包含 massif 高度 14)以及 entryId。
  3. fetch_receipt {"receiptUrl": "<from step 2>"} → 从 …/receipt 获取了回执(438 B) — receipt.sha256 与 tarball 的 receipt.cbor 摘要相同;receiptLogId 指向 publications 日志。
  4. fetch_genesis {"baseUrl": …, "logId": "e22c8d55-3f88-b2b5-f225-5d2c2441bcdd"} → 从 …/api/forest/e22c8d55-…/genesis 获取了创世文件(160 B):链 84532 上的 univocity 0xe22c8d553f88b2b5f2255d2c2441bcdd0d50cd58 — 与 tarball 中的 genesis.cbor 字节完全一致。请保留它:以下调用会将其作为字节传回,不会在同一次调用中获取。
  5. verify_fetched_receipt {"receiptUrl": …, "entryId": "<entry-id.txt>", "payload": {"path": "…/fixtures/self/statement.cose"}, "trust": {"root": "known-log-key", "keyXy": {"b64": "<contents of log-key.xy.b64>"}}} → 验证:通过 · 根=known-log-key · 封存有效;此根未回答视图分歧问题;此根未回答追加权限问题;归属有效
  6. 使用 "trust": {"root": "genesis", "genesis": {"path": "…/fixtures/self/genesis.cbor"}} 调用相同工具 → 验证:在签名处失败(delegation_invalid) · 根=genesis · … 这是预期结果,并非篡改:创世根的离线遍历只解析从 forest 根开始的一跳委托,而 publications 日志是其孙级节点。结果中包含 genesis_root_reaches_direct_delegates_only,对此作了明确说明。 请像第 5 步和第 7 步那样,在密钥或累加器下验证此回执。
  7. verify_fetched_receipt {"receiptUrl": …, "entryId": …, "payload": …, "trust": {"root": "known-accumulator", "chain": {"genesis": {"path": "…/fixtures/self/genesis.cbor"}, "rpcUrl": "https://sepolia.base.org", "logId": "da6f297c-4a0c-4c9a-b2ae-e701e558721d"}}} → 验证:通过 · 根=known-accumulator · 封存有效;视图分歧检查通过;此根未回答追加权限问题;归属有效 — anchor.blockNumber、anchor.matchedPeak 和 provenance.root.from.rpcUrl 会说明是哪个链状态提供了答复。如果自回执峰值以来日志有所增长,同一调用会回溯已发布的检查点,并添加 root_read_from_chain_history。
  8. 可选:fetch_accumulator {"chain": {…as in 7…}, "forReceipt": {"receipt": …, "payload": …, "entryId": …}} 会将快照作为字节返回,供保存;之后,@forestrie/mcp-verify 的 verify_receipt 在 {"root": "known-accumulator", "accumulator": <those bytes>} 下再次离线回答视图分歧问题。

链,以及查看位置。 第 7 步需要访问链 84532(Base Sepolia)的 JSON-RPC。本 package 不附带任何 provider,也未指定默认 provider;rpcUrl(或 FORESTRIE_RPC_URL)由你自行设置。以下端点是第三方公共服务,仅作为编写本示例时未经身份验证即可响应的示例列出;除初次尝试外,请使用你自己的 provider。

端点2026-09-22
https://sepolia.base.org已响应
https://base-sepolia-rpc.publicnode.com已响应
https://base-sepolia.drpc.org已响应
https://base-sepolia.gateway.tenderly.co已响应
https://1rpc.io/base-sepoliaHTTP 400
https://rpc.ankr.com/base_sepoliaHTTP 403
https://base-sepolia.g.alchemy.com/v2/demoHTTP 429

两个陷阱。 keyXy: {"path": "log-key.xy.b64"} 会失败:该文件是 base64 文本,而 path 输入会按原始字节读取——请将其内容作为 b64 传入。两个服务中的字节字段都名为 b64(此处也接受 base64 作为别名),因此从验证器中学到的数据结构可以原样用于此处。

test/core/readme-example.test.ts 会根据已记录的 lane-A fixture 校验本节中的坐标,因此重新采集 fixture 不会悄然导致示例失效。

八种工具

工具数据来源功能支持能力
fetch_scitt_configuration获取GET {baseUrl}/.well-known/scitt-configuration无
query_registration获取针对某条 statement 发起一次注册状态请求;绝不轮询无
fetch_receipt获取获取并解码收据,并报告其证书所指明的日志单独使用时无
fetch_genesis获取获取 forest 的创世文档,其中包含其链绑定和引导密钥sealing,仅适用于你保留的副本
fetch_accumulator链上读取读取日志已发布的累加器;向历史记录回溯以查找被埋藏的峰值split-view、sealing、append-authority
fetch_checkpoint_history链上读取在区块预算范围内,按从新到旧的顺序读取已发布的检查点与 fetch_accumulator 相同
fetch_ks256_attestation链上读取在指定区块询问合约 KS256 根是否接受收据的证书单独使用时无;mcp-verify 会使用它
verify_fetched_receipt获取,以及用户提供或链上读取获取收据,并根据你提供或从链上读取的根验证该收据验证器自身的回答,未经改动

fetch_ks256_attestation 适用于根为合约(Safe)的 forest。 这样的根无法通过 ecrecover 检查,因此验证器需要合约自身的回答;而获取该回答需要链上读取,验证器绝不会自行执行。将收据和根地址或你持有的 genesis 提供给工具;它会在一个区块上读取 isValidSignature(digest, signature)(默认读取最新区块,然后固定到该区块),并以 canonical-CBOR 证明的形式返回回答:

fetch_ks256_attestation  {receipt: {b64: …}, genesis: {b64: …}, rpcUrl: …, block?: 123}
  -> attestation {base64, byteLength, sha256}, fields {chainId, address, digest,
     signatureHash, blockNumber, blockHash, magic}, provenance, supports
verify_receipt           {receipt: …, …, ks256Attestation: {b64: <attestation.base64>}}

结果表示该证书在_该区块_上由合约的签名者验证有效;任何拥有 RPC 的人都可以重新执行调用以确认。对于没有合约代码的根(外部拥有的根无需此验证)、调用回退,或回答不完全是一个 32 字节的字(0x1626ba7e 后跟 28 个零字节;短返回、填充不干净、多余字或回显调用自身数据均会被拒绝),以及 RPC 所连接的链与 genesis 所属链不同时,工具会拒绝并且不返回证明。两次状态读取都通过区块哈希固定(EIP-1898),因此证明中的哈希就是读取状态时所对应的哈希。如果在 genesis 旁提供了 root,那么 root 就是被询问的合约,而 genesis 仅用于提供预期链。

每种工具都标注为只读、幂等且开放世界,因为它们都会与进程外部的对象通信。每项 supports 的含义及原因见 docs/what-fetching-proves.md。

一份获取到的内容能证明什么

从运营方获取的收据,在根据你持有的信任根完成验证之前,只是运营方的说法。forestrie/protocol 中的公开信任模型 spec/receipt-trust-model.md 列出了收据可以回答的四个问题(封存、视图分裂、追加权限、归属),以及调用方可以据此验证的四种信任根(genesis、known-log-key、known-accumulator、checkpoint-chain)。这些信任根没有先后顺序。哪一种合适,取决于你持有什么;获取操作会改变你持有的内容。

因此,这里的每个结果都包含 provenance(对于每项制品,说明它是从 URL 获取、从链上读取,还是由你提供,以及时间)和 supports(说明该材料在何种信任根下可作为哪些问题的证据,并附上一行说明)。这些说明是固定字符串,测试会逐字断言;相关列表和解释见 docs/what-fetching-proves.md。

工具接口中内置了以下三项结论,而不是只在文档中说明:

  • 获取到的 genesis 永远不能作为信任根。 verify_fetched_receipt 接受你提供的字节作为信任根,或接受从链上读取的累加器;其模式中没有任何形式可以在同一次调用中获取 genesis 并以其为根进行验证。在检查时从运营方获取 genesis,意味着收据和信任根都由运营方提供;这只能证明它与运营方今天选择提供的文档一致,除此之外不能证明任何事。提供 fetch_genesis 是为了让你获取一次文档、保存下来,此后将其作为字节传入。
  • 链绑定属于森林,而非运营方。 不歧义合约地址和链 ID 绑定在森林的 genesis 文档中。fetch_accumulator 和 verify_fetched_receipt 的链路径从你持有的 genesis 中读取这些值,或者要求你显式提供;绝不会使用默认值、绝不会使用调用内部获取的 genesis,也绝不会使用环境变量。
  • genesis 信任根只能覆盖直接委托对象,结果也会明确说明这一点。 在提供的 genesis 下,验证器的离线遍历只会解析森林根下的一跳委托。来自授权链更下游日志的收据——验证器自己的发布日志就是一个孙级日志——在该信任根下会以 delegation_invalid 失败,而 verify_fetched_receipt 会追加 genesis_root_reaches_direct_delegates_only,说明这是遍历能力的限制,并非对收据的判定。此类收据应使用 known-log-key 或 known-accumulator 验证。
  • 被折叠的峰值依据同一信任根,从已发布的历史记录中查询。 后续增长将收据的峰值折叠到更大的峰值中时,链路径会在你设置的区块预算内回查已发布的检查点,并说明这一点(root_read_from_chain_history)。它绝不会进行无界扫描。

验证器自身的 TRANSPARENCY.md(随其 tarball 一同提供)说明了什么是透明度日志以及收据包含什么;本软件包不再重复这些内容。其 docs/trust-roots.md 深入介绍了这些信任根。

此软件包绝不会做的事

  • 绝不写入:不注册、不授权、不创建密钥。
  • 绝不轮询:query_registration 只发送一次请求,由你决定是否再次调用。HTTP 429 会作为包含 retryAfterMs 的结构化 problem 返回,而不是作为错误。
  • 绝不替你选择操作员或链提供方。
  • 绝不跨调用缓存获取的创世数据或累加器:每个结果都带有一个新的 at。
  • 绝不修改验证器的回答。verify_fetched_receipt 会原样返回验证器的 stages、questions 和 diagnostics,并追加两条说明字节来源的诊断信息。not_answered_by_this_root 是一个真实回答,会原样传递给你。

目录结构与门禁

src/core/   pure over bytes: URL construction, response classification,
            provenance and supports labelling, the compose logic.
            No node:*, no fetch, no fs. Exported as ".".
src/net/    the ONLY place fetch is called; every function takes fetchImpl.
            Exported as "./net".
src/node/   the MCP adapter: SDK, stdio, {path}/base64 inputs, env defaults.
            Exported as "./server".

CI 会根据 AGENTS.md 中所述的纯净性和打包门禁进行阻断。单元测试会在会抛出异常的 fetch 下运行,并重放记录在 test/fixtures/ 中的交互。存在使用真实通道的真实项目,但需选择加入,且绝不会作为必需检查。

pnpm test        # purity gates + unit tests
pnpm typecheck
pnpm build
pnpm test:live   # FORESTRIE_LIVE=1 plus FORESTRIE_BASE_URL, FORESTRIE_RPC_URL, UNIVOCITY_ADDRESS, CHAIN_ID and GENESIS_CBOR_B64

约定、不变量和发布流程见 AGENTS.md。

依赖项

package.json 中的版本均精确锁定,并会审慎更新。在 @forestrie/mcp-verify 中,只使用 "." 核心导出。每个请求(包括链读取)都通过注入的 fetchImpl 发出。

许可证

MIT。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。