# SOS Flights MCP server

Last updated: 2026-10-02 · Operator: SOS Flights (pelicantravel.com s.r.o.) · Endpoint: `https://www.sosflights.help/mcp`

SOS Flights helps travellers whose flight is cancelled, delayed or overbooked. The MCP server gives an AI assistant four tools for passenger rights, what to say at the airline desk, airport help and live alternative flights, and five tools for a paid case handled by the SOS Flights team. No tool needs an account: a case is paid on SOS Flights' payment page and reached afterwards by its case code.

For travellers, the setup guide is at <https://www.sosflights.help/en/connect>.

## Connection

| | |
|---|---|
| Endpoint | `https://www.sosflights.help/mcp` (always `www`: the bare domain answers 301, which MCP clients do not follow on POST) |
| Transport | Streamable HTTP, `POST` only, stateless. `GET` and `DELETE` answer 405; there is no SSE stream and no session. |
| Protocol version | `2025-11-25` |
| Capabilities | `tools` only (no resources or prompts) |
| Responses | JSON (`Accept: application/json, text/event-stream`) |
| Origin check | Requests from `sosflights.help` and from assistant origins (`claude.ai`, `claude.com`, `chatgpt.com`, `chat.openai.com`, `grok.com`, `gemini.google.com`, `copilot.microsoft.com`, `m365.cloud.microsoft`) are served, as are requests without an `Origin` header. Any other `Origin` gets 403. |
| Timeout | Every call answers within 30 seconds; the flight search stops at 25 seconds and returns an error. |
| Rate limits | None. |

## Access

There is no sign-in and no account. Two kinds of caller reach the same server, tools and names.

| Caller | How it identifies | What changes |
|---|---|---|
| Direct caller (Claude, ChatGPT, any MCP client) | No `Authorization` header needed | Links carry `utm_source=mcp`. |
| Tripdesk gateway | `Authorization: Bearer <service token>` | Links are untagged and the call is logged as `tripdesk-gateway`. |

### Case codes

A case code is 8 characters (for example `53039309`). It is shown when the case is opened and on the payment confirmation, and it is the key to the case afterwards, as on the case page at `https://www.sosflights.help/<lang>/case-status?code=<case_code>`. Anyone with the code can read the case status and messages and write to the team, so travellers should keep it private.

### No OAuth

The server publishes no OAuth metadata and answers no request with 401, so clients connect without a login prompt. In ChatGPT, choose no authentication when creating the connector.

### Tripdesk gateway

The gateway sends a service token that only it and SOS Flights hold. The token names no user and is not a Supabase JWT. It is shared through deploy secrets, never in chat. On gateway calls the server:

- does not call Supabase Auth,
- returns links without `utm_` tags, so the gateway can add its own reference,
- logs the call as `tripdesk-gateway`.

Gateway configuration: `PRODUCTS_ENABLED` contains `sosflights`, `SOSFLIGHTS_MCP_URL=https://www.sosflights.help/mcp`, `SOSFLIGHTS_MCP_TOKEN=<service token>`.

All nine tools, cases included, work through the gateway, because cases need no account.

## Tools

| Tool | Title | Reads or writes |
|---|---|---|
| `sos_check_rights` | Check passenger rights | read |
| `sos_desk_script` | What to say at the airline desk | read |
| `sos_airport_help` | Airport help tonight | read |
| `sos_find_alternatives` | Find alternative flights | read (live search) |
| `sos_prepare_case` | Prepare an SOS Flights case | read, returns a confirmation token |
| `sos_open_case` | Open the SOS Flights case | write |
| `sos_get_case` | Get case status | read |
| `sos_prepare_message` | Prepare a message to the team | read, returns a confirmation token |
| `sos_send_message` | Send the message to the team | write |

Every tool sets all four annotations explicitly:

| Tool | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
| `sos_check_rights`, `sos_desk_script`, `sos_airport_help` | true | false | true | false |
| `sos_find_alternatives` | true | false | true | true |
| `sos_prepare_case`, `sos_get_case`, `sos_prepare_message` | true | false | true | false |
| `sos_open_case`, `sos_send_message` | false | false | true | true |

### sos_check_rights

Checks a disrupted flight against EU261, UK261 and US DOT rules. Returns the law that applies, up to three options (refund, re-routing), the care the airline owes, a compensation range per passenger with its conditions, warnings and facts that would sharpen the answer. Advice only, not legal advice.

| Field | Type | Required | Meaning |
|---|---|---|---|
| `type` | enum `cancellation`, `delay`, `denied_boarding`, `missed_connection` | yes | What happened to the flight |
| `origin` | string, 3-letter IATA | yes | Departure airport, for example `VIE` |
| `destination` | string, 3-letter IATA | yes | Final destination on the booking, for example `LHR` |
| `carrier` | string | no | Operating airline, for example `FR` |
| `arrival_delay_minutes` | integer | no | Expected arrival delay at the final destination |
| `departure_delay_minutes` | integer | no | Departure delay, if different |
| `notice_days` | integer | no | Cancellations: days between notice and scheduled departure |
| `reroute_departs_earlier_minutes` | integer | no | Re-routing offered: minutes earlier than the original flight |
| `reroute_arrives_later_minutes` | integer | no | Re-routing offered: minutes later than the original flight |
| `single_booking` | boolean | no | Missed connections: all flights on one booking |
| `volunteered` | boolean | no | Denied boarding: the traveller volunteered |
| `cause` | enum `unknown`, `technical`, `airline_staff_strike`, `crew_shortage`, `weather`, `atc`, `atc_strike`, `airport_strike`, `security`, `bird_strike`, `political`, `medical` | no | Reason the airline gave |
| `overnight` | boolean | no | The traveller must stay overnight |

Result: `law`, `law_reason`, `distance_km`, `options`, `care`, `warnings`, `follow_ups`, `compensation` (`currency`, `min`, `max`, `conditions`), `sources`, `last_verified`, `help_url`.

### sos_desk_script

Writes one to three polite sentences for the traveller to say at the airline desk, in their language, citing the regulation that applies.

Input: the same fields as `sos_check_rights`, plus `lang` (enum `en`, `sk`, `cs`, `de`, `pl`, `hu`, `it`, `es`; defaults to `en`).

Result: `law`, `lang`, `say` (array of sentences).

### sos_airport_help

Lists hotel, lounge and transfer search links for an airport, nearby alternative airports with directions, and who pays for a hotel under EU and UK rules. Links only; nothing is booked. Covers about 100 airports in Europe, North America and Asia.

| Field | Type | Required | Meaning |
|---|---|---|---|
| `airport` | string, 3-letter IATA | yes | Where the traveller is, for example `VIE` |
| `need` | enum `hotel`, `lounge`, `transfer`, `all` | no | Defaults to `all` |

Result: `airport` (`iata`, `name`, `city`, `country`), `links`, `nearby_airports` (`iata`, `name`, `distance_km`, `directions_url`), `who_pays`.

### sos_find_alternatives

Searches live one-way flights from the traveller's airport and up to two airports within 300 km to the destination on one date, ordered by earliest arrival. Times are local to each airport. Nothing is booked.

| Field | Type | Required | Meaning |
|---|---|---|---|
| `origin` | string, 3-letter IATA | yes | Where the traveller is now, for example `BTS` |
| `destination` | string, 3-letter IATA airport or city code | yes | For example `LON` |
| `date` | string, ISO 8601 date | yes | From today up to 365 days ahead, for example `2026-10-02` |
| `include_nearby_airports` | boolean | no | Defaults to `true` |
| `limit` | integer 1–25 | no | Options per page, defaults to 10 |
| `cursor` | string | no | `next_cursor` from the previous page |

Result: `flights` (`from`, `to`, `departure`, `arrival`, `price_eur`, `stops`, `flight_numbers`, `carriers`, `booking_url`, `ground_transfer`), `rail` (operator links for trips under 1,200 km), `who_pays`, `next_cursor`.

Flight data comes from the Pelikan flight search. `booking_url` links to pelikan.sk; on direct calls it carries `utm_source=mcp`.

### sos_prepare_case and sos_open_case

A case is handled by the SOS Flights team: rebooking help, hotel, evidence and follow-up. It costs €99 one time, with no success fee, or is covered by a prepaid access code.

`sos_prepare_case` checks the details and returns what will be submitted, the price and a `confirmation_token`. Nothing is created or charged.

| Field | Type | Required | Meaning |
|---|---|---|---|
| `email` | string, email address | yes | For the payment receipt and case updates |
| `situation_summary` | string, 20–4,000 characters | yes | Airport, travellers and children's ages, what happened, flight number and booking reference, destination and urgency, constraints, safety risks |
| `phone` | string with country code | yes | WhatsApp number, or an urgent contact for chat |
| `channel` | enum `whatsapp`, `chat` | yes | How the team talks to the traveller, as the traveller chose |
| `surname` | string | no | |
| `access_code` | string | no | Prepaid access code |
| `lang` | enum `en`, `sk`, `cs`, `de`, `pl`, `hu` | no | Language of the payment and case pages, defaults to `en` |

Result: `email`, `situation_summary`, `phone`, `surname`, `channel`, `payment` (`checkout` or `access_code`), `price_eur`, `confirmation_token`, `expires_at`.

`sos_open_case` opens the prepared case once the traveller has confirmed it.

| Field | Type | Required | Meaning |
|---|---|---|---|
| `confirmation_token` | string | yes | From `sos_prepare_case`, valid 15 minutes |
| `idempotency_key` | string, 8–100 characters | no | A repeated key returns the first result. Defaults to one key per token. |

Result: `case_code`, `status`, `active`, `channel`, `checkout_url`, `case_url`. The traveller keeps `case_code` to reach the case later.

With checkout, the case is `pending_payment` and `active: false` until the traveller pays on the Stripe page at `checkout_url`. Only then is the team notified. With a valid access code the case is active at once.

### sos_get_case

Returns the case with the given code: status, whether it is active, the team's recommended solution once there is one, the last 10 chat messages for chat cases, and the case page link.

| Field | Type | Required | Meaning |
|---|---|---|---|
| `case_code` | string, 8 characters | yes | From the payment confirmation or the case page |
| `lang` | enum `en`, `sk`, `cs`, `de`, `pl`, `hu` | no | Language of the case page link |

Result: `case_code`, `status`, `active`, `channel`, `recommended_solution`, `messages` (`from` `traveller` or `team`, `at`, `text`), `case_url`.

### sos_prepare_message and sos_send_message

For active cases on the chat channel. WhatsApp cases continue in WhatsApp.

`sos_prepare_message` takes `message` (1–2,000 characters, required) and `case_code` (required), and returns the message with a `confirmation_token`. Nothing is sent.

`sos_send_message` takes `confirmation_token` (required) and `idempotency_key` (optional) and sends the message. The team's reply appears in `sos_get_case` and on the case page.

## Writes

Every write is a pair: a prepare tool and an act tool.

1. The prepare tool validates the input and returns what will happen, with a `confirmation_token`. It has no side effects.
2. The assistant shows that to the traveller.
3. After the traveller confirms, the act tool runs with the token.

The token is a short random id such as `sc_3qJ8vT0kPzL1mW6xR2aYbQ`, returned both in `structuredContent` and in the text summary, so the model can copy it reliably. The prepared arguments stay on the server; the token is bound to the act tool and expires after 15 minutes. The act tool runs exactly what was prepared.

Writes are idempotent: the same `idempotency_key`, or the same token without a key, returns the first result and never opens a case or sends a message twice. A failed write is not stored, so it can be retried with the same key.

No tool takes a payment. Payment happens on SOS Flights' own Stripe checkout page.

## Results and errors

- Every tool declares an `outputSchema` and returns `structuredContent` plus a short text summary of the same result. Property names are snake_case.
- Failures come back as results with `isError: true` and a message that says what went wrong and what to send instead, for example: `date 2020-01-01 is in the past. Send a date from 2026-10-01 onward.`
- Invalid arguments (wrong type, unknown enum value) are rejected by schema validation with `isError: true`.
- Protocol errors are only for malformed JSON-RPC requests.
- Results contain no session, trace or request IDs, internal timestamps, logs or other travellers' data.
- Links are absolute `https` URLs. On direct calls, links to sosflights.help and booking links carry `utm_source=mcp&utm_medium=assistant&utm_campaign=<tool>`. On gateway calls they are untagged.

## Quick start

List the tools:

```bash
curl -s https://www.sosflights.help/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Check passenger rights:

```bash
curl -s https://www.sosflights.help/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"sos_check_rights","arguments":{"type":"cancellation","origin":"BTS","destination":"STN","carrier":"FR"}}}'
```

Add to an assistant:

- ChatGPT: Settings → Apps & Connectors → Advanced settings → Developer mode, then Create, with the endpoint URL and no authentication.
- Claude: Settings → Connectors → Add custom connector, with the endpoint URL.
- Claude Code: `claude mcp add --transport http sosflights https://www.sosflights.help/mcp`
- Other MCP clients: a remote server with Streamable HTTP transport and the endpoint URL.

## Testing

`supabase/functions/mcp/contract.test.ts` in the repository checks the rules above against any deployment: tool names, titles, annotations, output schemas, the portable JSON Schema subset, the Origin check, gateway calls, and one good and one bad call per tool.

```bash
MCP_URL=https://www.sosflights.help/mcp deno test -A --node-modules-dir=none supabase/functions/mcp/contract.test.ts
```

## Privacy and support

- Privacy notice: <https://www.sosflights.help/en/privacy>
- Flight details given to the rights, desk, airport and flight tools are not stored; only the tool name, client, language and duration are logged.
- Advice only, not legal advice. SOS Flights never books, cancels or changes a booking.
- Machine-readable summary: <https://www.sosflights.help/.well-known/mcp.json>
