-
-
The final finding stays beside its cited excerpt, ready for human review, source checking, and Markdown export.
-
A scoped question becomes live coverage across public archives, with Arquivo.pt selected for comparison.
-
The Evidence Room connects four WebMCP tools to one caseboard that the agent and the person can inspect together.
-
One selected window becomes a bounded diff with both source captures and an explicit untrusted text warning.
-
Index records produce six exact capture windows before any archived page body is downloaded.
Why I built it
Web archives contain real evidence, but working with them still feels like manual archaeology. Find snapshots, open a pile of tabs, compare dates, copy URLs, then try to remember which version actually proved the point. I wanted to ask a browser agent a sharper question: "How did this page change, and can you show me the exact captures that prove it?"
This project also has some history. @agntn/archives started in April 2025 as one TypeScript interface over several web archives. It gradually gained caching, lazy provider loading, typed metadata and more sources. In 2026 it grew into a proper agent tool: first native OMP and Pi extensions, then an MCP server, archived body reads, pagination, capture diffs and finally a Nuxt explorer running on Cloudflare Workers.
The WebMCP Challenge was a good reason to build the missing piece. Not another chat box, and not four aliases for buttons. I wanted the page itself to become a shared investigation room for a person and an agent.
What it does
Archive Evidence Room registers four native WebMCP tools through document.modelContext:
scope_archive_casedefines one historical question and checks which archives have evidence.find_change_windowsfinds consecutive captures without downloading archived bodies.inspect_archive_changereads one selected pair and returns a short cited diff.pin_archive_findingrecords whether that diff supports, contradicts or only adds context to the question.
Every call updates the same visible caseboard. The agent can do the repetitive archive work, but the person still sees the dates, original URL, provider, underlying Memento archive, diff and final interpretation. No invisible research session and no uncited answer at the end.
WebMCP is progressive enhancement here. Without the experimental browser API, the full workflow still works by hand.
How I built it
The UI is Nuxt 4, Vue and Docus. The server runs on Cloudflare Workers. I used the existing cached /api/coverage, /api/snapshots and /api/diff routes instead of creating a second archive backend for the hackathon. Those routes call the same @agntn/archives executors already used by MCP, OMP and Pi.
Discovery is index first. The room requests between 3 and 12 capture records, groups them by exact URL and provider, keeps Memento captures inside the same underlying archive, then ranks useful windows. Archived bodies are fetched only after someone chooses a window to inspect. The result is much faster and much kinder to public archive infrastructure than reading everything up front.
The caseboard keeps provenance all the way through. A diff can resolve to captures slightly different from the index rows, so the final citation comes from the diff result, not stale listing metadata. Findings store the interpretation beside the evidence instead of mixing both into one generated paragraph.
What was hard
Public web archives disagree about almost everything: timestamp formats, URL normalization, replay endpoints, metadata and failure behavior. Even www, default ports or letter case in a path can quietly produce the wrong pair. Memento adds another trap because one provider can return captures from several underlying archives. A plausible diff between unrelated records would be worse than no result, so I made the pairing rules deliberately strict.
Cancellation was more subtle. Browser abort signals had to travel through $fetch, Nitro, cache misses and the archive executor. Sharing one cached promise also shared one caller's cancellation with another caller. That was wrong. Each cache miss now owns its request and one closed tab cannot kill another investigation.
The other problem is trust. Archived HTML can contain instructions written specifically to manipulate an agent. Treating that as normal tool output would be ridiculous. The room exposes only a bounded text excerpt, marks it as untrusted, renders it as escaped text and keeps it separate from the finding written by the agent.
What I learned
The useful WebMCP abstraction is not "let the agent click my UI." It is a small protocol with state the user can inspect. caseId and changeId make the steps explicit, while the shared board makes mistakes visible.
I also learned that archive research needs honest negative results. No capture in one bounded query does not mean a page never existed. A partial diff cannot prove text was absent outside the compared prefix. The product gets better when those limits stay visible instead of being polished into confidence.
For the final smoke test I used sive.rs: seven captures became six safe windows, one exact archived diff and a finding pinned with both capture URLs. The public page does not preload this result because the caseboard belongs to the current browser session. Open the Evidence Room and ask the browser agent to investigate how sive.rs changed between 2020 and 2022 to reproduce the flow.
Built With
- cloudflare
- docus
- nitro
- nuxt
- vitest
- vue
- webmcp
Log in or sign up for Devpost to join the conversation.