# SimAtlas — MCP Server for AI Agents SimAtlas (СимАтлас) is a Russian-language eSIM service for travelers. This document describes the Model Context Protocol (MCP) server that lets AI agents search eSIM tariffs, quote a price, and create an order that returns a payment link. The human checkout, payment, and post-payment redirect are unchanged: the returned payment URL opens the normal payment page and, after a successful payment, redirects to the order success page. The eSIM (QR code + activation instructions) is delivered by email. ## Endpoint and transport - URL: https://simatlas.ru/mcp - Transport: MCP Streamable HTTP (spec 2025-11-25), stateless. - Only request/response tool calls are used; there are no server-initiated notifications or streaming. - Tool responses use structured JSON output. ## Authentication 1. Call the `start_session` tool (no auth required). It returns a temporary opaque bearer `token` and its `expires_at`. 2. Send that token on EVERY subsequent tool call as an HTTP header: `Authorization: Bearer `. 3. The token is the equivalent of a session cookie. It expires (24h by default); call `start_session` again to obtain a new one. Treat it as a secret — do not put it in tool arguments or share it. ## Tools ### start_session (no auth) Returns: `{ token, expires_at, usage }`. Begin here. ### search_esim_offers (read-only) Search eSIM data plans. Args: `country` (ISO alpha-2, e.g. TR, DE), `query`, `package_type` (`standard` | `daypass`), `limit` (1-50, default 20), `cursor` (opaque pagination cursor), `currency` (default RUB), `lang` (`ru` | `en`). Returns: `{ offers[], count, next_cursor }`. Each offer has `offer_id`, `name`, data amount, validity, package type, final `price` (RUB, all fees included), and covered `countries`. For daypass offers `is_daypass` is true and `price` is the TOTAL for `price_basis_days` days, while `price_per_day` and `data_per_day` (allowance per day) are per-day values — do not multiply `price` again; call `get_esim_offer` for the full per-day-count price grid. ### get_esim_offer (read-only) Details for one plan. Args: `offer_id`, `currency`, `lang`. For daypass plans (`is_daypass` true) the result includes a `day_options[]` grid — one entry per allowed day count, each `{ days, price (total for that many days), price_per_day }` — plus `min_days`/`max_days`. The top-level `price` is the total for `min_days`, and `price_per_day` / `data_per_day` are per-day values. ### list_countries (read-only) Supported destination countries (ISO code + localized name). Use it to map a country name to the code accepted by `search_esim_offers`. ### create_order_quote (step 1 of ordering) Compute a binding price quote. No order is created and no payment happens yet. Args: `offer_id`, `email` (buyer email for eSIM delivery), `days` (for daypass — if omitted for a daypass offer it defaults to the offer's minimum day count), `quantity`, `promo_code` (optional), `currency` (default RUB). Returns: `{ quote_id, amount, currency, data_amount, data_unit, days, summary, requires_confirmation, expires_at }`, where `amount` is the total for the resolved `days` (matching that day count's `day_options` entry). The quote is short-lived. ### confirm_order (step 2 of ordering) Create the order from a quote and get the payment link. Args: `quote_id`, `idempotency_key` (a unique client-chosen string so retries do not create duplicate orders), `payment_method` (`card` | `sbp`). Returns: `{ order_id, client_order_number, payment_url, amount, currency, status }`. Open `payment_url` to pay; the price charged is recomputed server-side and is rejected if it drifted above the quoted amount (request a fresh quote in that case). Show `client_order_number` (e.g. "СИМ-2026-1042") to the buyer as their order reference — it is human-friendly. For status calls always use `order_id` (the UUID). ### get_order_status (read-only) Check an order you created in this session. Args: `order_id`. Returns: `{ order_id, client_order_number, status, amount, currency, masked_iccid, usage_url }`. `client_order_number` is the human-friendly reference (e.g. "СИМ-2026-1042") to show the buyer; it is not a lookup key. `masked_iccid` is the last four digits of the eSIM's ICCID (e.g. "…2168"). Activation credentials (QR code, activation code) are never returned by this tool; the buyer receives them by e-mail. `usage_url` opens the eSIM's data-usage page only. Data-usage links issued before 2026-10 carry an older signature, which the data-usage page honours until 2027-08-01 00:00 Moscow time (setting `signing.usage_legacy_until`); after that date only links issued since then open it. A status of "refunded" means the order was refunded; no usage link is returned for a refunded order. A status of "failed" means the eSIM could not be issued; do not place a new order for the same purchase: the buyer should contact support, who will check whether a payment was taken. ## Typical flow 1. `start_session` -> save the token; send it as `Authorization: Bearer` from now on. 2. `list_countries` or `search_esim_offers` (e.g. country=TR) -> pick an `offer_id`. 3. `get_esim_offer` -> confirm details / day options. 4. `create_order_quote` with `offer_id` + buyer `email` -> get `quote_id` + price. 5. `confirm_order` with `quote_id` + a unique `idempotency_key` -> get `payment_url`. 6. Give the buyer the `payment_url`. After payment they are redirected to the success page and receive the eSIM by email. 7. `get_order_status` to check progress. ## Notes - All prices are final, in RUB, including all fees, unless another currency is requested. - Payment is by Russian bank card or SBP (Sistema Bystrykh Platezhey). - Validity of a plan starts on first connection abroad, not at purchase. - Be conservative: confirm details with the buyer before calling `confirm_order`. ## Adding SimAtlas as a custom connector (OAuth) In addition to the `start_session` bearer flow above, the `/mcp` endpoint can be added directly as a custom connector in clients that speak OAuth 2.1 (e.g. the claude.ai connector UI). When enabled, the server advertises: - Protected-resource metadata: `https://simatlas.ru/.well-known/oauth-protected-resource/mcp` - Authorization-server metadata: `https://simatlas.ru/.well-known/oauth-authorization-server` - Dynamic Client Registration (RFC 7591): `POST https://simatlas.ru/oauth/register` - Authorization Code + PKCE (S256 only): `GET https://simatlas.ru/oauth/authorize` - Token + refresh: `POST https://simatlas.ru/oauth/token` - Token revocation (RFC 7009): `POST https://simatlas.ru/oauth/revoke` - A2A Agent Card: `https://simatlas.ru/.well-known/agent-card.json`; its `url` points at the read-only A2A JSON-RPC bridge `POST https://simatlas.ru/a2a` (search/get/list only — ordering and payment are MCP-only). - Agent-skills index: `https://simatlas.ru/.well-known/agent-skills/index.json` (one skill, with an embedded SKILL.md at `/.well-known/agent-skills/simatlas-esim/SKILL.md`). - Agent auth entry point: `https://simatlas.ru/auth.md` (also linked from the AS/PRM metadata as service_documentation / resource_documentation) The flow is auto-consent (no login screen) and anonymous, exactly like `start_session`. Just add `https://simatlas.ru/mcp` as the connector URL; the client discovers the endpoints, registers itself, and obtains a bearer token automatically. After that, all tool calls work the same as documented above. SDK/code clients that don't do OAuth should keep using `start_session`.