jagabukit-mcp
README.md
# jagabukit-mcp
A read-only **MCP server** over the JagaBukit reception Google Sheet — the same
append-only sheet the WhatsApp receptionist in [`../jagabukit-backend`](../jagabukit-backend)
writes to. It lets any MCP client (Claude Desktop, Cursor, or a local **Ollama**-backed
agent) *query* the reception data through five tools.
Built as a Forward-Deployed-Engineer proof: **when a client's system has no connector,
you write the MCP server that gives an agent access to it.** Here the "client system" is
the reception sheet; the server exposes it without touching the production write path.
## Why this shape
- **Read-only.** The bot owns the append-only writes; this server never mutates the sheet.
It mirrors `store.ts`'s exact column order (`store.py`), so the two never drift.
- **Runs with zero credentials.** The default source reads local CSV fixtures, so you can
demo, test, and develop with no Google auth and no API spend (same credit-safe discipline
as the backend's fakes). Flip one env var to read the live sheet.
- **Layered for testing.** Pure parsing (`store.py`) → queries (`queries.py`) → thin MCP
tools (`server.py`). The tools are wrappers, so tests and the smoke script exercise the
real logic without a running client.
## Tools
| Tool | Returns |
|------|---------|
| `list_recent_messages(limit=20)` | Most recent conversation turns, newest first |
| `get_conversation(phone)` | Full ordered history for one phone number |
| `list_bookings(upcoming_only=True)` | Booked villa health-checks (future/undated by default) |
| `find_by_villa(query)` | Bookings + leads matching a villa name/area (e.g. "Bingin") |
| `reception_stats()` | Counts: turns, unique contacts, leads, bookings |
## Quick start
```bash
cd jagabukit-mcp
python -m venv .venv
.venv\Scripts\activate # Windows (source .venv/bin/activate on macOS/Linux)
pip install -r requirements.txt
# 1) Prove the data layer works — no model, no credentials:
python smoke.py
# 2) Run the tests:
pytest -q
# 3) Run the MCP server (stdio):
python server.py
```
## Point it at the live sheet
```bash
cp .env.example .env
# set in .env:
# JAGABUKIT_SHEET_SOURCE=google
# JAGABUKIT_SPREADSHEET_ID=<the reception sheet id>
# GOOGLE_APPLICATION_CREDENTIALS=./service-account.json (read access to that sheet)
pip install google-api-python-client google-auth
```
The service account needs only the read-only Sheets scope. Share the sheet with the
service account's email (Viewer) — no OAuth dance, it runs headless.
## Connect it to a client
**Claude Desktop** — add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"jagabukit-reception": {
"command": "python",
"args": ["C:/Users/Riska/Documents/Utamation/jagabukit-mcp/server.py"]
}
}
}
```
**Local / Ollama agent** — this server speaks standard MCP over stdio, so any MCP-capable
client works. For a fully-local, no-API-cost loop, drive it from an Ollama-backed MCP client
(see the `mcp_ai_agents` examples in `../awesome-llm-apps`). The server is model-agnostic —
whatever model the client runs, these five tools look the same.
## Layout
```
store.py # pure row->dataclass parsing, mirrors jagabukit-backend store.ts
queries.py # business logic over a SheetSource (recent, history, bookings, search, stats)
sources.py # CsvSheetSource (default, offline) + GoogleSheetSource (live) + env picker
server.py # FastMCP server: 5 read-only tools wrapping queries
smoke.py # credit-safe: call every query directly and print results
fixtures/ # sample Conversation/Leads/Bookings/Reminders CSVs (fake Uluwatu data)
tests/ # pytest unit tests (deterministic, AAA)
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues