@gerezi/mcp
v0.1.3
Published
MCP server that exposes the Gerezi restaurant platform as Claude tools (read-only Phase 1 + read+write Phase 2). Includes both stdio (`gerezi-mcp`) and Streamable-HTTP (`gerezi-mcp-http`) entry points.
Maintainers
Readme
@gerezi/mcp — Gerezi MCP server
A small Node program that lets Claude (Claude Code, Claude Cowork, Claude.ai, any MCP-aware client) talk to the Gerezi restaurant platform in plain English.
Two ways to run it:
| Mode | Entry point | Used by |
|---|---|---|
| stdio (gerezi-mcp) | dist/server.js | Claude Code on the operator's laptop (.mcp.json) and Claude Desktop (claude_desktop_config.json). One process per restaurant; key stored in .env. |
| HTTP (gerezi-mcp-http) | dist/server-http.js | The hosted multi-tenant deployment at https://mcp.gerezi.com. One server, many restaurants — each request carries its own Authorization: Bearer <gerezi-api-key>. |
Both share the same tool surface, defined once in src/core.ts.
What you can do with it
Once it's running and registered, type questions like these:
"Show me Villa Anvers tonight." "Find Julie Kohlhoff's booking." "Give me a quick restaurant summary." "Move BK-XXXX to 21:00 on Saturday." "Send the wedding quote to [email protected]."
Claude resolves them by calling one of the tools below.
Tools
Phase 1 — read-only (5 tools)
| Tool | What it does |
|---|---|
| list_bookings_for_date | Every booking on a given day with party, table, source, status |
| find_booking_by_guest_name | Substring search across recent + upcoming bookings |
| get_restaurant_summary | Today's covers, abandoned-cart leads, last-7-day no-shows |
| list_recent_staff_overrides | Force-overbooks + 48h-window bypasses from the audit log |
| search_guests | Fuzzy search the guest CRM by name / email / phone |
Phase 2 — read + write (10 more tools, gated by GEREZI_MCP_PHASE=2)
| Tool | What it does |
|---|---|
| move_booking | Reschedule a booking (time, table, party size) |
| cancel_booking | Cancel + optional refund + optional notify_guest: false for silent cleanup |
| change_party_size | Adjust covers without touching the time slot |
| add_internal_note | Append staff-only note to the booking |
| update_booking_contact | Fix guest name / email / phone on a placeholder booking |
| create_booking | Create a confirmed booking (placeholder or real customer) |
| create_devis | Wedding/private-event quote |
| revise_devis | Update an existing quote's line items / total |
| send_devis | Email the quote to the guest |
| cancel_devis | Mark a quote cancelled |
Every Phase-2 tool carries annotations.destructiveHint: true so MCP
clients can prompt the operator before executing.
Setup
Local stdio (Claude Code / Claude Desktop)
Generate an API key (from the repo root):
node scripts/generate-mcp-api-key.mjs --slug villa-anvers --name "MCP — read-only"Writes
tbl_live_*togerezi-mcp/.env(gitignored, mode 0600).Install + build:
cd gerezi-mcp npm install npm run buildRestart Claude Code. The repo-root
.mcp.jsonregisters this MCP automatically. Try:"Show me Villa Anvers bookings on May 7."
Hosted HTTP (mcp.gerezi.com)
The HTTP variant runs as a stateless Express server. Each request
carries its own API key in the Authorization header — no per-tenant
process, no in-memory session state, no cross-tenant leakage.
Claude client mcp.gerezi.com www.gerezi.com
────────────── Streamable ──────────────── HTTPS Bearer ────────────────
│ HTTP ───────────────► THIS SERVER ───────────────► /api/v1/*
│ Bearer <restaurant key> │
│ build a fresh MCP Server per
│ request, scoped to that key.Local smoke test:
PORT=3000 GEREZI_MCP_PHASE=2 node dist/server-http.js &
curl -sS http://127.0.0.1:3000/healthz
curl -sS -X POST http://127.0.0.1:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer tbl_live_…' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'Coolify deployment
- DNS: add an
Arecordmcp.gerezi.com→ Hetzner CX22 IP. - New Coolify app (Dockerfile mode):
- Repo: same as the main app
- Branch:
main - Dockerfile:
gerezi-mcp/Dockerfile.mcp-http - Build context:
gerezi-mcp/ - Port:
3000 - Domain:
mcp.gerezi.com(Coolify provisions Let's Encrypt cert via Traefik)
- Env vars:
GEREZI_API_URL=https://www.gerezi.comGEREZI_MCP_PHASE=2GEREZI_MCP_SHARED_TOKEN=<long random>(optional — pre-public gate)
- Deploy — Coolify polls
/healthzfor liveness; Traefik routes once it returns 200. - Verify:
curl https://mcp.gerezi.com/healthz # {"ok":true,"service":"gerezi-mcp","phase":"2"}
Optional shared-secret gate
If GEREZI_MCP_SHARED_TOKEN is set, callers must also send
X-Gerezi-Mcp-Token: <token> on each POST /mcp. Useful for keeping
the endpoint quiet before the npm package + registry submission go
public. Leave it unset once you're ready for unlisted public access —
the per-restaurant Gerezi API key is the real auth.
npm package (@gerezi/mcp)
Once published to npm, anyone can install + run the stdio server with:
npx -y @gerezi/mcp…provided they set GEREZI_API_KEY in env or in .env. That makes
custom-client config a one-liner:
// claude_desktop_config.json (Claude Desktop)
{
"mcpServers": {
"gerezi": {
"command": "npx",
"args": ["-y", "@gerezi/mcp"],
"env": {
"GEREZI_API_KEY": "tbl_live_…",
"GEREZI_MCP_PHASE": "2"
}
}
}
}Architecture
src/
├── core.ts ── buildMcpServer({apiUrl, apiKey, slug, phase}) factory
├── server.ts ── stdio entry → connects buildMcpServer() to StdioServerTransport
└── server-http.ts ── Express + StreamableHTTPServerTransport (stateless, per-request key)The closures over apiKey in core.ts mean each Server instance is
bound to one restaurant's credentials — for the HTTP variant we build
a fresh Server per request with the key extracted from the
Authorization header.
Smoke tests
npm run smoke # Phase 1: 11 checks
npm run smoke:p2 # Phase 2: 31 checks (includes destructiveHint audit)Runs the compiled server against an unreachable URL (port 1) so we verify boot + handshake + tool listing + graceful error handling without hitting production.
Troubleshooting
GEREZI_API_KEY env var is missing — .env missing or empty.
Re-run scripts/generate-mcp-api-key.mjs from the repo root.
Tool calls return Gerezi API 401 — key was revoked. The
bootstrap script auto-deactivates old keys when re-run.
Tool calls return Gerezi API 307 / land on /sign-in — the
public-paths fix in src/middleware.ts (allowing /api/v1/(.*))
isn't deployed yet. Redeploy on Coolify.
Claude Cowork doesn't see the MCP — Cowork doesn't auto-load
local stdio MCPs from .mcp.json. Use the hosted endpoint
(https://mcp.gerezi.com) once Layer 3a is live, or paste the
operator's API key into Cowork's per-conversation MCP config.
See docs/mcp-roadmap.md for the full
multi-layer rollout plan (npm → hosted → OAuth → registry).
