Skip to main content
Glama
hassan3301
by hassan3301
README.md
# Veloce MCP Server

A read-only [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that lets restaurant staff query their [Veloce](https://posveloce.com) POS data in plain language through an MCP client — Claude Desktop, the MCP Inspector, Claude Code, etc.

Built with the FastMCP Python SDK. Every Veloce endpoint it touches is read-only — there are no tools that can change or delete data.

> **About this repository.** This is a generalized, portfolio version of a server originally built for a multi-location restaurant client. Credentials, real location names, and all business data have been removed; the location names here (`Downtown`, `Midtown`, …) are placeholders you can rename. Veloce is a third-party POS platform and is not affiliated with this project.

## What it can answer

| Tool | Answers questions like |
|------|------------------------|
| `list_locations` | "Which locations can I ask about?" |
| `get_sales_summary` | "What were Downtown's total sales last Saturday?" |
| `get_daily_sales` | "Show me Uptown day-by-day for last week." |
| `get_payment_breakdown` | "How much came in via Uber vs cash at Midtown yesterday?" |
| `get_top_products` | "What were Eastside's 10 best sellers in May?" |
| `get_category_sales` | "Food vs beverage split at Westside last month?" |
| `get_hourly_sales` | "What's the busiest hour at Downtown on Sundays?" |
| `get_service_mode_sales` | "Dine-in vs delivery at Midtown last week?" |
| `get_employee_sales` | "Who were the top servers at Uptown in April?" |
| `get_refunds_and_voids` | "Any unusual refunds at Eastside yesterday?" |

### Weekly reports

| Tool | Produces |
|------|----------|
| `get_upsell_report` | Per-server upsell performance: beverages + food upgrades + sides as a % of each server's sales. |
| `get_lto_report` | Per-server Limited Time Offer sales vs. the tracked LTO list. |
| `get_avm_report` | Average Meal Value (net sales ÷ meal count) with a daily breakdown. |

### LTO items — managed as data, not code

The Limited Time Offer list lives in `lto_items.json` and is matched as case-insensitive substrings. When a promo changes, update it by conversation instead of combing the item list:

| Tool | Use |
|------|-----|
| `get_lto_items` / `set_lto_items` | View or replace the tracked LTO list. |
| `search_menu_items` | Find sold items by keyword (e.g. every "blueberry" item). |
| `find_new_items` | Surface items that started selling recently but weren't selling in an earlier baseline period — i.e. likely new LTOs. |

Typical flow: *"What new items showed up this month at Downtown?"* → `find_new_items` lists candidates → *"Track those as LTOs"* → `set_lto_items` saves them → `get_lto_report` uses them automatically.

It also exposes the location list as a resource (`veloce://locations`) and a `daily_briefing` prompt that produces an end-of-day manager summary.

## Setup

1. **Install dependencies** (Python 3.10+):

   ```bash
   cd veloce-mcp-server
   python3 -m venv .venv && source .venv/bin/activate
   pip install -r requirements.txt
   ```

2. **Configure your locations.** Edit `_LOCATION_KEYS` in `config.py` to match your locations, then add credentials. Each location is a separate Veloce login, so each needs its own email/password.

   ```bash
   cp .env.example .env
   ```

   Open `.env` and fill in the values. **Never commit `.env`** — only `.env.example` (which holds no secrets) is safe to share.

## Test it locally with the MCP Inspector

```bash
mcp dev server.py
```

This opens the browser-based Inspector. Click **Connect**, then try a tool: pick `get_sales_summary`, enter a location (e.g. `Downtown`) and a date, and run it. This is the fastest way to confirm credentials and the connection work before wiring it into a client.

## Connect it to Claude Desktop

Add this to your Claude Desktop config file
(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "veloce": {
      "command": "/absolute/path/to/veloce-mcp-server/.venv/bin/python",
      "args": ["/absolute/path/to/veloce-mcp-server/server.py"]
    }
  }
}
```

Use absolute paths, then restart Claude Desktop. The Veloce tools will appear and you can ask questions like *"What were Downtown's sales last Saturday and how did people pay?"*

## Notes & conventions

- **Dates** are `YYYY-MM-DD`. Where a range is optional it defaults to today.
- **Tokens** are cached in memory per location and refreshed automatically on a 401, so the server logs in once per location per session.
- **Locations** are matched case-insensitively and by prefix (`down` → `Downtown`).
- The server only loads locations that have *both* an email and password set, so it still runs with a subset configured.

## Architecture

- `server.py` — defines the MCP tools, resource, and prompt (FastMCP).
- `veloce_client.py` — per-location auth, in-memory token caching, automatic re-auth on 401, and a generic authenticated GET helper. All calls are read-only.
- `config.py` — loads per-location credentials from the environment and resolves friendly location names.
- `lto_items.json` — the editable Limited Time Offer list.

## Extending it

The Veloce API exposes many read-only endpoints; this server wraps the most useful ~10. To add another (e.g. `/sales/taxes`, `/transactions/giftCards`, `/sales/discounts`), add a new `@mcp.tool()` function in `server.py` that calls `vc.api_get(location, "/the/path", {params})`. See the [Veloce API documentation](https://posveloce.com) for the full endpoint list.

## License

MIT — see [LICENSE](LICENSE).