The callback server is what makes this more than a send-and-hope wrapper: Vonage's events land somewhere you can query, so "did that call connect" has an answer. Note the real-world constraint — the callback URL must be reachable from Vonage, so a production deployment needs a public address, and every call and message bills to your Vonage account.
An MCP server that turns a model's decision into a real phone call or text message via Vonage. Two tools do the work, and the project ships a second piece most telephony wrappers omit: a callback server that receives Vonage's event notifications so you can see what happened after the call was placed.
- A voice call placed to a number, with the language and speaking style passed as parameters — the README's own example is asking for a British accent — `voice_call`
- An SMS sent to a number — `send_sms`
- A callback server on port 8080 that receives and stores Vonage voice events fired when a call starts, completes or errors
- Endpoints to work with those events afterwards: `GET /events` lists them with pagination, `GET /events/{event_id}` returns one, `DELETE /events` clears them, and `GET /` is a health check
A Vonage account and four credentials: `VONAGE_API_KEY`, `VONAGE_API_SECRET`, `VONAGE_APPLICATION_ID` and a private key file at `VONAGE_PRIVATE_KEY_PATH`, plus `VONAGE_LVN` for the virtual number you send from. `VONAGE_API_URL` and `VONAGE_SMS_URL` point at the voice and SMS endpoints. `CALLBACK_SERVER_URL` is the address Vonage posts events back to — `http://localhost:8080` in development, and a public URL in production, which is what `ngrok http 8080` is for. Python 3.13+, or `docker compose up --build`.
One command plus a key — docker build -t telephony-mcp-server ., then supply credentials
