fare-data MCP server
by gvdeepthi
README.md
# fare-data MCP server
> **New here?** Follow the step-by-step [SETUP.md](SETUP.md) to get running.
Exposes ATPCO fare CSV snapshots (the ~119-column fare feed layout: CXR, ORIG,
DEST, Fare Class, Fare AMT, Tax AMT, Total Price AMT, Cabin, restrictions, …)
from a local folder to Claude via the Model Context Protocol, plus a live
fare-shopping tool backed by engine-wrapper-service.
## Data directory
Drop your fare CSVs into the data folder. Resolution order:
1. `FARE_DATA_DIR` environment variable, if set
2. `../fare-data` (a folder named `fare-data` next to this repo), if it exists
3. `./data` inside this repo
Any `*.csv` with the fare-feed header layout is picked up automatically; no
restart needed when you add or replace files (each tool call re-reads the
directory).
## Tools
| Tool | What it does |
|---|---|
| `list_fare_files` | List available CSVs with fare counts, markets, carriers |
| `get_schema` | Column names + a sample row for one file |
| `query_fares` | Filter fares (exact-match on any column, price range), sorted, compact column projection |
| `fare_summary` | Count/min/avg/max of Fare AMT and Total Price AMT grouped by any column (default Cabin) |
| `compare_files` | Diff two snapshots of a market: added / removed / repriced fares |
| `shop_fares` | Live fare shop via engine-wrapper-service — POST to frmwithtotalpricewrapperstream |
### shop_fares notes
- Requires the internal engine-wrapper endpoint (corporate network/VPN).
Configure it via `ENGINE_WRAPPER_URL` — copy `.env.example` to `.env` and
fill in the URL (ask your team; it is deliberately not committed) — or pass
`endpoint_url` per call (e.g. to hit the historical wrapper).
- `origin`, `destination`, `carrier` are required; everything else defaults to
the standard request: dates (`travelDate`, `asOfDateTime`, `ticketDate`)
default to the current date/time in engine format (e.g. `02AUG26T1119`),
`hostCarrier` defaults to `carrier`, `userId` defaults to `ATP1XXX`,
trip type `OW`, `daysStay` 7.
- Any other request field can be set through the `overrides` dict, which is
merged last and wins (e.g. `{"taxes": false, "validateCategories": "15"}`).
An override set to `null` removes that field from the request entirely.
- Responses whose parsed JSON exceeds `max_response_chars` (default 200000)
return a preview only, to protect the LLM context window. Programmatic
callers should pass `max_response_chars: 0` for complete data.
## Setup
```bash
cd fare-mcp-server
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env # then fill in ENGINE_WRAPPER_URL
```
## Running without Claude
Claude is just one MCP client — the server runs standalone and anything that
speaks MCP (or plain Python) can drive it.
**Raw stdio mode** (what any MCP client spawns):
```bash
.venv/bin/python server.py
```
It waits silently for JSON-RPC on stdin — normal for a stdio server. Ctrl+C
to exit.
**MCP Inspector** — interactive web UI to browse and call the tools (best for
development, debugging, and demos; requires Node):
```bash
npx @modelcontextprotocol/inspector .venv/bin/python server.py
```
**From a Python script** — the MCP client library is already installed in the
server's venv:
```python
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
params = StdioServerParameters(command=".venv/bin/python", args=["server.py"])
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("list_fare_files", {})
print(result.content[0].text)
asyncio.run(main())
```
**No MCP at all** — the tools are plain Python functions:
```bash
.venv/bin/python -c "import server, json; print(json.dumps(server.list_fare_files(), indent=2))"
```
## Register with Claude Code
From the directory where you cloned this repo:
```bash
claude mcp add --scope user fare-data \
--env FARE_DATA_DIR="$(pwd)/../fare-data" \
-- "$(pwd)/.venv/bin/python" "$(pwd)/server.py"
```
(`--env FARE_DATA_DIR=...` is optional — see the resolution order above.)
## Register with Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`,
replacing `<repo>` with your clone's absolute path:
```json
{
"mcpServers": {
"fare-data": {
"command": "<repo>/.venv/bin/python",
"args": ["<repo>/server.py"]
}
}
}
```
Then restart Claude Desktop.
## Use from FarePulse-Agent
FarePulse-Agent can route its wrapper snapshot calls and competitor probes
through this server: clone the two repos side by side and set
`FARE_MCP_ENABLED=1` in FarePulse-Agent's `.env` (see the "fare-data MCP
server" section of its README).
## Example prompts once connected
- "What fare files are available?"
- "Show me the cheapest business-class fares in MEX_LAX_28Jul.csv"
- "Summarize fares by cabin in the 28Jul file"
- "What changed between the 10Jul and 28Jul MEX-LAX snapshots?"
- "Shop live fares for ADL-LAX on FJ, one way"
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues