Inspiration

Across South Asia, Africa and Latin America, homes pump water from a ground sump into a rooftop tank, on power that comes and goes on a schedule. People guess when to run the pump. Guess wrong and the motor dry-runs and burns out, or the tank overflows onto the terrace. A voice assistant could manage this, but the moment an AI can switch on a real motor, "the model said so" is not good enough.

What it does

Jal is an Alexa+ add-on built as a self-hosted MCP server over Streamable HTTP. You can ask "do we have enough water for tomorrow morning?" or "should I run the pump?", and Jal answers from a deterministic forecast. It never starts anything on its own:

  1. The assistant proposes. propose_pump_run returns a plan and a signed one-time token. It does not start the pump.
  2. The human confirms. confirm_pump_run needs that token: HMAC-signed, 60-second TTL, single use, and rejected if the tank or sump changed since the proposal.
  3. The device enforces. The device twin checks its own invariants (tank full, sump empty, no power, run too long) on every command and every 1-second tick. It refuses unsafe starts with HTTP 409 even when the command skips the server, and auto-stops a running pump the moment the sump runs dry. Stops are always allowed.

A second device, a water heater, runs through the same guardrail with no heater-specific guardrail code: just a policy file and a twin device.

How we built it

  • Twin (FastAPI): physics simulation and invariants.
  • Guardrail (Python library): policy, tokens, rate limits, cooldowns and a SQLite audit log shared with the twin.
  • MCP server (FastMCP): 9 tools, every output validated against JSON Schemas.
  • Web dashboard (React, Vite): a real MCP client with browser speech, so judges can try the full flow without Alexa+.
  • Delivery: Caddy puts it all behind one port, and Docker Compose runs it with one command.
  • Tests: 90 tests, including an end-to-end test over the real Streamable HTTP transport.

No LLM computes any number or makes any safety decision.

Challenges

  • The Alexa+ CLI was gated for our account, so the add-on never ran inside Alexa+. We built a simulated Alexa+ experience in the web app instead and documented it in our friction log.
  • Getting the production build to route /mcp and the device API through one origin took a reverse proxy.
  • Making sure a schema check could never block an emergency stop meant validating only after the stop had happened.

What we learned

Safe physical actuation over MCP is an architecture problem, not a prompt problem. The model should only talk. Code should compute. The device should trust nobody. MCP would benefit from a standard "requires human confirmation" tool annotation, which is our top feature request.

Built With

Share this project:

Updates

Submission history