eSIM MCP Server
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ESIM_MCP_HOST | No | HTTP transport bind host. Defaults to 127.0.0.1, use 0.0.0.0 when deployed. | 127.0.0.1 |
| ESIM_MCP_PORT | No | HTTP transport bind port. Defaults to 8080, falls back to platform PORT. | 8080 |
| ESIM_API_BASE_URL | Yes | Required. Backend base URL without /api/v1. https in production. | |
| ESIM_MCP_LOG_LEVEL | No | Log level: DEBUG…CRITICAL. Defaults to INFO. | INFO |
| ESIM_MCP_TRANSPORT | No | Transport: stdio or streamable-http. Defaults to stdio. | stdio |
| ESIM_MCP_ENVIRONMENT | No | Environment mode: local, development, qa, staging, production. Defaults to local. | local |
| ESIM_MCP_POOL_TIMEOUT | No | Pool timeout in seconds. Defaults to 5. | 5 |
| ESIM_MCP_READ_TIMEOUT | No | Read timeout in seconds. Defaults to 20. | 20 |
| ESIM_MCP_DEV_CLIENT_ID | No | stdio/dev identity; ignored in production. Defaults to local-dev-client. | local-dev-client |
| ESIM_MCP_WRITE_TIMEOUT | No | Write timeout in seconds. Defaults to 20. | 20 |
| ESIM_MCP_DEFAULT_LOCALE | No | Sent as Accept-Language. Defaults to en. | en |
| ESIM_MCP_DEVICE_ID_SALT | No | Required in production, >= 32 chars. Ephemeral outside production. | |
| ESIM_MCP_CONNECT_TIMEOUT | No | Connect timeout in seconds. Defaults to 5. | 5 |
| ESIM_MCP_DEFAULT_CURRENCY | No | Sent as X-Currency. Defaults to USD. | USD |
| ESIM_MCP_MAX_ACTIVE_QUOTES_PER_USER | No | Simultaneous prepared quotes per user (1…50). Defaults to 5. | 5 |
| ESIM_MCP_PURCHASE_QUOTE_TTL_SECONDS | No | Prepared-quote lifetime in seconds (30…1800). Defaults to 300. | 300 |
| ESIM_MCP_LOGIN_CHALLENGE_TTL_SECONDS | No | Pending-OTP lifetime in seconds. Defaults to 300. | 300 |
| ESIM_MCP_TOKEN_REFRESH_WINDOW_SECONDS | No | Refresh this long before expiry. Defaults to 120. | 120 |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| request_login_otpA | Start login: ask the eSIM platform to send a six-digit one-time code to the user's email address or phone number. WHEN: the user wants to log in or sign in, or something you are about to do needs a signed-in user and get_login_status reports nobody is signed in. FIRST: ask the user which email address or phone number to use if they have not said yet. Pass exactly one of them, exactly as the user gave it. Never invent, guess or auto-complete an address or number. AFTER SUCCESS: tell the user that a code was sent to the masked destination in the result and ask them to read out the six-digit code, then call verify_login_otp. The user is NOT logged in yet -- do not say login is complete. DO NOT call this tool again for the same login attempt; it is rate limited. If the user says the code never arrived, use resend_login_otp. |
| resend_login_otpA | Send the pending one-time code again, to the same destination as the login already in progress. WHEN: only when the user explicitly asks for another code ("resend it", "I never got it"). Pass the same email or phone that started the login. DO NOT call this on your own after a wrong or expired code, and do not use it to retry a failed request_login_otp. If the platform reports that a code is still active or that the limit was reached, tell the user plainly and wait -- do not call it again. |
| verify_login_otpA | Finish login: verify the six-digit code the user received and open their eSIM session. WHEN: the user has given you a six-digit code for a login you started with request_login_otp. Pass that code together with the same email or phone the code was sent to. AFTER SUCCESS (status 'authenticated'): tell the user they are signed in. The session is kept on this server for this client; you never see, need or handle any token. DO NOT ask the user for an access token, a refresh token or a password, and do not retry a rejected code by yourself -- ask the user to re-read it, or to ask for a new one. |
| get_login_statusA | Check whether this client already has a signed-in eSIM user. Local and fast: it does not call the eSIM platform. WHEN: before anything that needs a signed-in user, and whenever the user asks whether they are logged in. If 'authenticated' is true, carry on -- do not ask the user to log in again. If the result shows a pending login, ask the user for the six-digit code instead of starting a new login. |
| get_user_profileA | Read the signed-in user's own profile and wallet balance from the eSIM platform. WHEN: the user asks about their account, profile, name or balance -- and only while they are signed in. If this answers 'authentication_required', start the login flow with request_login_otp instead of asking the user for any credential. Contact details come back masked; tokens and internal session data are never included, so do not ask for or expect them. PRIVACY: repeat the masked email and phone exactly as returned. Never restore or retype the complete address or number, not even when the user typed it earlier in this conversation -- say 'your email' or the masked form instead. |
| logoutA | Sign the current user out of the eSIM platform, for this client only. WHEN: only when the user explicitly asks to log out or sign out. DO NOT log anyone out on your own -- not after an error, not to 'reset' things, not at the end of a conversation. Other clients and other users are unaffected. |
| list_countriesA | List the countries the eSIM platform sells plans for, or check the one the user named. WHEN: the user asks which destinations are available, or you want to confirm a country exists before searching for plans. Pass the user's own wording as 'query' to resolve it; omit 'query' to browse. The result is deliberately a limited extract plus a total count -- do not read the whole list out, ask the user where they are travelling. This needs no login. |
| list_regionsA | List the regions the eSIM platform sells multi-country plans for, such as Europe. WHEN: the user mentions a region, asks what regional plans exist, or is travelling to several countries in one area. Use a region from this result with find_bundles_by_region. This needs no login. |
| browse_home_catalogA | Show what the catalogue offers: how many destinations and regions exist, plus a few cruise and global plans. WHEN: the user asks something broad like "show me all bundles", "what do you have" or "what plans are there". IMPORTANT: there is no endpoint that returns every plan for every country, so never claim to be showing all of them. Use this overview to say what kinds of plans exist, then ask which country or region the user is travelling to, or whether they want a global or cruise plan. This needs no login. |
| find_bundles_by_countryA | Find the eSIM plans available for one country. WHEN: the user names a destination country -- "I need an eSIM for France". Pass the country exactly as the user said it (name, ISO2 or ISO3); this tool resolves it against the platform's own list. Only pass a filter the user actually stated (budget, minimum data, minimum validity, unlimited). AFTER SUCCESS: present a few options as a numbered list with data, validity and price, and ask whether the user wants details on one of them. Keep the bundle_code of each option so that "the second one" can be looked up with get_bundle_details; never read a code out to the user and never invent one. The result covers this destination only -- never describe it as the platform's whole catalogue. Prices are catalogue prices and may not include final tax. This needs no login; browsing must never be blocked behind signing in. |
| find_bundles_by_regionA | Find the multi-country eSIM plans available for one region, such as Europe. WHEN: the user names a region, or is visiting several countries in the same area. Pass the region as the user said it (name or code); this tool resolves it against the platform's own region list. Filters and presentation work exactly as in find_bundles_by_country: only pass filters the user stated, then offer a short numbered list and keep each bundle_code for follow-up. The result covers this region only. This needs no login. |
| list_cruise_bundlesA | List the eSIM plans sold for cruise ships. WHEN: the user says they are going on a cruise, names a ship or a cruise line, or asks for maritime coverage. Each plan covers specific ships; the summary carries how many, and get_bundle_details names them. If the user has a particular ship in mind, check it there before promising coverage. This needs no login. |
| get_bundle_detailsA | Read the full details of one plan: data, validity, price, coverage, plan type, activation policy and availability. WHEN: the user asks about a specific plan you already listed -- "tell me more about the second one". Pass the bundle_code of the option the user picked, taken from the result you already have. Never invent a code, and never ask the user to read one out. AFTER SUCCESS: describe the plan in ordinary language and pass on the price note: the displayed catalogue price may not include final tax. Nothing here reserves, orders or charges anything -- this version cannot buy a plan. This needs no login. |
| prepare_purchaseA | Prepare a signed-in user's chosen plan for buying, and report exactly what it would cost. This does NOT buy anything: it creates no order, moves no money, and reserves nothing. WHEN: a signed-in user has picked a real plan from a list you showed and wants to go ahead -- "I want the second one", "prepare the cheapest France plan". FIRST: the user must be signed in. Check get_login_status and run the normal login conversation if they are not. Then ask whether they want to use their wallet balance or a card, and pass their answer -- never pick for them. Pass the bundle_code of the plan they chose, taken from the catalogue result you already have. Never invent a code and never ask the user for one. If it is unclear which plan they mean, ask them which one before calling this. The plan's price, availability and the wallet balance are all re-read from the platform here, so you cannot supply them and must not assume them. AFTER SUCCESS: tell the user the plan, the amount and the payment method, and say plainly that no order was created and nothing was charged. Never say the plan is reserved, held or bought. Do not ask for card details. Do not call this again for the same choice -- if you do, the earlier quote is replaced. Preparing is not paying, and this tool cannot take a payment of either kind. Only once the user has heard the amount and explicitly agreed to it does paying begin: confirm_purchase for a Wallet quote, create_card_checkout for a Card quote. Never start either on your own initiative. |
| get_prepared_purchaseA | Read back a quote you prepared earlier in this conversation: the plan, the amount, the payment method and whether it is still valid. WHEN: the user asks about what you prepared -- "show me my prepared purchase", "what was that going to cost". Pass the quote reference from the prepare_purchase result. This reads local state only and never contacts the eSIM platform, so it changes nothing. A quote is short-lived. If the result says it expired or was cancelled, say so plainly and offer to prepare the plan again -- and repeat that no order was created and nothing was charged. |
| cancel_prepared_purchaseA | Throw away a quote you prepared earlier. This discards local information only. WHEN: the user says they do not want the plan you prepared, or wants to start again. IMPORTANT: there is no order behind a prepared quote, so nothing is cancelled at the eSIM platform and nothing is refunded or reversed -- there was never a charge. Tell the user the prepared quote was discarded; never tell them an order was cancelled. This never contacts the eSIM platform. |
| confirm_purchaseA | Buy the plan in a quote you prepared earlier, paying from the user's eSIM wallet. THIS SPENDS REAL MONEY: it creates an order at the eSIM platform and debits the wallet balance. It cannot be undone from here, and there is no refund tool. WHEN: only after the user has been told the plan, the exact amount and the payment method, and has explicitly said yes to that amount -- "yes, buy it", "confirm", "go ahead". Never call this on your own initiative, never to "check" something, and never because the user merely asked to prepare or price a plan. Wanting a quote is not agreeing to be charged. FIRST: prepare the plan with prepare_purchase, read the amount back to the user, and wait for their answer. If the quote has expired, prepare it again and get their agreement to the new amount -- never confirm an amount they have not heard. Pass only the quote reference from your own prepare_purchase result. The plan, the price, the currency and the payment method come from that stored quote, so you cannot supply or change any of them here. Wallet only in this version. A quote prepared for card payment cannot be bought. SAFE TO REPEAT: calling this twice with the same quote reference returns the stored result of the first purchase and never buys the plan twice. AFTER SUCCESS: tell the user plainly that the plan was bought and paid for from their wallet, with the plan name and the amount. IF THE RESULT IS UNCLEAR: if the outcome is reported as unknown or as needing support, never say the purchase succeeded and never say it failed. Do not prepare a new quote for the same plan and do not try to buy it again -- say the platform is confirming it, and offer to check the same purchase again. |
| create_card_checkoutA | Open the eSIM platform's secure hosted checkout page for a plan the user prepared for card payment, and return the payment link. THIS CHARGES NOTHING BY ITSELF: it creates a payment page, and the user pays on that page or does not. WHEN: only after the user has been told the plan, the exact amount and the payment method, and has explicitly said yes to paying that amount by card -- "yes, pay by card", "open the payment page", "go ahead". Never call this on your own initiative, and never because the user merely asked to prepare or price a plan. Wanting a quote is not agreeing to pay. FIRST: the user must be signed in, and the plan must already be prepared with prepare_purchase for 'Card'. Read the amount back to them and wait for their answer. If the quote has expired, prepare it again and get their agreement to the new amount -- never start a payment for an amount they have not heard. Pass only the quote reference from your own prepare_purchase result. The plan, the price, the currency and the payment method come from that stored quote, so you cannot supply or change any of them here. NEVER ask the user for a card number, an expiry date, a security code, a cardholder name or any other card detail, and never offer to enter one for them. Card details are entered only on Stripe's own secure hosted page, which the returned link opens in the user's own browser. This server never sees a card. SAFE TO REPEAT: calling this twice for the same prepared quote returns the same payment link and never opens a second page, so the user is never asked to pay twice. AFTER SUCCESS: give the user the link, the plan and the amount, and say plainly that nothing has been charged yet. Then wait -- do not check the payment until they say they have paid or ask you to check, and use check_card_payment_status when they do. |
| check_card_payment_statusA | Ask the eSIM platform what happened to a card payment you started with create_card_checkout. This is the ONLY way to know whether a card payment went through: the platform's own payment webhook confirms the payment and sets up the eSIM, and this tool reads the result of that. Nothing here can make a payment succeed. WHEN: the user says they have paid, or asks you to check. Do not call it on a loop and do not keep checking on your own -- one check per request, and only when there is a reason to. NEVER treat any of these as proof of payment: the user returning to this conversation, a browser redirect, a success screen on the payment page, or the user simply saying it worked. Only this tool's answer counts, and there is no argument here through which you could tell it that a payment succeeded. The answer means exactly what it says:
|
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/samah-jamal-monty/esim-opensource-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server