Inspiration
Every house accumulates facts that no app owns. Which plumber fixed the water heater, what he charged, when the fridge warranty runs out, that the spare key is with the neighbour, that the dishwasher leak was quoted at $210 and never decided on. Those facts live in WhatsApp threads, memory, and a drawer of receipts — and they are needed at the worst possible moment: hands wet, phone across the room, someone standing at the door. That is exactly the Alexa+ moment: ambient, hands-free, conversational. None of that memory is reachable by a voice assistant today, because the assistant has nowhere to keep it and no reason to be trusted with it.
What it does
Attic is a self-hosted MCP server that gives Alexa+ a durable, queryable memory of the house. It exposes
nine voice-native tools over MCP 2025-11-25 / Streamable HTTP:
| Tool | What it is for |
|---|---|
recall |
One search across memories, service history, appliances and warranties, open problems, reminders. |
remember |
Save a fact ("the spare key is with Mrs. Chen"), deduplicated. |
log_service |
Record a repair or installation: vendor, cost, date, warranty terms. |
home_brief |
Proactive summary: reminders due, warranties expiring, appliances overdue, what is still broken. |
report_problem / mark_fixed |
Track a problem until it is actually fixed, with a resolution. |
remind / complete_reminder |
Maintenance reminders that outlive the conversation. |
forget |
Delete a memory by id or text — memory is only useful if it can be taken back. |
Plus one resource (attic://house) and one prompt (weekly_brief).
Answers are spoken-first: one or two sentences, grounded in retrieved dates, names and prices, never a hoarded id. Writes are only confirmed after a tool result comes back, so "saved" is a fact, not a hope.
The repository also contains the simulated Alexa+ experience used in the demo — a voice-first web client with the real JSON-RPC traffic streaming beside it, so a judge can watch the protocol instead of taking it on faith.
How we built it
One Node 22 process, one SQLite file, no native modules.
src/mcp.tsbuilds theMcpServerwith the official@modelcontextprotocol/sdk1.32.1 and registers the nine tools with zod input schemas, titles,readOnlyHint/destructiveHintannotations, and server instructions written for a speech-first client.src/index.tsmounts a statefulStreamableHTTPServerTransportat/mcp:initializecreates a session (Mcp-Session-Id),POSTcarries JSON-RPC,GETopens the server→client SSE stream,DELETEends the session. Bearer auth is enforced in front of the transport.src/db.tsis a small data layer overnode:sqlitewith FTS5. Search is hybrid: FTS5 with AND, then a relaxed OR pass, an alias map (fridge→refrigerator,ac→hvac) and cross-entity scoring, so "when does the fridge warranty expire" finds an appliance row while "the dishwasher leak" finds both the issue and the service history.src/agent.tsis the other half of the demo: a real MCP client that lists tools and runs a tool-use loop against an OpenAI-compatible model. It holds no house data — every fact in an answer arrives as a tool result.- The wire panel is
mcp-trace, a zero-dependency middleware that tees JSON-RPC in both directions and publishes the frames on an in-process bus. It was extracted into its own MIT package during the hackathon: https://github.com/Alvnvnc/mcp-trace (six tests). - Deployment is Caddy in front of the Node process on a $5 Lightsail box, HTTPS-only, with Let's Encrypt issuing over TLS-ALPN-01 because port 80 was already taken.
Challenges we ran into
- Streamable HTTP is SSE even for one request. The first
curllooked broken until theAccept: application/json, text/event-streamheader and theevent: message / data:framing were handled properly — which is also whymcp-traceparses both plain JSON and SSE frames. - One transport, one server. Sharing a single
McpServeracross sessions silently mixes state. The correct pattern is a new server and transport per session, keyed byMcp-Session-Id. - Writes are the hard part of a memory product, not reads. Early versions let the model say "saved" before the tool had returned. The fix was structural: the system prompt forbids confirming a write until a tool result exists, and the trace panel proves it in the demo.
- Certificates on a box with a busy port 80. Solved with a second Caddy container on host networking,
443 only,
auto_https disable_redirects, and TLS-ALPN-01. - Making tool names speakable.
open_issue/resolve_issueread badly in a conversation; they becamereport_problem/mark_fixed, which a voice client can route on far more reliably.
Accomplishments that we're proud of
- The demo is honest: the right-hand panel is the actual JSON-RPC, frame by frame, not a mockup. What the judge sees is what the server sent.
- The model cannot invent a price or a date. Every number on screen is traceable to a SQLite row, and the ledger tab shows those rows.
- A complete, self-hosted Alexa+ skill in one process and one file, deployable to the smallest VPS, with no vendor lock-in: any MCP-capable assistant can use it unchanged.
- The tracing piece was generalised and released:
mcp-traceis reusable by any Streamable HTTP MCP server, with tests.
What we learned
MCP itself is boring in the best way — the interesting engineering is in the shape of the tools. A voice assistant needs few tools, unambiguous names, one-call answers, and writes that are verifiable. Most of the work went into retrieval quality and into refusing to let the model speak before the data arrived, not into the protocol.
What's next for Attic
- A conformance harness against a real Alexa+ client, so "works with Alexa+" stops being a claim about a spec and becomes a test.
- Multi-house and multi-user scoping with per-user tokens, so a household can share one memory without sharing every memory.
- Photo and receipt capture (a photo of an invoice becomes a service record with a warranty date).
- Proactive briefs pushed on a schedule, not only when asked.
Try it
- Live experience: https://attic.54-254-226-82.sslip.io
- MCP endpoint:
POST https://attic.54-254-226-82.sslip.io/mcp(bearer token in the testing instructions) - Demo video: https://www.youtube.com/watch?v=0eQjCyVg3dI
- Source: https://github.com/Alvnvnc/attic (MIT)
Built With
- caddy
- css
- express.js
- html
- javascript
- json-rpc
- linux
- mcp
- node.js
- playwright
- sqlite
- typescript
- zod

Log in or sign up for Devpost to join the conversation.