
Arcaeon Adapter
io.arcaeonPublished by arcaeon.iov0.2.0Updated Oct 24, 2026
MCP stdio proxy that logs the tool-call seam to the ledger without the agent's cooperation
Overview
A local stdio proxy that sits between an MCP client and server, logging every tool call to a hash-chained ledger without the agent's cooperation.
- What you can do
- It wraps any MCP server command and forwards JSON-RPC byte-for-byte, writing one hash-chained row per tools/call: which tool, digests of arguments and result, ok or error, and duration. It also records session begin/end, initialize, and tools/list events, and logs calls that never receive an answer. By default it stores digests rather than payloads; a --raw option embeds the payloads. The resulting log can be verified with the companion arcaeon-ledger CLI, which names the exact line where a chain breaks.
- When to use it
- Use it when you want an automatic, tamper-evident record of everything crossing one MCP seam, rather than relying on the agent to log its own actions. It is meant for auditing or review of a wrapped MCP server's tool calls. It only covers the seam it is wrapped around, not other tools or direct network calls.
- Requirements
- Runs as a local process on the user's machine (desktop only, stdio transport). Install via pip (arcaeon-adapter, optionally arcaeon-ledger). No accounts, API keys, environment variables, or headers are declared, and it makes no network calls at runtime. It is configured by wrapping an existing MCP server command with a --ledger path.
Installation
In SourceWeft
- Open Arcaeon Adapter in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
arcaeon-adapter
arcaeon-ledger proves a record wasn't altered. It can't prove the record is complete — because the agent decides what to write. This moves the pen.
arcaeon-adapter is a stdio proxy that sits between an MCP client and an MCP
server. It forwards JSON-RPC byte-for-byte, and on every tools/call it writes
one hash-chained row to its own ledger: which tool, digests of the arguments and
the result, ok or error, how long it took.
It runs in its own OS process. The agent is not consulted, cannot skip it, and cannot see it.
Wrap any MCP server's command — one line of config, zero code:
Or straight from a shell:
What lands in the log
Real rows, from wrapping arcaeon-ledger's own MCP server (the ledger logging
itself through the ledger), trimmed for width. Captured on adapter 0.1.0 with
ledger 0.5.7; a current run stamps the installed versions in seam_impl and
ledger_backend:
In that same run, the wrapped server's own log — the diary it keeps when the
agent remembers to call ledger_append — had one row. The seam log had six.
That difference is the entire product.
Digests, not payloads, by default. The row proves which bytes crossed the
seam without keeping them. An audit log that quietly becomes a copy of every
prompt and every result is a liability, not an asset — and a person-free core is
much easier to retain for years. --raw embeds the payloads for deployers who
own that risk; the digests stay either way.
A call that never gets an answer still gets a row (status: "unanswered").
Otherwise "kill the server mid-call" would be a way to make an action leave no
trace at the seam, which is the exact hole this exists to close.
Verify it
The seam log is an ordinary arcaeon-ledger file:
Edit a row, delete one, reorder them — every later link breaks and verify names
the exact line.
The honest limit
An adapter on one seam logs that seam completely — and nothing else. An agent can still act around it: a direct HTTP call, an un-wrapped MCP server, a shell command never crosses this proxy and never hits this ledger. The second-set-of-books problem does not go away; no logging layer can force total honesty. What the adapter guarantees is narrower and real: everything that crossed the instrumented seam is in the record, automatically, and the record proves itself. Honesty is forced at the seams, not everywhere — not a lock, a neighborhood.
Specifically blind to:
- your harness's built-in tools (Bash, file edits, web fetch) — they never touch MCP
- any MCP server you did not wrap
- HTTP the agent makes natively
- the model's reasoning, which is not an action and leaves no wire trace
- frames larger than
--max-frame(relayed fine; counted and reported insession_endasoversize_frames_unlogged, never a silent gap)
And on compliance, plainly: this does not make anyone compliant with anything. Regulations like the EU AI Act's Art. 12 place duties on a provider or deployer, and duties land on people, not libraries. What this is: a mechanism that makes recording at one seam automatic rather than voluntary, which is a thing you would otherwise have to build. Retention policy, log semantics, risk classification, and every other obligation remain yours. Anyone selling you a package that "makes you compliant" is selling you a story.
Whoever controls the config can also remove the wrapper. That is the same class of limit every logging layer has, and it is stated here rather than in a footnote.
Fidelity is the P0 property
A proxy that corrupts, reorders, or delays a customer's JSON-RPC is worse than no proxy at all. So the design puts fidelity ahead of observation, structurally:
- Bytes are forwarded first, observed second, from a copy. A parsing defect here cannot alter or withhold traffic; the worst it can do is produce a wrong row.
- Raw binary end to end. No text mode anywhere — on Windows that would rewrite
\nas\r\nand silently alter every frame. - No reframing, ever. We never parse a frame and re-emit it. The classic proxy
bug is
json.dumps(json.loads(frame)): semantically identical, byte-different. - One thread per direction, so ordering within a direction is the OS's.
- The child's stderr is inherited, not piped. Its diagnostics land exactly where they did unwrapped, and the proxy itself prints nothing on an honest run.
- Malformed frames are relayed untouched and not logged. A server that prints a stray line to stdout keeps working; we don't guess, because a guess in an audit record is fiction.
- The child's exit code is the proxy's exit code.
This is tested by running a scripted client against a synthetic MCP server directly, then through the proxy, and requiring the two stdout streams to be identical bytes — including a 4 MB frame spanning ~64 pipe reads, unicode, embedded CRLF, malformed lines, a notification with no id, and a final frame with no trailing newline.
Prove the checks can fail
An instrument that has never failed proves nothing. Every case runs GREEN on a
clean fixture, then mutates and requires the same check to go RED — with a
no-op guard in between, because a mutation that changes nothing proves nothing
either. Output abridged (two header lines and the tail of each PASS line cut;
the drop_byte length differs by a byte or two between runs):
The fidelity mutations are injected into the real relay, not a mock, so what's proven is that the comparison would catch a regression in the shipping code path.
Options
Install and dependencies
Stdlib only at runtime. arcaeon-ledger is the intended writer and is what makes
a row provable — but it is not a hard dependency, on purpose: this gets
wrapped around somebody else's working MCP server by editing one line of config,
and a missing package must never be why their server fails to start. Without it,
rows are written by a byte-compatible fallback and session_begin says so in
ledger_backend, so a reviewer never has to guess which writer produced a chain.
(That byte-compatibility is asserted in the test suite, not just claimed here.)
No network calls at runtime. Ever.
Status
v0. Works, tested, dogfooded on our own MCP server. Deliberately not yet built:
--authority stamping, --bind-inputs artefact binding, --auto-pin witness
publication, and harness-hook / HTTP-gateway seams. See CHANGELOG.md.
MIT.
Source: adapter/README.md at commit 4aaceaf
Tools
0Version history
2- v0.2.0LatestSep 23, 2026
- v0.1.4Sep 23, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
