yard-desk
by MNLABSUK
README.md
# Yard Desk
**Simulated Alexa+ trade desk** for a small CCTV / field business (Sky Guard–style ops).
**Not a shell** — a practice desk with session memory, editable drafts, and an activity audit. An agent lists today’s jobs, triages inbox items, drafts client chases, and proposes invoices — always through **real MCP tools**. A human must **Approve / Leave it / Later**. Yard Desk **never** auto-sends money or legal commitments.
Built for the **Amazon Developer Hackathon** — track: **Alexa+**.
> This is a **new project** created during the submission window (not a pre-existing product wrap).
> No payment cards. No Nebius.
## Eligibility map
| Requirement | How Yard Desk meets it |
|-------------|------------------------|
| Real MCP server (official Python SDK) | `yard_desk/mcp_server.py` uses `mcp.server.MCPServer` |
| Streamable HTTP | Mounted at **`/mcp`** via `streamable_http_app(...)` |
| Tools actually called in code | Sim agent uses `mcp.Client(mcp)` → `call_tool(...)` |
| Simulated Alexa+ experience | Cream/navy Sky Guard desk phone UI; MCP tool names on chip tooltips |
| Works without paid APIs | Rule-based dry-run agent when no LLM key |
| Human gate | Yes, go ahead / No, leave it / Later → `record_decision` (editable draft audited) |
## Product depth
| Feature | What you get |
|---------|----------------|
| Session memory | Remembers last item/job; “chase them” / “invoice it” work |
| Editable drafts | Full draft in the decision bar — edit before Yes/No/Later |
| Activity audit | Sidebar **Activity** + `GET /api/activity` (process lifetime) |
| Chat yes/no | Typing “yes” / “leave it” / “later” maps to `record_decision` |
| Richer tools | `get_job`, `get_inbox_item`, `list_overdue`, `list_activity` |
## MCP tools
| Tool | Purpose |
|------|---------|
| `list_todays_jobs` | Sample field schedule |
| `get_job` | Single job detail (address, tech, £ totals) |
| `get_inbox_item` | Single inbox item |
| `list_overdue` | Overdue / chase items with amounts |
| `list_activity` | Recent drafts + gate decisions |
| `triage_inbox_item` | Classify a message |
| `draft_client_chase` | Draft chase text for overdue bill |
| `propose_invoice` | Draft invoice send proposal after job complete |
| `record_decision` | `approve` \| `leave` \| `later` with optional note + edited draft |
## How MCP Streamable HTTP is exposed
- **URL path:** `http://127.0.0.1:43150/mcp`
- **Transport:** Streamable HTTP (`json_response=True`, `stateless_http=True`)
- **SDK:** official `mcp` Python package v2 (`MCPServer`)
- FastAPI lifespan enters `mcp.session_manager.run()` so the mounted ASGI app can serve sessions.
### Verify the MCP endpoint
With the server running:
```bash
# Health (REST) confirms tools + path
curl -s http://127.0.0.1:43150/api/health | python3 -m json.tool
# MCP initialize (Streamable HTTP / JSON)
curl -s -X POST http://127.0.0.1:43150/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"initialize",
"params":{
"protocolVersion":"2025-11-25",
"capabilities":{},
"clientInfo":{"name":"yard-desk-verify","version":"0.2.0"}
}
}'
```
You should get a JSON-RPC result with `serverInfo.name` ≈ `yard-desk` (not HTTP 404/421).
### MCP Inspector
If you have the [MCP Inspector](https://github.com/modelcontextprotocol/inspector):
```bash
npx @modelcontextprotocol/inspector
```
Connect with transport **Streamable HTTP** to:
```text
http://127.0.0.1:43150/mcp
```
List tools — you should see the Yard Desk tools above. Call `list_todays_jobs` from the Inspector to prove the server.
In-process (no HTTP), tests also call tools via `Client(mcp)`.
## Product UI
Cream / navy phone desk for Sky Guard ops — Instrument Sans / DM Sans, expandable job cards (address, tech, £), inbox badges after decisions (chased / left / later), editable draft textarea in the Decision Gate, and an **Activity** feed in the sidebar. Main chrome stays trade-desk language; MCP / Streamable HTTP details sit in a subtle footer and settings chip. Tool chips show human labels with the technical `MCP · tool_name(...)` name in the tooltip for judges.
## Desk walkthrough (demo video)
1. Start the app (`./scripts/start.sh`).
2. Open [http://127.0.0.1:43150/](http://127.0.0.1:43150/).
3. Use chips or type:
- **What's on today?** → `list_todays_jobs` (at-risk called out + next action)
- **What's overdue?** → `list_overdue` with £ + offer to chase top one
- **Chase Ridgeway** → triage + draft + editable pending decision
- **Invoice Oak Street** → `get_job` totals + invoice draft
- Follow-ups: **chase them** / **invoice it** / chat **yes**
4. Edit the draft textarea, then **Yes, go ahead / No, leave it / Later** → `record_decision` (edited text on Activity).
5. Watch the Activity panel and inbox badges update.
## Stack
- Python 3 + FastAPI + official **MCP** SDK (`MCPServer`, Streamable HTTP)
- Package `yard_desk/`
- Product cream/navy Sky Guard desk UI (`web/static/`)
- `uvicorn` on port **43150**
## Quick start
```bash
cd yard-desk
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env # optional — leave LLM keys blank for dry-run
.venv/bin/pytest -q
./scripts/start.sh
```
Then open [http://127.0.0.1:43150/](http://127.0.0.1:43150/)
```bash
curl -s http://127.0.0.1:43150/api/health | python3 -m json.tool
curl -s http://127.0.0.1:43150/api/jobs | python3 -m json.tool
curl -s http://127.0.0.1:43150/api/activity | python3 -m json.tool
curl -s -X POST http://127.0.0.1:43150/api/chat \
-H 'Content-Type: application/json' \
-d '{"message":"What'\''s on today?"}' | python3 -m json.tool
```
## Optional later — AWS Builder mini
Not required for this MVP. A future iteration can add an AWS Builder ID–oriented mini (e.g. deploy notes / Cognito-less static hosting) without changing the MCP tool contract.
## Seed desk items
1. Overdue invoice chase (Ridgeway / INV-2841)
2. Quote request (cameras + NVR)
3. Supplier delay (Ash Grove parts)
4. Spammy vendor blast
5. Family / household bill reminder
6. Job complete — Oak Street ready to invoice
## License
MIT © MN Labs
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues