Inspiration

AI agents now take actions that matter: they approve releases, issue refunds, send messages, change records. The record of what an agent did is a log on the operator's server, and after an incident that log is often the only evidence, held by the party with the most reason to change it. The operator, the agent itself, or whoever stole its credentials can delete a step, edit what a tool returned, or add a check that never ran.

I wanted the person who owns or pays for an agent to be able to ask one question, without opening a dashboard: "What did my agent do yesterday, and has its log been changed?" That question is asked at home or on the way to work, so voice fits it, and Alexa+ talks to services through MCP, so the log became an MCP server.

What it does

agentlog-mcp is a self-hosted MCP server (spec 2025-11-25, Streamable HTTP) with six tools:

  • log_action: an agent appends one step of its run (tool call, model call, error, end of run). Each step is hashed, signed with the agent's key and linked to the step before it.
  • audit_day: "what did my agent do yesterday?" Lists the day's runs in the user's time zone, verifies every run and returns a spoken answer that leads with the verdict.
  • verify_run: the verdict of one run (intact, open, broken) and the first step that cannot be trusted, with the reason: edited, deleted, forked, foreign_signer, bad_signature, relinked, after_seal.
  • list_runs, get_run: runs of an agent, and a run as an export bundle anyone can re-verify offline.
  • diff_versions: when a client and an operator disagree about what the agent did, checks each side's raw copy against what the agent signed and says, step by step, whose version is genuine.

audit_day and verify_run also return an MCP App view (ui://agentlog/audit-card.html): a card that shows the chain of steps and where it breaks.

Because Alexa+ developer tooling is not available to hackathon participants, the project includes a simulated Alexa+ experience: a web page that is a real MCP client (initialize, tools/list, tools/call, resources/read over Streamable HTTP), with voice in and voice out through the Web Speech API, and a panel that shows every JSON-RPC message and every MCP Apps postMessage.

In the demo, an attacker with write access to the SQLite file rewrites a failed health check (503) to 200 to hide why a release was blocked. The MCP server is not told. Asked again, it answers: "Warning: one log was tampered with. In the run at 1:05 PM, step 2 cannot be trusted: its content was edited after the agent signed it." The same check works on a run written to the public Arkiv testnet, which the operator cannot rewrite.

How we built it

  • TypeScript on Node.js 22.18+ (type stripping, no build step), the official @modelcontextprotocol/sdk (McpServer, StreamableHTTPServerTransport).
  • Each entry stores SHA-256 hashes of the canonical JSON of the call's input and output, the previous entry's hash, and an EIP-191 signature by the agent's key. The raw data stays on the server as private evidence. run.end seals a run, so a cut-off run shows as open, never as complete.
  • Storage behind one interface: SQLite (Node's built-in node:sqlite) by default, or readonly entities on the Arkiv network.
  • The verifier recomputes every hash, recovers every signature and follows the links from step 0. The spoken answer and the card are built from that result, never from a stored flag.
  • The web simulator implements the MCP client by hand (sessions, protocol header, SSE parsing) and a minimal MCP Apps host (sandboxed frame, CSP with no network access).
  • 66 automated tests, including end-to-end tests where the SDK's own MCP client talks Streamable HTTP to the server, before and after the SQLite file is tampered with. CI on Node 22.18 and 24.

How the work was done: I am a solo entrant. I set the goal, the scope and the acceptance criteria, and I reviewed and tested the result. The architecture, threat model, code and demo were produced by AI coding agents (Claude Code) working to those goals under my direction; every change was also reviewed by Google Jules, and the Jules-driven fixes are separate commits in the history. The hash-chain library underneath was written the same way on 9 October 2026 for my SiteLog project, also inside the submission period; everything in agentlog-mcp itself was written from 10 October 2026.

Challenges we ran into

  • There is no way for a participant to connect a self-hosted MCP server to a real Alexa+ device or developer console (the Alexa+ tools are preview, select partners only). We followed the simulated-experience path the FAQ allows and made the simulator a real MCP client, so the protocol on screen is the real one.
  • The MCP Apps server helpers (@modelcontextprotocol/ext-apps 2.x) target the v2 split MCP packages, while the server uses @modelcontextprotocol/sdk 1.x. We implemented the MCP Apps wire protocol directly instead.
  • MCP tool calls carry no user time zone, so "yesterday" depended on the server's clock. Every date-aware tool takes an optional IANA time zone; the simulator sends the browser's.
  • Making the spoken answer short and verdict-first while still naming the exact step and the kind of tampering.

Accomplishments that we're proud of

  • The answer about tampering comes from cryptographic verification, not from a flag stored next to the data: an attacker who edits, deletes or re-signs a step is caught, and the server says which step and how.
  • The dispute check: when the operator edits its own copy of the evidence and leaves the chain alone, the run still verifies as intact, and diff_versions still shows that the client's version is the one the agent signed.
  • One command (npm install && npm run demo) runs the whole demo locally, and a run written on the public Arkiv testnet can be verified from its RPC with no key.

What we learned

  • Voice needs the verdict first and the identifiers last: a hash read aloud helps nobody, a step number and a time do.
  • structuredContent next to a plain-text result fits voice well: the text is spoken, the structure feeds the card.
  • A tamper-evident log on a server the operator controls has a clear limit: whoever holds both the agent's key and the file can rewrite a whole run consistently. Writing to a network the operator cannot rewrite (Arkiv) closes that gap; the README states what each mode does and does not catch.

What's next for agentlog-mcp

  • Connect it to Alexa+ as soon as self-hosted MCP servers can be added, and test the card on Echo Show if MCP App views are supported there.
  • Hosted deployment with authentication, so an agent running elsewhere can log to it.
  • Log adapters for common agent frameworks, so agents record steps without calling log_action by hand.

Built With

Share this project:

Updates

Submission history