Skip to main content
Glama
rrabe

ElevenAir Customer Service — MCP Server

by rrabe
README.md
# ElevenAir Customer Service — MCP Server (example)

A small, self-contained **Model Context Protocol (MCP)** server that gives a
conversational AI voice agent a set of airline customer-service tools. It powers
a demo in which a caller reaches "ElevenAir", authenticates, and rebooks a
canceled flight — ending with a real HTML confirmation e-mail.

> This is a demo/example project. Bookings and flights are mock data, and the
> rebooking is simulated (not persisted). The only real side effect is sending
> the confirmation e-mail over SMTP.

## Features

- **Five MCP tools** exposed over the streamable-HTTP transport.
- **Mock data** for 10 bookings and a set of alternative flights (JSON files).
- **Real confirmation e-mail** rendered from a clean HTML template and sent via
  your own SMTP server (with a plain-text fallback).
- **Readable terminal logs** (via [rich](https://github.com/Textualize/rich)) so
  you can follow every tool call live.
- **Simulated e-mail mode** when no SMTP credentials are configured, so the
  server runs out of the box.

## Tools

| Tool | Parameters | Description |
| --- | --- | --- |
| `authenticate_customer` | `booking_reference`, `date_of_birth` | Verifies the caller's identity before anything else. |
| `get_booking_details` | `booking_reference` | Returns the current booking and flight status. |
| `list_alternative_flights` | `booking_reference` | Lists alternatives on the same route, earliest first. |
| `rebook_flight` | `booking_reference`, `new_flight_id` | Rebooks onto a new flight (mocked, not persisted). |
| `send_confirmation_email` | `booking_reference`, `new_flight_id` | Sends the HTML confirmation e-mail via SMTP. |

## Project layout

```
server.py            FastMCP server and the five tools
data.py              Loads mock data and provides lookup helpers
logs.py              Rich-based terminal logging helpers
email_template.html  HTML e-mail template (tokenized with {{...}})
bookings.json        Mock bookings
flights.json         Mock alternative flights
smoke_test.py        Manual end-to-end check of all tools
requirements.txt     Pinned dependencies
.env.example         Template for SMTP configuration
```

## Requirements

- Python 3.10+ (developed on 3.14)
- An SMTP account if you want real e-mails (optional; otherwise sends are simulated)

## Setup

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

## Configuration

Copy the example environment file and fill in your SMTP details:

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

```dotenv
SMTP_HOST=smtp.example.com
SMTP_PORT=587          # 587 (STARTTLS) or 465 (SSL)
SMTP_USER=you@example.com
SMTP_PASSWORD=your-app-password
SMTP_FROM=you@example.com
```

If `SMTP_HOST`, `SMTP_USER`, or `SMTP_PASSWORD` are empty, the server logs a
**simulated** send instead of contacting a mail server.

To receive the confirmation e-mail during a demo, set the passenger `email` in
[`bookings.json`](bookings.json) to an inbox you control.

## Run

```bash
python server.py
```

The MCP endpoint is served at `http://127.0.0.1:8000/mcp`, with a health check at
`http://127.0.0.1:8000/health`.

## Expose it publicly

A cloud-hosted MCP client needs a public URL to reach the server. For local
development, tunnel with [ngrok](https://ngrok.com):

```bash
ngrok http 8000
```

Use the resulting HTTPS URL plus `/mcp` as the server URL, e.g.
`https://<subdomain>.ngrok-free.app/mcp`.

## Connect it to a voice agent

Any MCP client that supports the streamable-HTTP transport can use this server:

1. **Server URL:** your public URL ending in `/mcp`.
2. **Transport:** Streamable HTTP.
3. If you tunnel through ngrok, send the HTTP header
   `ngrok-skip-browser-warning: true` to skip ngrok's interstitial page.
4. Drive the flow from the agent's instructions: authenticate first, then look up
   the booking, offer the next flight, rebook, and send the confirmation.

## Smoke test

Exercise all five tools in one shot (this sends a real e-mail if SMTP is set):

```bash
python smoke_test.py
```

## Security

- Secrets live only in `.env`, which is **git-ignored** and must never be committed.
- The server reads all credentials from environment variables.
- Treat any tunnel URL as sensitive while it is live.

## Notes

- The network covers five cities: London (LHR), New York (JFK), San Francisco
  (SFO), Warsaw (WAW), and Berlin (BER).
- Rebooking is a mock: it confirms and e-mails, but does not change stored data.