Skip to content

Migrate @relayburn/mcp tool handlers to archive queries #97

@willwashburn

Description

@willwashburn

Context

The MCP server's two tool handlers — currentBlock and sessionCost — both call queryAll() from @relayburn/ledger (packages/mcp/src/tools/current-block.ts:6,47, packages/mcp/src/tools/session-cost.ts:3,28). Every in-session self-query from a running agent therefore re-walks the entire ledger and re-folds stamps. The MCP path is explicitly the place where latency matters most — the agent is paying per-token to wait for the answer.

PR #78 explicitly defers this rewire:

Rewiring burn summary / compare / plans / @relayburn/mcp to read from the archive (each command is a self-contained migration that keeps the in-memory fallback intact).

Issue #40 calls this out as a primary motivation for the archive:

@relayburn/mcp (#26) wants low-latency self-query from inside a running agent.

The MCP tools accept a queryTurns dependency injection in their Deps types already (current-block.ts:35-40, session-cost.ts:21-25), so the rewire surface is small.

Proposal

  1. Add a queryTurnsFromArchive(query) helper in @relayburn/ledger that prepares a parameterized SQL SELECT against the archive's turns table and returns the same EnrichedTurn[] shape callers already consume. The archive already carries workflow_id / agent_id / persona / tier plus the JSON enrichment blob, so the result shape can be reconstructed without folding.
  2. Default currentBlock's queryTurns and sessionCost's queryTurns to the archive-backed helper.
  3. Run buildArchive() (incremental tail apply) at MCP server startup so the first tool call doesn't pay the cold cost. Optionally re-run on a low-frequency interval, or on-demand before each call if the ledger has grown — measure first.
  4. Fallback path: if the archive open or query throws, log via onLog and fall through to queryAll(). The MCP server must never fail a tool call because the archive is unavailable.

Tests:

  • Existing MCP unit tests pass with the archive-backed helper injected via Deps.
  • New end-to-end test: spin up the MCP server against a fixture archive + ledger, call both tools, assert results match the ledger-backed equivalents.
  • Fallback path: archive missing/corrupt -> tools still succeed via queryAll.
  • Cold-start path: first MCP call after a new ledger tail applies the tail incrementally before responding.

Acceptance criteria

  • burn__currentBlock and burn__sessionCost issue SQL against archive.sqlite on the hot path, not full ledger walks.
  • Tool responses are equivalent (within float-rounding tolerance for cost) to the pre-migration implementation.
  • Server startup includes an incremental archive build; subsequent tool calls do not re-walk the ledger.
  • Archive failure paths fall back transparently to queryAll().
  • Latency: tool-call P50 on a 100k-turn ledger is at least 10x faster than the current implementation.

Out of scope

  • New MCP tools or new tool inputs.
  • Schema additions to the archive.
  • The CLI summary/compare/plans rewires.

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions