mcpField
A
Arcaeon Adapter

Arcaeon Adapter

本地服务
arcaeon.io安全08 周前更新

关于 Arcaeon Adapter

Arcaeon Adapter 是位于 MCP 客户端与服务之间的 stdio 代理,自动记录每次工具调用的摘要、结果状态和耗时,适用于需要审计 MCP 操作的部署。它在独立进程中转发协议字节,并将记录写入哈希链账本。

主要功能

  1. 01逐字节转发 JSON-RPC
  2. 02记录每次工具调用
  3. 03记录参数与结果摘要
  4. 04捕获未获响应的调用
  5. 05哈希链防篡改账本

适用场景

  1. 01为 MCP 服务调用建立审计记录
  2. 02核对工具调用是否留下完整记录
  3. 03检查账本是否被修改或重排

MCP 相关

它作为 stdio 代理置于 MCP 客户端与服务之间,转发 JSON-RPC,并将每次 tools/call 写入自己的账本。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"io-arcaeon-adapter": {
"command": "uvx",
"args": [
"arcaeon-adapter"
]
}
}
}
启动命令uvx arcaeon-adapter

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

安装包
pypiarcaeon-adapter0.2.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

arcaeon-adapter

arcaeon-ledger 能证明记录未被篡改,却无法证明记录是_完整的_——因为要写入什么由 Agent 决定。这个工具把笔交到了别处。

arcaeon-adapter 是一个 stdio 代理,位于 MCP 客户端和 MCP 服务之间。它会逐字节转发 JSON-RPC,并在每次 tools/call 时向自己的账本写入一行哈希链记录:调用了哪个工具、参数和结果的摘要、成功还是出错,以及耗时。

它在独立的 OS 进程中运行。Agent 无须参与,无法跳过它,也看不到它。

pip install arcaeon-adapter arcaeon-ledger

只需一行配置、无需编写代码,即可包装任意 MCP 服务的命令:

{ "mcpServers": {
    "ledger": {
      "command": "python",
      "args": ["-m", "arcaeon_adapter", "--ledger", "seam.log.jsonl", "--",
               "python", "-m", "arcaeon_ledger.mcp_server", "--log", "agent.log.jsonl"]
    }
} }

也可以直接从 Shell 运行:

python -m arcaeon_adapter --ledger seam.log.jsonl -- <your mcp server command...>

日志中会记录什么

以下是包装 arcaeon-ledger 自身的 MCP 服务时生成的真实记录(账本通过账本记录自身),为适应宽度做了截取。记录由 adapter 0.1.0 和 ledger 0.5.7 捕获;当前运行会在 seam_impl 和 ledger_backend 中标注已安装的版本:

{"evt":"session_begin","seam":"mcp-stdio","seam_impl":"arcaeon-adapter/0.1.0",
 "session":"25eda195-70e8-45cb-9035-be9f61cfc759","seq":1,
 "server":"arcaeon_ledger.mcp_server","ledger_backend":"arcaeon-ledger/0.5.7",
 "command":["python","-m","arcaeon_ledger.mcp_server","--log","agent.log.jsonl"],
 "command_digest":"sha256:json-c14n:v1:ec06bd01…","raw_payloads":false,
 "ts":"2026-08-19T14:18:08Z","chain":"0081ec1fe5d98395192f595e553b4133"}

{"evt":"tools_list","seq":3,"tools":["ledger_append","ledger_verify"],"tool_count":2,
 "tools_digest":"sha256:json-c14n:v1:b85c9fce…","status":"ok", …}

{"evt":"tool_call","seq":4,"tool":"ledger_append","rpc_id":"3",
 "args_digest":"sha256:json-c14n:v1:cfb2bb50…",
 "result_digest":"sha256:json-c14n:v1:ba037f70…",
 "status":"ok","ms":144, …}

{"evt":"session_end","seq":6,"reason":"child_exit","exit_code":0,
 "rows_before_end":5,"calls":2, …}

在同一次运行中,被包装服务自己的日志——也就是 Agent 记得调用 ledger_append 时它所记下的日志——只有一行。而 seam 日志有六行。这正是整个产品的意义所在。

字段用途
evttool_call、session_begin、session_end、mcp_initialize、tools_list
seam始终为 "mcp-stdio"——即来源层级。独立进程在协议层观察到这条记录。下游验证器读取此字段,以区分基础设施级捕获与 Agent 可能直接不调用的协作式进程内回调。
session / seq一个代理进程对应一个会话;seq 是会话内连续递增的全序号。session_begin + session_end 标记运行的起止,便于审核者配对会话的开始和结束。
args_digest / result_digestsha256:json-c14n:v1:<hex>——格式自描述,即使陌生人手中只有这条记录,也能复现计算结果。
status / msok / error / unanswered,以及墙钟耗时。error 同时涵盖 JSON-RPC error 和包含 isError: true 的 result。

默认记录摘要,而非载荷。 记录可以证明哪些字节经过了这条 seam,而不会保留这些字节。悄悄变成每条提示词和每个结果副本的审计日志是负担,而非资产——不包含个人信息的核心日志也更容易留存多年。--raw 会嵌入载荷,供愿意承担相关风险的部署者使用;无论如何都会保留摘要。

未获得答复的调用仍会留下一条记录(status: "unanswered")。 否则,“在调用过程中终止服务”就会成为让操作不在 seam 留下痕迹的手段,而这正是本工具要堵住的漏洞。

验证

seam 日志是普通的 arcaeon-ledger 文件:

python -m arcaeon_ledger.cli verify seam.log.jsonl

编辑或删除一条记录,或重新排序记录——之后每个链接都会失效,verify 会指出具体行号。

诚实的边界

一个接缝上的适配器,只会完整记录该接缝上的内容——仅此而已。 Agent 仍然可以绕过它采取行动:直接进行 HTTP 调用、使用未包装的 MCP 服务,或执行 shell 命令;这些都不会经过此代理,也不会进入这本账册。双账本问题并不会消失;任何日志层都无法强迫所有行为都诚实。适配器能保证的范围更窄,但确实可靠:所有经过已检测接缝的内容,都会自动写入记录,而且记录本身可供验证。 诚实是在各个接缝处强制实现的,而非无处不在——它是一片街区,不是一把锁。

具体而言,以下内容对它不可见:

  • 你的运行框架内置的工具(Bash、文件编辑、网页抓取)——它们根本不会接触 MCP
  • 任何你未包装的 MCP 服务
  • Agent 直接发起的 HTTP 请求
  • 模型的推理;推理不是一项操作,也不会留下线上痕迹
  • 大于 --max-frame 的帧(会正常转发;在 session_end 中计入并报告为 oversize_frames_unlogged,绝不会悄无声息地漏掉)

关于合规,直说:这不会让任何人自动符合任何合规要求。 EU AI Act 第 12 条等法规规定了提供者或部署者的义务,而义务由人承担,不是由库承担。这实际上是:一种机制,能让一个接缝处的记录自动完成,而非依赖自愿;否则,你就得自己构建这套机制。保留策略、日志语义、风险分类以及其他所有义务,仍由你负责。任何向你兜售「让你实现合规」套件的人,兜售的都是一个故事。

控制配置的人也可以移除包装器。这与所有日志层都有的限制属于同一类问题;我们在这里明说,而不是把它藏在脚注里。

保真度是 P0 属性

会破坏、重排或延迟客户 JSON-RPC 的代理,还不如没有代理。因此,在设计上,保真度优先于观测:

  • 先转发字节,再从副本中进行观测。 这里的解析缺陷无法更改或拦截流量;最坏也只是生成错误的记录行。
  • 端到端传递原始二进制数据。 全程不使用文本模式——在 Windows 上,文本模式会将 \n 改写为 \r\n,悄无声息地改变每一帧。
  • 绝不重新分帧。 我们绝不会解析一帧再重新输出。典型的代理错误是 json.dumps(json.loads(frame)):语义相同,字节却不同。
  • 每个方向各用一个线程,因此各方向内的顺序由操作系统决定。
  • 子进程的 stderr 继承而来,不通过管道传输。 其诊断信息会出现在与未包装时完全相同的位置;正常运行时,代理自身不会打印任何内容。
  • 格式错误的帧会原样转发,不记录。 如果服务端在 stdout 中打印了一行意外内容,它仍会继续工作;我们不会猜测,因为猜出来的审计记录就是虚构。
  • 子进程的退出代码就是代理的退出代码。

我们通过以下方式测试这一点:先让一个脚本客户端直接连接到合成 MCP 服务,再通过代理连接,并要求两次 stdout 流在字节层面完全相同——包括一个跨越约 64 次管道读取的 4 MB 帧、Unicode、内嵌 CRLF、格式错误的行、没有 id 的通知,以及末尾没有换行符的最后一帧。

证明这些检查确实能失败

python -m arcaeon_adapter.selftest

从未失败过的检测工具,什么也证明不了。每个测试用例先在干净的 fixture 上通过,然后再进行变异,并要求同一项检查失败——中间还会加一道空操作防护,因为毫无变化的变异同样证明不了任何事。输出已缩略(每个 PASS 行截去了两行标题和末尾部分;不同运行中的 drop_byte 长度会相差一两个字节):

PASS passthrough_fidelity GREEN: 2001202 bytes identical byte-for-byte through the proxy
PASS passthrough_fidelity RED on reserialize: corruption detected (length 2001202 vs 2001097)
PASS passthrough_fidelity RED on drop_byte: corruption detected (length 2001202 vs 2001168)
PASS one_row_per_call GREEN: 5 tools/call frames -> 5 tool_call rows, 9 rows total, seq 1..9
PASS one_row_per_call RED on log_on_request: count check caught 10 rows for 5 calls
PASS unanswered_call_logged GREEN: unanswered `quiet` call rowed with args_digest bound
PASS unanswered_call_logged RED on no_flush: dropping the shutdown flush loses the row
PASS tamper_detected GREEN: seam log verifies (ok=True, rows=9)
PASS tamper_detected RED on edited args_digest: first_break='line 4: chain mismatch'
PASS digest_recipe_frozen GREEN: 3 frozen json-c14n:v1 vectors reproduce exactly
PASS digest_recipe_frozen RED on unsorted_keys: drifted canonicalizer produces a different digest

ALL CHECKS PASSED — and every one was observed failing on its own defect.

保真度变异会注入到真实的中继器中,而非 mock 中,因此,这里证明的是:如果正式代码路径发生回归,比较检查能够将其检测出来。

选项

--ledger PATH      seam ledger (required). Keep it SEPARATE from any ledger the
                   wrapped server writes: one file, one writer, clean provenance.
--server NAME      label for the wrapped server in every row (default: derived
                   from the command — `-m pkg.mod` reads as "pkg.mod", not "python")
--session ID       session id (default: a fresh uuid4 per proxy process)
--raw              embed raw argument and result payloads. Off by default.
--max-frame BYTES  frames larger than this are relayed but not logged (default 64 MiB)

安装和依赖项

运行时仅使用标准库。arcaeon-ledger 是预期使用的写入器,也是让 行可验证的关键——但我们有意不将其设为硬依赖:只需编辑一行配置,就能 将它包装到其他人已有的 MCP 服务中;绝不能因为缺少软件包而导致他们的服务 无法启动。没有该软件包时,程序会通过字节兼容的回退机制写入行,并在 ledger_backend 中由 session_begin 说明这一点,这样审核者就无需猜测是哪种写入器生成了链。 (这种字节兼容性已在测试套件中验证,并非仅仅在此声称。)

运行时绝不进行网络调用。

pytest -q                            # 146 tests
python -m arcaeon_adapter.selftest   # the mutation harness

状态

v0。可用,已测试,并已在我们自己的 MCP 服务上实际使用。以下功能刻意尚未实现: --authority 标记、--bind-inputs 工件绑定、--auto-pin 见证发布,以及 harness-hook / HTTP-gateway 接口。详见 CHANGELOG.md。

MIT。

评论

支持 Markdown

第一次接触 MCP?

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

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