MyOTP.App
Give an AI agent the ability to send and verify one-time passcodes over SMS, WhatsApp and Telegram. Works with Claude, Codex, Cursor, and anything else that speaks the Model Context Protocol.
The MCP server is a thin layer over two endpoints. This is the whole round trip, recorded against production:
Send, then verify. return_otp is a testing flag so the round trip completes on screen; in production the code only reaches the handset.
Point your agent at this URL and pass your MyOTP API key as a header. Nothing to install or keep running.
https://mcp.myotp.app/mcp
Every request carries its own X-API-Key, so the hosted server never holds anyone's key. It reads the key per request and forwards the call under it. Authorization: Bearer <key> works too, for clients that can only set a bearer token (Codex is one). Send whichever your client can actually set.
108.61.176.199, not from your
machine. Add that address to your key's allowlist or every call comes back
403. If you would rather not, use the local option below, where calls originate
from your own machine.
Runs on your machine, so calls come from your own IP and your key never leaves it.
npx @myotp/mcp
Use the scoped name. npx myotp-mcp is the binary name, not a package, and does not resolve.
Add to your MCP config, using whichever of the two blocks you want:
{
"mcpServers": {
"myotp": {
"command": "npx",
"args": ["-y", "@myotp/mcp"],
"env": { "MYOTP_API_KEY": "your-32-character-api-key" }
}
}
}
Same shape, in .cursor/mcp.json at your project root.
Codex reads TOML. Add to ~/.codex/config.toml:
[mcp_servers.myotp]
command = "npx"
args = ["-y", "@myotp/mcp"]
[mcp_servers.myotp.env]
MYOTP_API_KEY = "your-32-character-api-key"
Or point Codex at the hosted server instead of launching anything locally. It sends the token as
Authorization: Bearer, which the endpoint accepts:
[mcp_servers.myotp]
url = "https://mcp.myotp.app/mcp"
bearer_token_env_var = "MYOTP_API_KEY"
On older Codex builds that only pick up stdio servers, add
experimental_use_rmcp_client = true above the entry. If you use the hosted URL, the
IP-allowlist note above applies.
Windsurf, Zed, Continue, OpenClaw, Hermes and Grokbot all take the same stdio shape:
npx, ["-y", "@myotp/mcp"], and MYOTP_API_KEY in the
environment, written as JSON or TOML depending on the client. For a hosted client, point it at
https://mcp.myotp.app/mcp with your key in either header.
| Tool | What it does |
|---|---|
| generate_otp | Send a passcode over SMS, WhatsApp or Telegram. Returns a message_id. |
| verify_otp | Check the code the person typed. |
| check_otp_status | Delivery report and whether the code is still live. Useful for debugging. |
| extend_otp | Give someone longer before the code expires. |
| get_usage_report | Transaction history. |
| get_account_info | Account and balance. |
Sign up at myotp.app for 15 free credits, no card. Generate a key in the dashboard, then add the calling IP to that key's allowlist — your own address for the local server, or 108.61.176.199 for the hosted one.
Phone numbers are digits only: no leading +, no trailing national prefix. 19876543210, not +1 (987) 654-3210.
A 403 almost always means the IP allowlist rather than a bad key. A 400 on a number that looks correct usually means there is no priced route to that country on that channel.
If you want delivery status pushed to you instead of polling check_otp_status, register a delivery webhook.