Housewarden
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Housewardenmark the electricity bill as paid"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Housewarden
A household-operations MCP server where every action that changes something is previewed, confirmed and audited. Built for Alexa+ and any MCP host that speaks Streamable HTTP.
Housewarden runs one household — bills, chores, shopping, reminders, budget, simulated smart-home devices and routines, members — behind 31 MCP tools. Reads are free. Every mutating tool goes through one guard: it produces a dry-run preview of exactly what will change, asks a person when the action is risky, executes exactly once, and appends to a hash-chained audit log. The web console uses the same path, so an assistant can never reach a weaker one than a person can.
Why this exists
A home assistant is about to be handed real actions: pay this bill, unlock the door, clear the shopping list. The missing piece is not the tools; it is the safety layer around them — show me what will change before it changes, ask me, and keep a tamper-evident record. Housewarden is that layer, shipped as a complete product rather than a demo: self-hosted, zero-setup, open source (MIT).
Related MCP server: expense-tracker-mcp-server
Demo video
Watch: https://youtu.be/3zZOKYgpXVw (YouTube, under three minutes, English captions burned in) — the same file is in the repo as demo/housewarden-demo.mp4. Shot list and every caption: demo/script.md. It was recorded with Playwright driving the real console and a real MCP client (demo/record.mjs); nothing in it is mocked.
Dashboard | Pending approval | Audit chain |
|
|
|
Quickstart — 90 seconds, nothing but Node 20+
git clone https://github.com/buildwithabid/housewarden
cd housewarden
npm install
npm run devThe first start:
writes
.env.localwith a randomHOUSEWARDEN_TOKEN(the bearer token MCP clients send) andHOUSEWARDEN_ADMIN_SECRET(the console login), and prints both once;creates an embedded Postgres (PGlite) in
.data/pgliteand applies the schema;asks
Load the demo household (Ali family)? (Y/n)— press Enter;starts Next.js on http://localhost:3000.
Then:
Open the console: http://localhost:3000 → sign in with the admin secret. The dashboard shows today's due items, the pending-approvals badge and "Chain intact". If you skipped step 3, press Load demo data.
Connect a client to
http://localhost:3000/api/mcpwith headerAuthorization: Bearer <HOUSEWARDEN_TOKEN>(see Connect Alexa+ or any MCP host).Watch it work without a host:
npm run demo:client -- --auto-approvenarrates the four-step demo in the terminal;npm run e2edrives the server with a real MCP client and prints a pass/fail table.
How the guard works
Every mutating tool accepts dry_run (preview only) and idempotency_key (safe retries). Its result is always one of executed, needs_confirmation or dry_run, and always includes the preview — a list of concrete change lines such as bill 'Electricity' 3,000 PKR due 2026-09-30: status overdue → paid.
sequenceDiagram
autonumber
participant P as Person
participant A as Alexa+ / MCP host
participant G as Housewarden guard
participant D as Household data + audit chain
participant C as Console /pending
P->>A: "Mark the electricity bill as paid"
A->>G: tools/call mark_bill_paid { bill: "Electricity" }
G->>D: plan (reads only) → preview of every change
G->>G: resolve policy → risk: confirm
G->>D: store pending action (expires in 10 min), audit "proposed"
G-->>A: needs_confirmation { action_id, preview, expires_at }
A-->>P: "Marking Electricity, 3,000 rupees, as paid needs your approval."
alt the person says yes
P->>A: "Yes"
A->>G: tools/call confirm_action { action_id }
else the person approves on a screen
P->>C: Approve (the card shows the same preview)
C->>G: confirm_action (console actor)
end
G->>D: atomic claim pending → confirmed, re-plan, compare preview
G->>D: execute once, audit "executed" (hash = sha256(prev_hash + row))
G-->>A: executed { result }
A-->>P: "Electricity is marked paid. The next one is due on 30 October."What the diagram does not show, but the code does:
Risk levels come from policies:
read(never guarded),low(executes immediately, audited),confirm(a person approves in the console or the assistant callsconfirm_actionafter the user says yes),high(only the console can approve). Defaults: adds and updates arelow; money-moving and destructive tools (mark_bill_paid,clear_shopping_list,run_routine,add_member, unlocking a lock) areconfirm;set_policyishigh, so an assistant can never lower the guard and approve its own change in one conversation. Per-member overrides exist (in the demo, a child unlocking the front door ishigh).Exactly once.
confirm_actionclaims the row atomically under an advisory lock; a second call returns the stored result withidempotent_replay: true. If the household changed between proposal and approval, the re-planned preview no longer matches and the action fails withSTALE_PREVIEWinstead of doing something the person did not see.Nothing hidden. Dry runs write nothing. Proposals, executions, rejections and expiries each append an audit row whose hash covers the previous row's hash;
verify_audit_chainrecomputes the whole chain and the console shows "Chain intact · N rows".No timers, no sessions. Expiry is swept on access; the pending action is the session, so the server stays stateless and any number of hosts can talk to it.
The tools
31 tools: 12 read, 17 mutating (all through the guard), 2 guard. Every tool has a title, a two-sentence description written for a voice assistant, a zod input schema, an output schema (SDK v2 structuredContent) and a spoken one-liner in content[0].text. Full shapes and examples are in docs/TOOLS.md.
# | Tool | Kind | Default risk | What it does |
1 |
| read | read | Lists the people in the household with their roles. |
2 |
| read | read | Gives a spoken-ready overview of what is due, overdue, waiting for approval and whether the audit log is intact. |
3 |
| read | read | Lists bills, unpaid ones by default, soonest first. |
4 |
| read | read | Reads one bill in detail. |
5 |
| read | read | Lists chores, open ones by default, with who they are assigned to. |
6 |
| read | read | Lists what is still to buy, grouped by category. |
7 |
| read | read | Lists upcoming reminders, soonest first. |
8 |
| read | read | Lists the smart-home devices with their current state, and the routines that can be run. |
9 |
| read | read | Summarises spending for a month by category, with the previous month for comparison. |
10 |
| read | read | Lists actions waiting for approval, with what each would change and when it expires. |
11 |
| read | read | Reads the tamper-evident audit log, newest first. |
12 |
| read | read | Recomputes every hash in the audit log and reports whether the chain is intact. |
13 |
| mutating | confirm | Adds a person to the household as an adult or a child. |
14 |
| mutating | low | Adds a bill with an amount and due date, optionally recurring. |
15 |
| mutating | low | Changes a bill's name, amount, currency, due date or recurrence. |
16 |
| mutating | confirm | Marks a bill as paid and, if it recurs, creates the next one. |
17 |
| mutating | low | Adds a chore, optionally assigned to someone and repeating. |
18 |
| mutating | low | Assigns a chore to a member, or unassigns it. |
19 |
| mutating | low | Marks a chore done and, if it repeats, schedules the next one. |
20 |
| mutating | low | Rotates every open, assigned chore to the next member in the household order. |
21 |
| mutating | low | Adds an item to the shopping list with a quantity and category. |
22 |
| mutating | low | Checks an item off the shopping list. |
23 |
| mutating | confirm | Removes checked-off items from the shopping list, or everything if asked. |
24 |
| mutating | low | Adds a reminder at a specific time, optionally for one member. |
25 |
| mutating | low | Cancels a scheduled reminder. |
26 |
| mutating | low | Records money spent in a category for the budget. |
27 |
| mutating | low (locks: confirm) | Changes a device's state, such as locking a door or setting a thermostat. |
28 |
| mutating | confirm | Runs a saved routine, applying each of its steps together. |
29 |
| mutating | high | Changes how much confirmation a tool needs, for everyone or for one member. |
30 |
| guard | — | Approves a waiting action so it runs exactly once. |
31 |
| guard | — | Declines a waiting action so it never runs. |
Mutating tools also accept dry_run: boolean, idempotency_key: string and member (who is asking — a name or id, used for per-member policies and the audit trail).
Connect Alexa+ or any MCP host
Housewarden is a self-hosted MCP server over Streamable HTTP, the transport Alexa+ integrations use. It serves the MCP 2025-11-25 revision (and earlier 2025 Streamable HTTP clients) and the 2026-07-28 revision natively, from one endpoint, with no sessions to manage.
Endpoint shape
POST https://<your-host>/api/mcp
Authorization: Bearer <HOUSEWARDEN_TOKEN>
Content-Type: application/json
Accept: application/json, text/event-streamThe token is the only credential. There is no OAuth flow to set up: paste the token from
.env.localwherever the host asks for an authorization header or bearer token.Browser-based hosts send an
Originheader; add that origin toHOUSEWARDEN_ALLOWED_ORIGINS(comma-separated full origins) or the request is refused with 403. Native and server-side hosts send noOriginand need nothing.GET /api/mcpanswers 405: serving is stateless, so there is no server-initiated stream to open.
Alexa+. In the Alexa+ developer configuration for a self-hosted MCP server, supply the endpoint URL (https://<your-host>/api/mcp) and the Authorization: Bearer <token> header. The server's instructions tell the assistant what to do with a needs_confirmation reply: read the spoken line, wait for an explicit yes, then call confirm_action; on no, call reject_action; never confirm without the user's yes; say so when an action can only be approved in the console. Tool descriptions are written to be spoken.
Any MCP host with a JSON config (Claude Code, Cursor, VS Code, Windsurf and others use this shape):
{
"mcpServers": {
"housewarden": {
"type": "http",
"url": "https://<your-host>/api/mcp",
"headers": {
"Authorization": "Bearer hw_…"
}
}
}
}Stdio-only hosts (Claude Desktop and similar) can bridge with mcp-remote:
{
"mcpServers": {
"housewarden": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://<your-host>/api/mcp", "--header", "Authorization: Bearer hw_…"]
}
}
}From a terminal, to see the raw protocol:
curl -s http://localhost:3000/api/mcp \
-H "Authorization: Bearer $HOUSEWARDEN_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_household_summary","arguments":{}}}'The console
The console is the human half of the guard, at the same origin as the MCP endpoint. /login takes the admin secret; / is the dashboard (due today, pending badge, chain status); /pending shows each waiting action as a confirmation card with the exact change lines and warnings and Approve / Reject buttons; /audit lists the chained log with a Verify chain button; /bills, /chores, /shopping, /reminders, /budget and /devices are plain CRUD views whose forms go through the same runTool path the assistant uses (a console "Mark paid" produces the same confirmation card); /settings shows the policy table, the token hint, the endpoint URL with a copy button and the allowed origins. It is server-rendered, works with JavaScript disabled, and is designed for a phone at night (docs/DESIGN.md).
Security model
Concern | What Housewarden does |
Endpoint authentication |
|
Never fall open | If |
Cross-origin abuse |
|
Dangerous actions | Risk policies with a floor: |
Exactly once | Atomic |
Stale approvals | The preview is re-computed at confirmation time and compared; a mismatch fails with |
Tamper evidence | Append-only |
Console session | HMAC-derived |
Secrets | Never logged, never rendered; |
Scripts
Command | What it does |
| Zero-setup dev server: secrets, migrations, demo-data prompt, then |
| Production build ( |
| Applies pending SQL migrations and prints the applied list. |
| Loads the demo household; refuses if one exists ( |
| Vitest unit and integration tests on an in-memory PGlite. |
|
|
| Starts a throwaway server on a free port, seeds it, and drives it with |
| Narrated terminal walkthrough of the four demo steps. |
| Drives the four-step storyline through the real console and a real MCP client with Playwright (26 assertions); without |
Configuration
All settings are environment variables; .env.example documents each. The ones you are likely to touch:
Variable | Default | Meaning |
| generated on first | Bearer token for |
| generated on first | Console login (≥ 8 chars) |
| (empty) | Comma-separated browser origins allowed to call the endpoint |
|
|
|
|
| How long a pending action waits for approval |
| derived from the request | Endpoint URL shown on |
|
| Set |
| on |
|
|
| Used when the demo household is created |
Self-hosting
Any host that runs Node 20 or newer will do; there is no other service to install.
npm ci
npm run build # next build, output: "standalone"
HOUSEWARDEN_TOKEN=… HOUSEWARDEN_ADMIN_SECRET=… HOUSEWARDEN_COOKIE_SECURE=1 \
HOUSEWARDEN_PUBLIC_URL=https://housewarden.example.com npm run startnpm run start serves a full checkout (Next prints a note that the standalone entry point is node .next/standalone/server.js; both work). For a minimal deployment copy .next/standalone — it already contains db/migrations and ui/pending.html — plus .next/static into .next/standalone/.next/static, and run node server.js there with the same environment.
Storage: the embedded PGlite database lives in
HOUSEWARDEN_DATA_DIRand needs one writable directory (back it up like any file). For a managed Postgres setDATABASE_URL(with?sslmode=requirewhen needed) andHOUSEWARDEN_DB=pg; migrations apply on first start either way.TLS: terminate HTTPS in front (Caddy, nginx, a platform's edge) and set
HOUSEWARDEN_COOKIE_SECURE=1. The endpoint must be reachable by the host you connect (for Alexa+, a public HTTPS URL).Origins: if the console and the endpoint are called from a browser-based host, add its origin to
HOUSEWARDEN_ALLOWED_ORIGINS.VPS install script:
deploy/install.shbuilds the app, applies migrations, registers asystemd --userservice on127.0.0.1:3124(with lingering, so it survives a reboot), and optionally starts a Caddy front for automatic TLS. Two things bite on a fresh VPS:HOUSEWARDEN_DATA_DIRmust be absolute in the service unit. Next's standaloneserver.jscallsprocess.chdir(__dirname), so a relative path resolves inside.next/standaloneand the service quietly opens a different database from the onenpm run seedwrote to (friction log F7).Ports 80 and 443 must be open inbound at the provider's network firewall, not just on the host. Let's Encrypt validates from outside; if the provider blocks the ports,
caddystill listens locally and answers on the machine's own IP, while ACME fails withTimeout during connect (likely firewall problem)for bothhttp-01andtls-alpn-01. Open them in the provider's control panel before starting the TLS front.If the provider filters those ports upstream anyway — both ACME challenge types time out and, tellingly, no connection is ever logged by the server — skip inbound entirely and publish through an outbound tunnel:
deploy/tunnel.servicerunscloudflared tunnel --url http://127.0.0.1:3124, which dials out and needs no open port. The account-less form assigns a hostname that changes on each restart; for a stable one create a named tunnel against a domain you control and usecloudflared tunnel run <name>.
Project layout
app/api/mcp/route.ts MCP endpoint: Origin check → bearer check → createMcpHandler (mcp-handler 2, SDK v2)
lib/tools/ one file per tool + registry.ts (31 tools, zod in/out schemas, spoken lines)
lib/guard/ the one write path: propose → plan → policy → execute | queue → confirm/reject/expire
lib/domain/ reads and mutation plans per entity (bills, chores, shopping, …)
lib/audit.ts hash-chained audit log + verifyAuditChain
lib/db/ Db interface with PGlite and pg adapters; db/migrations/*.sql
lib/contracts.ts shared DTOs, schemas, tool catalogue, canonical JSON
app/(console)/ the console (server components + server actions, Tailwind, no client data library)
scripts/ dev, migrate, seed, demo-client
demo/ stage.html + record.mjs (storyline check and video recorder), script.md, housewarden-demo.mp4
tests/ vitest suites (core, tools, console) and tests/e2e/protocol.e2e.ts
docs/ SPEC, TOOLS, DESIGN, FILE_OWNERSHIP, SUBMISSION, FRICTION_LOGDocumentation
docs/SPEC.md — entities, the guard state machine with exact JSON shapes, policies, idempotency, the audit chain with test vectors, auth, storage, the MCP surface, the console, scripts, the demo storyline.
docs/TOOLS.md — every tool's input, output, risk and an example call.
docs/DESIGN.md — the "Hearth" visual identity: palette, type, spacing, the three components, copy voice.
docs/SUBMISSION.md — the hackathon submission (Alexa+ track, Open Source mini challenge).
docs/FRICTION_LOG.md — what actually bit us building on mcp-handler 2, MCP SDK v2, PGlite and Next 16.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Household finance memory, budgets, transactions, and monthly reviews for AI assistants.
Household-aware cooking brain: pantry, meal suggestions, dietary safety, recipes, shopping lists.
AI life manager: tasks, home, health, wealth, childcare, pets & more — on your own data.
Household budgeting app with AI assistant: zero-based envelopes, accounts, transactions, reports.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI-powered household management including inventory tracking, restock predictions, meal planning from available ingredients, and baby supply monitoring through natural language commands.Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables users to manage personal finances using natural language, including tracking expenses, income, budgets, and generating financial summaries.-
- AlicenseNot gradedqualityBmaintenanceEnables voice-first household maintenance tracking, turning spoken updates into durable records, service history, and due-date reminders for a concise maintenance brief.MIT
- FlicenseNot gradedqualityCmaintenanceEnables families to manage shared expenses, income, budgets, and financial reports through natural language, with all data stored in PostgreSQL and exposed as MCP tools to compatible LLM clients.-


