{
 "openapi": "3.1.0",
 "info": {
  "title": "eSIM-Global.VIP eSIM Catalog",
  "version": "2.0.5",
  "summary": "Prepaid travel eSIM data plans for 200+ countries.",
  "description": "Prepaid travel eSIM data plans for 200+ countries from eSIM-Global.VIP. Search by destination (any language, one country or several, or a region), get every plan fact the catalogue holds \u2014 coverage with networks per country, data and speed rules, activation and validity rules, hotspot / APN / registration facts, top-up, refund rule, price with its basis \u2014 let the server recommend plans for a whole trip, read the shop's own facts (delivery, payment, guarantee, support, devices) and hand the customer a direct buy link. Three plan shapes: Data Pack (a fixed amount of data over a validity window), Unlimited Flex (priced per day - the customer chooses the duration at checkout within the plan's day range - with a daily high-speed allowance that continues at reduced speed) and Daily Pack (a set number of days, each with its own high-speed allowance).\n\n## This is an MCP server, not a REST API\n\nEvery call is `POST /mcp` with a JSON-RPC 2.0 body. The path never changes \u2014 only the body does. Transport is MCP streamable-HTTP, protocol version `2025-06-18`. Server version 2.0.5.\n\n### Call order\n\n1. `POST /mcp` with `method: \"initialize\"`. The response carries an **`Mcp-Session-Id`** response header and the server instructions (read them \u2014 they carry the pricing and presentation rules).\n2. `POST /mcp` with `method: \"notifications/initialized\"` and that header. Returns 202 with an empty body \u2014 it is a notification, so no JSON-RPC result comes back.\n3. Every later request repeats the `Mcp-Session-Id` header.\n\nThe server also answers a `tools/call` without the handshake (the session id is advisory, never enforced) \u2014 the handshake is still the correct order because it delivers the instructions.\n\n### Reading errors correctly\n\nJSON-RPC errors are returned with **HTTP 200** and an `error` object in the body. This is what the JSON-RPC 2.0 and MCP specifications require, and it is deliberate. Do not treat a 200 as success without checking that `result` is present and `error` is absent. A tool that cannot fulfil a request (unknown plan, unknown destination, missing argument) answers with `result.isError: true` and a `structuredContent.code` such as `not_found`, `unknown_destination` or `invalid_argument`. A body that is not valid JSON at all returns HTTP 400. `GET /mcp` returns 405: this server implements streamable-HTTP without an SSE stream, so refusing GET is correct.\n\n### Results\n\nEvery tool result carries `structuredContent` (the JSON object) and the same JSON as text in `content[0].text`. Plans carry only the facts the catalogue holds \u2014 an absent field is unknown, never to be inferred. `coverage_countries` lists every country a plan works in (ISO code, name, network operators where known); `covers_via` marks a multi-country plan returned for a single-country search.\n\n### Prices\n\n`price` must be read with `price_basis`. `total` (Data Pack, Daily Pack): the full price of the plan. `per_day` (Unlimited Flex): the price of ONE day - the customer picks the duration at checkout within `days_range`, longer durations are discounted, and `price_max` is the price for the longest duration with the discount applied; `start_checkout` with `days` returns `total_for_days`, `recommend_plan` returns `total_for_trip`. Never present a per-day price as the price of the plan. Prices are quoted in `pricing_bucket` (language-region, default en-us / USD); pass `bucket` or `currency` to quote in the customer's own.\n\n### Limits and safety\n\nRate limit: 60 requests per minute per session and 120 per IP for unrecognised clients (recognised assistants: 120 per session, 480 per IP); exceeding it returns 429 by design. No authentication, no API key, no account \u2014 the endpoint is public and read-only. `start_checkout` only returns a `buy_url`; it takes no payment and creates no order, so every tool here is safe to call in a test run. Prices and availability are live, so exact values change between calls \u2014 assert on shape, not on specific prices.\n\n",
  "contact": {
   "name": "IbiPoint Ltd",
   "url": "https://esim-global.vip/esimshop/",
   "email": "contact@esim-global.vip"
  },
  "x-mcp": {
   "endpoint": "https://esim-global.vip/esimshop/wp-json/esimglobal/mcp",
   "transport": "streamable-http",
   "protocolVersion": "2025-06-18",
   "serverCard": "https://esim-global.vip/.well-known/mcp/server-card.json",
   "llms": "https://esim-global.vip/llms.txt"
  }
 },
 "servers": [
  {
   "url": "https://esim-global.vip/esimshop/wp-json/esimglobal",
   "description": "eSIM-Global.VIP MCP server (public, no auth)"
  }
 ],
 "externalDocs": {
  "description": "Plain-language guide for LLM agents",
  "url": "https://esim-global.vip/llms.txt"
 },
 "paths": {
  "/mcp": {
   "post": {
    "operationId": "mcpCall",
    "summary": "MCP JSON-RPC 2.0 endpoint \u2014 handshake, tools/list, tools/call, resources, prompts",
    "description": "All MCP traffic goes here. Pick the request body from the examples; they are in call order. Send Mcp-Session-Id on every call after initialize.",
    "parameters": [
     {
      "name": "Mcp-Session-Id",
      "in": "header",
      "required": false,
      "schema": {
       "type": "string",
       "format": "uuid"
      },
      "description": "Returned by initialize as a response header. Repeat it on every subsequent request. Omit it only on the initialize call itself."
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/JsonRpcRequest"
       },
       "examples": {
        "1_initialize": {
         "summary": "Step 1 \u2014 handshake (must be first)",
         "value": {
          "jsonrpc": "2.0",
          "id": 1,
          "method": "initialize",
          "params": {
           "protocolVersion": "2025-06-18",
           "capabilities": {},
           "clientInfo": {
            "name": "your-agent",
            "version": "1.0"
           }
          }
         }
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "JsonRpcRequest": {
    "type": "object",
    "description": "Referenced by this document but never defined in it. API Evangelist added this empty placeholder so the document resolves; the shape is unknown and is NOT a claim about the API.",
    "x-ae-placeholder": true
   }
  }
 },
 "security": []
}