-
-
Unrush: the assistant that speaks first, before your evening falls apart. Self-hosted MCP server + Amazon Bedrock + AgentCore Memory.
-
Before: a call at 5:30, study group at 7:30 (leave by 7:05), a 45-min curry. Unrush already predicts eggs are out and milk runs low.
-
A late meeting lands and Unrush speaks first, unprompted: leave by 7:05, the curry won't fit, try a 15-min swap. Live on Bedrock.
-
"Yes please": swap saved, order drafted with your usual products from past orders. For new items Unrush asks: "Which pesto?"
-
Explicit yes: one place_order(confirmed: true). Simulated order; each product links to its Amazon page so you add it to your cart.
-
MCP Apps: the same evening and order cards, served by the MCP server as ui:// views and rendered with the official AppBridge.
-
Reload and Unrush still remembers: state from the MCP server, conversation from Amazon Bedrock AgentCore Memory. Dark mode.
-
Self-hosted MCP server negotiating spec 2025-11-25 over Streamable HTTP. Every tool call timed; alerts fire as the calendar changes.
-
Architecture: browser ↔ Bedrock agent backend ↔ MCP server, plus Bedrock + AgentCore. Three locks: nothing is bought without your yes.
Inspiration
Busy evenings rarely collapse all at once. They collapse one small change at a time. A meeting runs late, so there's no time to cook the dinner you planned, and the eggs you'd fall back on ran out yesterday. Today's assistants wait to be asked, and by the time you think to ask, the evening is already gone.
We wanted an assistant that notices first and fixes things in the right order: get you out the door on time, then sort dinner, then groceries. It should never spend money without asking.
What it does
Unrush is a proactive household assistant, built as a simulated Alexa+ experience in the browser. It watches the calendar, the kitchen and the groceries.
- A late meeting lands. Your 5:30 call now runs to 7, on an evening you planned to cook.
- Unrush speaks first, without being asked: "Your 5:30 Project sync now runs to 7. To reach your 7:30 Study group you'll need to leave by 7:05."
- It fixes dinner. Tonight's 45-minute curry no longer fits the 40 free minutes, so it offers a 15-minute tomato & garlic spaghetti from what's in the pantry.
- It knows the kitchen. Eggs are out (you said so this morning). Milk runs out tomorrow, predicted from six weeks of purchases, with the reasoning shown.
- It orders only on a yes. It drafts the order with your usual products from past orders and asks which one for anything new ("Which pesto?"). It reads the order back and asks "Shall I place the order?" After an explicit yes it records a simulated order and gives you a link to each product on Amazon, where you add it to your cart and check out yourself. Unrush never pays.
- It remembers. Reload the page or restart the server and Unrush still knows everything.
An Agent activity panel shows every Amazon Bedrock call and every MCP tool call live, with inputs and results.
How we built it
- Self-hosted MCP server. MCP spec 2025-11-25 over Streamable HTTP (
POST/GET/DELETE /mcp, withMcp-Session-Idsessions), built with the official TypeScript SDK 1.32.1. It has 17 tools with zod input and output schemas, plus 2 resources. Household state lives in SQLite, so it survives sessions and restarts. - Proactive engine inside the MCP server. It runs every 60 s and immediately after any change, and detects three things: a squeezed departure, a dinner that no longer fits, and staples about to run out. Alerts are de-duplicated and resolve themselves when the problem goes away.
- Amazon Bedrock agent. The backend is an MCP client. It turns the MCP tool list into a Converse
toolConfigand runs a tool-use loop with Amazon Nova 2 Lite, capped at 8 model calls per turn. When an alert fires, the agent runs with a "speak first" instruction and streams to the browser over Server-Sent Events. - Amazon Bedrock AgentCore Memory. Every turn is stored as an AgentCore event per household and day, so a new session or a restarted backend picks up the conversation. A user-preference strategy extracts long-term household preferences, and relevant ones are recalled into the prompt.
- MCP Apps. The server ships two interactive
ui://views, the evening and the grocery order. Any MCP Apps host can render them, and our UI has a Cards ↔ MCP Apps toggle. - Agent Skill. An evening-rescue playbook in the open
SKILL.mdformat, loaded by the agent at runtime. - Web UI. React + Vite: push-to-talk voice, spoken replies, an animated alert banner, live cards, and light and dark mode.
The core logic is plain arithmetic. The leave-by time for an event is
$$ t_{\text{leave}} = t_{\text{start}} - d_{\text{travel}} - b_{\text{buffer}} $$
so for the study group: 7:30 − 20 min − 5 min = 7:05.
Run-out prediction uses each staple's purchase history. With total bought $Q$, on hand $q$, and $\Delta t$ days since the first purchase:
$$ r = \frac{Q - q}{\Delta t}, \qquad \text{days left} = \frac{q}{r} $$
For milk: $r \approx 0.51$ L/day with 0.6 L left, so it runs out tomorrow. Confidence comes from how regular the purchase intervals are (their coefficient of variation).
Consent by design: three independent locks.
- The MCP
place_ordertool refuses unlessconfirmed: true. - The backend blocks the call unless Unrush just asked "Shall I place the order?" and you said a clear yes.
- MCP App views may only call read-only tools.
The checkout is simulated, and no payment data exists anywhere in the system.
Challenges we ran into
- Proving the protocol version. The MCP SDK has no public getter for the negotiated version on the server, so we read it from the outgoing initialize result and log it for every session.
- Version lines. The latest MCP Apps package targets MCP SDK v2, and the Strands TypeScript SDK requires the v2 MCP client. We stayed on SDK 1.x as required, pinned
ext-apps1.7.5, and built the agent on Bedrock Converse plus AgentCore instead. - The first live Bedrock run found bugs our fakes had hidden. Nova emitted
<thinking>text that would have been read aloud. And because conversation history keeps only spoken text, the model lost the order id between turns and tried to place a freshly rebuilt order the user hadn't heard. We now strip reasoning, andplace_orderdefaults to the draft that was just read back. - Single-file MCP App views. The official view runtime ships only as ES modules, so we inline it into each view when the server starts.
What we learned
- For voice agents, design tools so follow-up turns don't depend on ids from earlier turns. "Yes" has to work on its own.
- Model choice matters even within one family. Nova 2 Lite chained five tool calls per turn and kept replies speakable; Nova Lite drifted into bullet lists.
- Show the agent's work. The live activity panel was our best debugging tool, and it's also how users learn to trust an assistant that acts first.
- Test against the real service early. 95 automated tests passed, yet the live run still surfaced two real bugs.
What's real vs simulated
- Real: the MCP server and tools, the Bedrock agent loop, AgentCore Memory, MCP Apps, the Agent Skill, the leave-by and run-out logic, and browser speech, and real Amazon product links for the Amazon-brand products it picks.
- Simulated, and labelled "Simulated" in the UI: calendar events, travel times, the checkout itself (fake confirmation number, no payment; the Amazon product links it gives you are real), and the six weeks of purchase history.
What's next
- Live on Alexa+. The Alexa+ MCP Toolkit requires an MCP server on spec 2025-11-25 over Streamable HTTP with MCP Apps support, which is exactly what Unrush's server is. Going live needs public hosting, OAuth 2.1 account linking and Private Preview access. Checkout then moves to Amazon Wallet, so Alexa+ handles payment and confirmation.
- Real Google Calendar and live travel times, plugged in behind the existing provider interfaces.
- Push alerts from the MCP server instead of polling.
- Restaurant and ride suggestions for nights when there's no time at all.
- Fitness and habit coaching.
Built With
- agent-skills
- amazon-bedrock
- amazon-bedrock-agentcore
- amazon-nova
- amazon-web-services
- aws-sdk
- better-sqlite3
- css3
- express.js
- github
- html5
- json-schema
- mcp
- mcp-apps
- model-context-protocol
- node.js
- npm
- react
- server-sent-events
- sqlite
- typescript
- vite
- web-speech-api
Log in or sign up for Devpost to join the conversation.