Inspiration

I wanted to build an AI tool my whole family would use together, every day. Something that connects every person in the household to one living memory and brings the family closer.

Every home has one person who knows everything. The furnace filter size. The plumber who charges fairly. Where the water shutoff is. And, for the 53 million Americans caring for someone they love, who is taking Mom to cardiology on Thursday.

When that person is busy, traveling, or gone, the household goes blind. Household knowledge leaks away because capture friction kills every tool built for it. The moment passes before anyone opens an app in the basement to type "check the anode rod in three years."

Caregiver figure: National Alliance for Caregiving and AARP, "Caregiving in the U.S. 2020" (53.0 million adults, May 2020).

What it does

Attic is a living memory for one home, drawn as a cutaway house at dusk. Every lamp is one thing the house knows, glowing in the room it belongs to. A house is a private link you hand to your family. Everyone enters with the link alone. The people your family looks after live there too. The care circle holds Mom's appointments, her meds and refills, the rides still waiting to be claimed, and a journal siblings write to each other.

Every family member's AI agent can read and write all of it through 17 WebMCP tools the house page publishes itself. Anyone in the house sees each change land as it happens, with a receipt they can press Undo on.

How we built it

The house is one hand-drawn SVG cutaway in React and Vite. Rooms, lamps, people, and the cat all sit on the same layout model, so a new memory knows which room it belongs in.

Behind it is a Cloudflare Worker with one Durable Object per house. The object owns the state, applies every change as an op, stores the inverse op alongside it, keeps a 200-entry receipt log, and broadcasts to everyone connected over WebSockets.

Every tool travels the same op channel as the buttons on the page. An agent's write lights a lamp in the right room on everybody's screen and leaves a receipt any family member can undo.

Challenges we ran into

Undo that survives other people. Working out how to reverse a change after the fact is guesswork. So every op stores its own inverse at the moment it is applied. Undo is a tool too. An agent can take back its own mistake by receipt id, and your sister can undo what your agent did from her phone in another state.

Cloudflare answered before the Worker did. not_found_handling: "single-page-application" was serving index.html for API paths because the asset router sees navigations first. /api/* has to be named explicitly in run_worker_first.

Making an agent's work legible. An agent quietly editing your family's records is unsettling. Every change lights the room it belongs to, writes a receipt with a name and a time, and stays undoable by anyone in the house.

Accomplishments that we're proud of

*An AI tool that connect people and agents, in two way network *

A test suite that drives every tool and guards the spec. tests/webmcp-tools.test.mjs polyfills document.modelContext and calls all 17 house tools, both landing tools, and all three declarative forms. It also asserts that every annotation key is a member WebMCP defines. An invented hint fails the build.

A two-browser test that proves the whole claim. One browser drives an agent, the other is a family member's screen. The suite watches the change cross the wire and watches the other person undo it.

A demo a judge can run in any browser. The Agent tab runs the real execute() functions behind a button, so the entire tool surface is testable today, including on a phone.

What we learned

WebMCP changes what a page is for. The web was built for eyes and a pointer. Software reaching it has always worked from the outside: scrapers, separate servers, issued keys. WebMCP turns that around. The page itself offers what it can do, inside the user's own browser session, behind the security and permissions the site already enforces. The site stays in charge of its own rules. One codebase serves the person and the agent at once, with the agent surface designed in from the first line. I believe this is where web development goes: sites built for two audiences, with the second one treated as first class.

Build the tool surface as a peer of the UI. Every tool goes through the same op channel as the buttons on the page. remember does what the add-memory panel does. claim_care_task does what the Claim button does. Once that was true, the design questions answered themselves: if a family member can do it, an agent can do it, and everyone in the house watches it happen.

Tool names and descriptions are the interface. A model reads whats_coming_up, search_house_memory, claim_care_task, and undo_last_action the way a person reads menu labels. The names that work are verbs a family already says out loud. whos_here earns its place because an agent should know who else is in the house before it acts on their behalf. Returning both a receipt id and a record id from every write is what makes chained flows work: search, claim by id, then journal about it.

The annotations are a vocabulary, and it rewards reading the dictionary. WebMCP defines three hints: readOnlyHint, untrustedContentHint, and consequentialHint. destructiveHint and idempotentHint belong to MCP's separate server-side set. A conformant browser keeps the members WebMCP defines and silently discards the rest. Attic declares readOnlyHint on all 17 tools and sets it true on the seven that only read. untrustedContentHint goes on the twelve whose output can carry text another family member wrote. consequentialHint goes on the two an agent should confirm first. Attic ships the three WebMCP defines.

Check the annotations in a browser, beyond the spec alone. I registered a probe tool in Chrome 152 under the origin trial with six annotation keys and read it back with document.modelContext.getTools(). Two survive today: readOnlyHint and untrustedContentHint. consequentialHint appears in the published dictionary but remains unimplemented, so it is dropped in conversion. Attic keeps it anyway. It is the correct member, and it starts working the day Chrome ships it. The same caution sits in the descriptions of forget and add_medication, which is the channel a model reads right now. That check takes five minutes and belongs in any WebMCP project.

What's next for Attic

I want Attic to become a real product. This submission is a hackathon build. The problem behind it is a solution, and it is the one I want to work on.

The next step is putting OpenAI's newest models behind the house. An agent that holds a whole household in view can surface the refill that slipped and the appointment two siblings both booked. It can catch the pattern in a care journal that shows up only across months.

Mostly I want Attic to be the answer when someone asks what these tools are actually for. Keeping a family close through a hard year is a real use for AI, and it is the one I care about.


1. Why this use case is a strong fit for WebMCP

The thing that kills household memory is capture friction. An agent is the only thing that removes it.

You say "gutters cleaned by ClearFlow, about $180" in passing to the agent you are already talking to. remember files it, dated, in the yard, with a reminder for next autumn. The knowledge gets captured at the moment it exists, which is the only moment it is ever free.

Retrieval is just as agent-shaped. A year later you are in a hardware store and ask "what size filter does the furnace take?" Your sister, in another state, asks her agent "who is covering Mom this week?" Both of you want the answer where you already are, in the conversation you are in.

A household memory needs structured tools. The data is small, highly structured, deeply personal, and it changes constantly from several directions at once. Attic hands agents 17 imperative tools registered with document.modelContext.registerTool inside a house, and 2 more on the landing page so an agent can create or open one for you. All use JSON Schema inputs and annotations from the WebMCP ToolAnnotations dictionary, plus 3 declarative <form toolname> tools.

2. How it creates a better user experience

Handing an agent write access to a family's shared memory is only tolerable if the family can see and reverse what it did.

  • Every mutating tool call lands on the page as a receipt: who did it, through which tool, in plain language, with an Undo button any family member can press.
  • The Durable Object stores an inverse op with every change, so undo is exact. Undo is a tool too (undo_last_action), so an agent can take back its own mistake by receipt id.
  • Annotations use the WebMCP ToolAnnotations vocabulary. readOnlyHint is declared on all 17 tools and true on the seven read-only ones. untrustedContentHint goes on the twelve whose output can carry text another family member wrote. consequentialHint goes on the two that deserve a pause. forget removes something the family may keep in this one place. add_medication is health information someone will act on. destructiveHint and idempotentHint belong to MCP's server-side set; a conformant browser keeps the members it defines and silently discards the rest. Attic ships the three WebMCP defines.
  • Checked in a browser, beyond the spec alone. A probe tool registered in Chrome 152 with six annotation keys comes back carrying two. consequentialHint appears in the published dictionary but remains unimplemented. The same caution sits in the descriptions of forget and add_medication, which is the channel a model reads today.
  • Tools travel the same op channel as the buttons on the page. The server validates, persists, and broadcasts one human-readable cause. That cause drives the receipt, the lamp in the room, and the presence chips. An agent's change is visible within a frame, to everyone connected.

An agent reads as a guest with a key.

3. What people and agents can do together that was difficult or impossible before

A whole family and their agents, working the same live page at the same time.

Marcus is in Denver. Dana is at the house. Mom's Metoprolol needs picking up this week. Marcus tells his agent "I can do the refill, claim it for me." It calls care_circle, then whats_coming_up, finds the refill unclaimed, and calls claim_care_task.

In Dana's kitchen the errand flips to "Marcus has it" while she is looking at it, and his name appears on the hook rail. The page carried it. She adds a line to the journal from her phone, and Marcus's agent reads it on his next question. If she thinks he took the wrong day, she presses Undo, and his agent's next whats_coming_up shows the errand open again.

Four parties working one document: two people and one agent each. A person can undo an agent. An agent can undo a person. Everyone sees the same house within a frame. whos_here lets an agent check who else is in the house and whose agent has been acting, so it reasons about the family as a whole.

That is the new part. An agent becomes another pair of hands the family can supervise.

53 million Americans are coordinating someone's care right now, mostly in group texts that scroll away by Thursday. The pharmacy run, the cardiology appointment, the dose that changed, the sibling who missed the message. This is the version of that I want running in my own family this week.

4. Implementation notes

Frontend. React 18 and Vite. One screen: an SVG cutaway house on the left, a rail on the right (Rooms / Family / This week / Agent). Mobile-first below 900px, so it works in ChatGPT's in-app browser. The house is plain SVG, so it paints instantly and stays legible on a phone.

Backend. A Cloudflare Worker with one Durable Object per house. The DO holds an op reducer, an inverse op for every change, a 200-entry receipt log, presence, and WebSocket broadcast with hibernation so idle houses cost zero.

Sharing model. Every family member opens the same URL, and so does every agent they bring. A house is addressed by a slug with about 41 bits of CSPRNG entropy from crypto.getRandomValues, unlisted and unindexed. You share access the way you share a spare key: send the link and they are in, on any device, ready the moment it opens. Anyone holding the link is family. That is the trust model of a physical house key, and it is the one families already reason about. A password layer is a straightforward addition for households that want one.

The WebMCP layer. web/src/webmcp.js. All tools register at page mount through an AbortController, so they are live before any asset finishes loading and unregister cleanly on navigation. execute returns MCP-shaped { content: [{ type: 'text', ... }] }. Every write returns a receipt id and a record id, which is what makes chained agent flows work: search, then claim by id, then journal about it.

For judges testing outside a WebMCP browser. The Agent tab has a Run a simulated agent button. It calls the real execute() functions, labeled in its own color, and everything it does is undoable. The same tab shows the literal registerTool call the house makes.

Tests. Three suites, all runnable against the deployed instance. First, a raw WebSocket protocol test against the Durable Object. Second, a Playwright test that polyfills document.modelContext and exercises all 17 house tools, both landing tools, and all three declarative forms the way an agent-capable browser would. It includes a conformance guard that fails the build if any tool carries an annotation key outside the WebMCP ToolAnnotations dictionary. Third, a two-browser test that proves live human-to-agent-to-human sync and cross- user undo.

Try it

Open the live URL, click Walk through the Hensley House, come in as Dana, and ask your agent: "what needs doing this week? I can take Mom to cardiology."

Built With

Share this project:

Updates

Submission history