SMS.ir MCP server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@SMS.ir MCP serverWhat's my current SMS credit?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
SMS.ir MCP server
A local Model Context Protocol server that exposes a curated, safety-gated set of tools for the SMS.ir Panel V2 API. Built with Python + FastMCP.
stdio transport for Codex / Claude Desktop / Claude Code
streamable HTTP transport for local development and testing
Read operations work out of the box; every send is billable and blocked by default behind a confirmation flag and a server-side kill switch.
Phone numbers, message text, API keys and OTP codes are masked in logs.
Built from the SMS.ir Panel V2 Postman collection (not included in this repo —
it embeds a real API key). The normalized API description lives in
docs/API.md and docs/openapi.yaml.
1. Setup
Requires Python 3.10+ (developed and tested on CPython 3.12).
cd C:\Users\Kasra\Documents\sms.ir-mcp
# create the project-local virtual environment
py -3.12 -m venv .venv
# install runtime deps (pinned)
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
# ...or install with the package + dev/test extras
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"Related MCP server: SOLAPI MCP Server
2. Configuration
All configuration comes from environment variables. For local use, copy the example env file and fill it in — it is git-ignored and never committed:
copy .env.example .env
notepad .envVariable | Required | Default | Purpose |
| yes | – | SMS.ir Panel API key, sent as the |
| no | – | Fallback sender line for send tools |
| no |
| Kill switch. Must be |
| no |
| API base URL (host-allowlisted) |
| no |
| Allow a non- |
| no |
| Per-request timeout |
| no |
| Retries for transient failures (429 / 5xx / network) |
| no |
| Client-side rate limit |
| no |
| Upper bound accepted for |
| no |
|
|
| no |
| Path to the env file to auto-load |
Real environment variables always override values from the env file.
3. Running
# stdio (what MCP clients launch)
.\.venv\Scripts\python.exe -m sms_ir_mcp --transport stdio
# streamable HTTP for local testing (http://127.0.0.1:8000/mcp)
.\.venv\Scripts\python.exe -m sms_ir_mcp --transport http --host 127.0.0.1 --port 8000For a quick connectivity + auth check that never spends credit, call the
health_check tool (or get_balance) from any connected client — both are
GET /v1/credit under the hood.
4. Tools
Read-only tools are always available. Write tools require confirm=true
and SMSIR_ALLOW_SEND=true; the destructive tool requires confirm=true.
Tool | Kind | API | Description |
| read |
| Remaining SMS credit |
| read |
| Sender line numbers / virtual numbers |
| read |
| Delivery report/status for one sent message |
| read |
| Per-recipient results for a bulk pack (paginated) |
| read |
| Sent messages, |
| read |
| Bulk packs, |
| read |
| Inbound messages, |
| read |
| Newest inbound message containing a parseable one-time code (heuristic) |
| read |
| Reachability + auth check, never billable; also returns effective config |
| admin | – | Re-read |
| billable |
| One text to one or more recipients |
| billable |
| Templated OTP/verification message |
| billable |
| A distinct text per recipient |
| destructive |
| Cancel a not-yet-sent scheduled pack |
Every tool returns {"ok": true, "data": …, …} on success or
{"ok": false, "error": {"code": …, "message": …}} on failure. Error codes:
config_error, validation_error, confirmation_required, send_disabled,
auth_error, rate_limited, transient_error, api_error, internal_error.
Examples
// check balance
get_balance() -> {"ok": true, "data": {"credit": 45210}}
// read the latest OTP received on a given number
extract_latest_otp({"mobile": "9821000"})
-> {"ok": true, "data": {"otp": "834122", "matched": true, "from": "*****1000", ...}}
// attempt a send without confirming -> refused, nothing sent
send_sms({"message_text": "Hi", "mobiles": ["09121234567"]})
-> {"ok": false, "error": {"code": "confirmation_required", ...}}
// confirmed send, but kill switch still off -> refused, nothing sent
send_sms({"message_text": "Hi", "mobiles": ["09121234567"], "confirm": true})
-> {"ok": false, "error": {"code": "send_disabled", ...}}
// edited .env to set SMSIR_ALLOW_SEND=true -> apply it without restarting
reload_config()
-> {"ok": true, "data": {"config": {"allow_send": true, ...}, "changed": ["allow_send"]}}
// with SMSIR_ALLOW_SEND=true AND confirm=true -> actually sends (billable)
send_sms({"message_text": "Hi", "mobiles": ["09121234567"],
"line_number": "30007732000000", "confirm": true})
-> {"ok": true, "data": {"packId": "…", "messageIds": [123], "cost": 1.0}, "recipients": 1}5. Safety model
Billable operations (
send_sms,send_verification_code,send_personalized_sms) need both:confirm=truein the tool call, andSMSIR_ALLOW_SEND=truein the server environment. With the kill switch off, a confirmed call still sends nothing.
Destructive operation (
cancel_scheduled_send) needsconfirm=true.No arbitrary base URLs: only
api.sms.iris accepted unlessSMSIR_ALLOW_CUSTOM_BASE_URL=true. HTTPS is enforced.No header injection: callers cannot set request headers; only typed, validated fields are forwarded.
Timeouts + bounded retries + client-side rate limiting on every request.
Masking: API keys, phone numbers, message bodies and OTP values are masked in log output.
No admin endpoints: only the operations in the Postman collection are exposed; nothing for account/config management.
6. Client registration
Your real API key goes in .env in this folder — never in a client config
file. Each config below only points the client at this server and its .env.
Codex CLI (installed)
codex mcp add sms-ir `
--env SMSIR_ENV_FILE=C:\Users\Kasra\Documents\sms.ir-mcp\.env `
-- C:\Users\Kasra\Documents\sms.ir-mcp\.venv\Scripts\python.exe -m sms_ir_mcp --transport stdio
codex mcp list # sms-ir should appear
codex mcp get sms-irManual equivalent: docs/codex_config.example.toml.
Claude Code (installed)
This repo ships a project-scoped .mcp.json. Open Claude Code in
this directory and approve the sms-ir server when prompted:
cd C:\Users\Kasra\Documents\sms.ir-mcp
claude
/mcp # shows sms-ir and its toolsTo register it at user scope instead:
claude mcp add sms-ir --scope user `
--env SMSIR_ENV_FILE=C:\Users\Kasra\Documents\sms.ir-mcp\.env `
-- C:\Users\Kasra\Documents\sms.ir-mcp\.venv\Scripts\python.exe -m sms_ir_mcp --transport stdioClaude Desktop (not installed)
When installed, merge docs/claude_desktop_config.example.json
into %APPDATA%\Claude\claude_desktop_config.json (back it up first; keep other
servers).
7. Development
.\.venv\Scripts\python.exe -m ruff check src tests
.\.venv\Scripts\python.exe -m ruff format --check src tests
.\.venv\Scripts\python.exe -m pytestTests cover request construction, auth header, envelope parsing, error normalization, retries/rate-limiting, argument validation, masking, OTP extraction, mocked integration for every tool (using the Postman example payloads), OpenAPI-vs-collection consistency, and MCP tool discovery.
8. First live test (after you provide a credential)
Nothing in this repo has made a billable call. To run the first real send, which you explicitly authorize:
Put your key in
.env:SMSIR_API_KEY=<your real key> SMSIR_DEFAULT_LINE_NUMBER=<your approved line> SMSIR_ALLOW_SEND=trueVerify connectivity without spending anything — from a connected client call
health_check(orget_balance).Then, and only then, make the first billable call. Exact tool call:
send_sms({ "message_text": "SMS.ir MCP test", "mobiles": ["<your own mobile>"], "line_number": "<your approved line>", "confirm": true })Codex phrasing: "Use the sms-ir server's send_sms tool to send 'SMS.ir MCP test' to from line , with confirm true."
9. Troubleshooting
Symptom | Cause / fix |
| No key in env or |
| Wrong/rotated key, or key lacks Panel API access |
|
|
Edited | The server reads config once at startup. Call |
| Re-call the tool with |
| Use 10–15 digits, optional leading |
| Client-side limiter tripped; raise |
| Network/5xx after retries; check connectivity and SMS.ir status |
Client shows no tools | Wrong |
| SMS.ir rejected the request; |
This server cannot be deployed
Maintenance
Related MCP Connectors
- SureSMSOAuthcom.suresms
Send SMS, manage contacts and groups, and read delivery reports. OAuth 2.1 SureSMS login.
Send and schedule SMS and WhatsApp messages, manage contacts and templates, and track delivery.
Send and verify one-time passcodes over SMS, WhatsApp and Telegram.
One API, all things verified — control, delegation, human approval, anti-impersonation.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables sending SMS, querying delivery reports, and managing senders and blacklists through the iletiMerkezi SMS API.118 npm2MIT

SOLAPI MCP Serverofficial
AlicenseNot gradedqualityCmaintenanceEnables searching SOLAPI documentation and examples, and sending/managing SMS, LMS, MMS, RCS, and Kakao messages with safety guards.129 npmMIT- AlicenseAqualityAmaintenanceEnables MCP clients to read Instantly.ai analytics and manage leads, campaigns, Unibox, sender accounts, blocklist, and webhooks, with write actions gated behind confirm prompts and configurable safety policies.4056 PyPIMIT
- AlicenseAqualityCmaintenanceEnables policy-aware access to the Productive.io API v2 for managing projects, tasks, time tracking, resource planning, financials, CRM, and reports, with safe defaults and staged writes for sensitive operations.12Apache 2.0