Inspiration

This started with my own tax return. Most of it was prefilled, but my foreign shares and crypto weren't - so I was the one who had to get all of it in. That meant logging into each broker, exporting my holdings (every platform in its own format), and then typing each position in by hand. It's tedious, easy to get wrong, and it's the same job every year.

The hard part was never the tax treatment. It was moving structured facts out of a pile of exports and into one draft I could actually review, without losing track of where each number came from or which ones the paperwork couldn't answer. That's the gap ReturnReady goes after.

ReturnReady is a small WebMCP experiment: I attach synthetic evidence to Codex, Codex pulls the structured facts out (outside the page), and the app exposes a few narrow tools for recording and checking those facts. I still review everything and fill in anything the evidence can't prove.

What it does

ReturnReady opens on a sparse FY2025–26 draft with a bit of prefilled PAYG context. From there you can add deductions and disposals yourself, or ask Codex to do it through WebMCP.

The demo walks through:

  • 40 hours of work-from-home, at the prototype's fixed rate, giving a visible $28 deduction
  • MSFT and AAPL foreign-share disposals
  • a BTC disposal with the transaction fee left out on purpose

The evidence doesn't contain AAPL's acquisition details, so validation raises a blocker instead of making the numbers up. You supply those facts yourself as a user attestation, which stays visibly separate from anything backed by a document. Once the blocker is cleared, ReturnReady builds a review pack, keeping the unresolved BTC warning and logging every action along the way.

One thing worth being clear about: ReturnReady organizes evidence. It doesn't lodge returns, give tax advice, work out the authoritative tax, or claim your return is complete. The gains and losses are amounts I worked out myself and entered; the app records and checks them, it doesn't calculate them.

Why WebMCP

Normal browser automation has to read the DOM, guess what each control does, and poke at fields from the outside. ReturnReady skips all of that. It exposes six tools with tight JSON Schemas:

  • get_return_draft
  • record_deductions
  • record_disposals
  • record_acquisition_details
  • validate_review_pack
  • generate_review_pack

Both the agent and the manual UI go through the same controller and the same domain logic. So WebMCP speeds up data entry without getting around validation, provenance, idempotency, or the audit trail and if WebMCP isn't available, the manual workflow still works on its own.

How I built it

ReturnReady is a static React app in strict TypeScript, built with Vite, no backend. It registers its tools imperatively with document.modelContext.registerTool().

Every tool checks its input against an allow-list at the schema boundary, then checks it again inside the handler. The page never sees the attached files or the raw document text. No tool takes a file path, a URL, a selector, executable content, or arbitrary JavaScript. All the bundled evidence and values are synthetic.

For tests, Vitest and Testing Library cover the domain rules, the security boundaries, tool annotations, bounded outputs, idempotency, and making sure a human and the agent get the same result. Playwright runs the whole manual workflow end to end for accessibility.

Challenges I ran into

The main one was keeping a single trustworthy workflow across two ways in. Early on, validation triggered by the agent could look different from validation triggered by a human. I fixed it by deriving the modal and the review pack from shared controller state, and added a regression test that runs the real WebMCP handler against the rendered UI.

The other challenge was one I felt as a builder: the page deliberately never touches the raw files. Part of me wanted to just let the app accept an upload and parse it, that's the obvious and easy path. But that's exactly the boundary that makes this trustworthy, so keeping all the file handling outside the page stayed non-negotiable, even when it made the build feel more restrictive than it had to be.

I also kept the scope tight on purpose. ReturnReady shows the recorded facts and a fixed-rate deduction result, but it doesn't try to calculate capital gains or guess at missing acquisition data.

Accomplishments that I am proud of

  • 6 small WebMCP tools instead of handing over the whole browser
  • one shared domain layer behind both the manual and agent paths
  • provenance that clearly separates documentary evidence from user attestation
  • invalid or conflicting calls get rejected cleanly, with no change to state
  • repeat calls are idempotent, they don't pile up duplicate records
  • a review pack that carries unresolved warnings through instead of hiding them
  • a fully synthetic demo anyone can reproduce

What I learned

WebMCP earns its keep when it exposes what things mean, not when it turns every button into a tool. A small, semantic surface lets the agent move fast while the app keeps hold of the parts that matter: validation, state changes, and deciding what the person actually needs to review.

What's next for ReturnReady

More evidence categories, better review exports for an accountant, and a few real calculation methods so the amounts don't all have to be worked out by hand first, all while keeping raw-file interpretation outside the page and the same trust boundary intact.

Built With

Share this project:

Updates

Submission history