PantryPilot MCP
README.md
# PantryPilot MCP
Greenfield **TypeScript** [Model Context Protocol](https://modelcontextprotocol.io) server for the **Amazon Developer Hackathon — Alexa+ track**.
PantryPilot is a persistent kitchen-operations agent: pantry state, dietary preferences, meal planning, shopping gaps, product discovery, and a **mock/reversible cart** over **MCP 2025-11-25 Streamable HTTP**. One tool (`kitchen_run`) orchestrates the full loop against durable SQLite household memory and structured media cards.
**Safety:** cart draft/confirm never places a real Amazon order or moves money.
| | |
|---|---|
| **Devpost** | https://devpost.com/software/pantrypilot-sytrm1 |
| **Demo video** | https://www.youtube.com/watch?v=U24ZL9LqIsw |
| **Repo** | https://github.com/burbanodev-lab/pantrypilot-mcp |
| **Status** | Devpost **SUBMITTED** (2026-09-11) · primary track **Alexa+** · mini-challenges **AWS Builder** + **Open Source** |
AWS credentials are **optional**. Without `AWS_REGION` + `BEDROCK_MODEL_ID`, `meal_plan` uses a deterministic stub so local demos and Docker work offline. Live Bedrock (`source: bedrock`) is an optional enhancement, not required to judge.
## Judge Quick Start
```bash
git clone https://github.com/burbanodev-lab/pantrypilot-mcp.git
cd pantrypilot-mcp
npm ci
npm run verify-submission
npm start
```
Then open `http://127.0.0.1:3000/companion/` → **Stock sample pantry** → **Run weekly kitchen**.
One-pager for reviewers: [`JUDGES.md`](./JUDGES.md) · full narrative: [`SUBMISSION.md`](./SUBMISSION.md) · failure modes: [`FAILURE_MODES.md`](./FAILURE_MODES.md)
Aggregate check `verify-submission` runs build, submission audit, Alexa add-on check, raw MCP conformance, smoke, judge-check, and evals. No AWS credentials required.
### Docker (optional)
```bash
docker compose up --build
# Health: http://127.0.0.1:3000/health
# Companion: http://127.0.0.1:3000/companion/
```
Hosted MCP at https://pantrypilot.mcpize.run — `/health` is public; `/mcp` returns **401 Bearer token required** (MCPize gateway). Prefer video + local companion for judging; do not treat the gated `/mcp` URL as the main live demo.
## Architecture
```
Alexa+ / MCP client
│ POST /mcp (Streamable HTTP, JSON responses)
▼
┌───────────────────────────────┐
│ Express (createMcpExpressApp)│
│ StreamableHTTPServerTransport│ ← @modelcontextprotocol/sdk
│ McpServer + tools │
└───────────────┬───────────────┘
│
┌───────┴────────┐
▼ ▼
SQLite household Optional Amazon Bedrock
store (DATABASE_PATH; (Converse via
+ memory cache) @aws-sdk/client-bedrock-runtime)
│ │
▼ ▼
Mock product catalog Structured meal slots
(ASIN + mediaCard) + mediaCard payloads
```
| Layer | Role |
|-------|------|
| `src/server.ts` | Entry: Streamable HTTP, session map, `/mcp` + `/health` + `/companion/` |
| `src/tools.ts` | MCP tools (incl. `kitchen_run`) — count from live `tools/list` |
| `apps/companion/` | Minimal web companion (HTML/JS) calling `kitchen_run` + rendering `mediaCard`s |
| `evals/` | Scripted happy-path + soft-failure eval (`npm run eval`) |
| `src/mcp-extras.ts` | MCP resources (`pantry://…`) + prompts (`use_up_expiring`, `weekly_kitchen`) |
| `src/state.ts` / `src/db.ts` | Household pantry / prefs / plan / cart + SQLite durability + `MediaCard` types |
| `src/meals.ts` | Deterministic meal-plan stub + slot enrichment |
| `src/bedrock.ts` | Optional Bedrock Converse meal_plan path |
| `src/catalog.ts` | Deterministic mock catalog + `mediaCard` helpers |
| `scripts/mcp-smoke.ts` | Asserts protocol `2025-11-25` + non-empty `tools/list` |
### Tools
| Tool | Purpose |
|------|---------|
| `pantry_upsert` | Add/update pantry items |
| `pantry_query` | List/filter pantry |
| `prefs_set` / `prefs_get` | Dietary preferences |
| `meal_plan` | Bedrock (if configured) or deterministic multi-day plan; structured slots + `mediaCard` |
| `shop_list_build` | Shortfalls vs pantry |
| `product_search` | Mock catalog cards (asin, image, price, URL) + `mediaCard` |
| `cart_draft` / `cart_confirm` | Mock cart (no Amazon order); lines carry `mediaCard` |
| `session_recall` | Session/household context snapshot |
| `kitchen_run` | Agent loop: pantry → meal_plan → shop → product_search → cart_draft + step log |
Exact tool count is whatever `tools/list` returns (currently **11** including `kitchen_run`); smoke/conformance assert required names rather than a frozen integer.
### Structured meal + media cards
Meal slots include `description`, `tags`, `estimatedMinutes`, `ingredients`, and an Alexa-oriented `mediaCard` (`title`, `subtitle`, `text`, `imageUrl`, `detailPageUrl`). Product search and cart lines expose the same `mediaCard` shape so companion UIs can render consistently.
### Bedrock meal_plan (optional)
When **both** are set:
- `AWS_REGION`
- `BEDROCK_MODEL_ID`
…plus standard AWS credentials (`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN`, shared config, or IAM role), `meal_plan` calls Bedrock **Converse** and expects a JSON array of meal objects. On missing config or invoke/parse failure, the server falls back to the stub and reports `source: "stub"` (and `bedrockError` when applicable).
## Requirements
- **Node.js 20+**
- npm 9+
## Setup
```bash
cd pantrypilot-mcp
cp .env.example .env # optional; add Bedrock vars only if you have access
npm ci
npm run build
```
## Run
```bash
npm start
# → http://127.0.0.1:3000/mcp
# Health: http://127.0.0.1:3000/health
```
Environment (see `.env.example`):
- `PORT` (default `3000`)
- `HOST` (default `127.0.0.1`; use `0.0.0.0` in Docker)
- `ALLOWED_HOSTS` — comma-separated Host allow-list when not on plain localhost
- `AWS_REGION` + `BEDROCK_MODEL_ID` — enable Bedrock meal plans
- Standard AWS credential env vars (never commit real values)
### Docker
```bash
# Stub path (default — no AWS needed)
docker compose up --build
# Optional Bedrock (credentials from your shell / secret store)
export AWS_REGION=us-east-1
export BEDROCK_MODEL_ID=amazon.nova-lite-v1:0
# export AWS_ACCESS_KEY_ID=...
# export AWS_SECRET_ACCESS_KEY=...
docker compose up --build
```
Compose forwards `AWS_*` / `BEDROCK_MODEL_ID` from the host environment; the image itself does not bake secrets.
## Smoke test
After `npm ci`, the smoke script **starts an ephemeral server**, runs MCP `initialize` + `tools/list`, then exits:
```bash
npm run smoke
```
Expected output includes:
- `OK initialize protocolVersion=2025-11-25`
- `OK tools/list count=<N>` (non-empty; required tools present)
- `SMOKE PASSED`
Against an already-running server you can also point a custom client at `http://127.0.0.1:3000/mcp` using `@modelcontextprotocol/sdk` `Client` + `StreamableHTTPClientTransport`.
## Companion UI + evals
```bash
npm start
# open http://127.0.0.1:3000/companion/
# Stock sample pantry → Run weekly kitchen → media cards
npm run eval
# PASS happy_path_pantry_meal_cart
# PASS failure_cart_confirm_without_draft
# (+ allergen / budget gate evals)
```
See [`FAILURE_MODES.md`](./FAILURE_MODES.md) for judge-oriented failure documentation.
## Demo script
**Preferred (companion):** open `/companion/` → Stock sample pantry → **Run weekly kitchen** (`kitchen_run`).
**Tool-by-tool (Alexa+ / MCP client):**
1. **Warm start** — `session_recall` with `householdId: "demo"`.
2. **Stock the pantry** — `pantry_upsert` eggs, milk, rice.
3. **Prefs** — `prefs_set` `{ diet: ["omnivore"], servings: 2 }`.
4. **Agent loop** — `kitchen_run` `{ days: 3, goal: "weekly" }` → steps + meal/product `mediaCard`s + cart.
5. **Or manual:** `meal_plan` → `shop_list_build` → `product_search` → `cart_draft` → `cart_confirm`.
6. **Recall** — `session_recall` shows cart + pantry counts (SQLite-durable across restart).
## SDK notes
- Package: `@modelcontextprotocol/sdk` **v1.30.x** (monolith). Its `LATEST_PROTOCOL_VERSION` is `2025-11-25`.
- Transport: `StreamableHTTPServerTransport` with `enableJsonResponse: true` and session IDs.
- Optional LLM: `@aws-sdk/client-bedrock-runtime` (Converse).
- See [`FRICTION_LOG.md`](./FRICTION_LOG.md) for scaffold friction vs the newer v2 / `2026-07-28` packages and Bedrock notes.
## Appendix — GenAI Open Agent 2026 (separate / parallel context)
> Not the Amazon submission above the fold. Kept for continuity with a later competition prep trunk.
- **Track intent:** 05 Real-World Industry Agents (household kitchen ops); backup 04 Persistent Memory
- **Baseline tag:** `baseline/pre-genai-2026-10-14` — see [`PREEXISTING.md`](./PREEXISTING.md)
- **Submission packet:** [`SUBMISSION_GENAI.md`](./SUBMISSION_GENAI.md)
- Resources / prompts and durable memory listed above are already part of the Amazon-facing product surface.
## License
MIT — see [LICENSE](./LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues