MCP server for textbee.dev. Give your AI agent a phone number: send and read SMS through your own Android phone.
Three well-defined tools with excellent descriptions, comprehensive parameter schemas, and clear error guidance. All tools have descriptive names starting with action verbs (send_, get_, list_). Descriptions are LLM-optimized (150 - 400 chars), explaining WHAT the tool does, WHEN to use it, and key constraints. Input schemas use Zod with proper type definitions and constraints. Output schemas are implicitly documented through descriptions (messages with delivery status, device lists). Error handling is present with recovery guidance (e.g., 'call list_devices when send fails with device error'). Tool composition is clean: each tool has one responsibility, and outputs chain properly (sms_batch_id from send_sms feeds into get_messages). Risk annotations (DESTRUCTIVE, READ_ONLY) are present and correct. Main gap: output schema structures are not formally documented in JSON Schema; they are inferred from description text and must be reverse-engineered from the API response format (format.ts). This is acceptable but not A+ grade.
Read the SMS messages on the user's textbee account, covering every device, no device id needed. direction defaults to "received": checking for a reply or a one-time code is the usual case. Pass direction "sent" to review what went out (each row carries its delivery status), or "all" for a conversation in order. Pass the sms_batch_id from a send to see that send's per-recipient delivery status. To poll for new messages without missing or repeating any: use order "asc" with a from bound, then keep calling with the next_cursor each result prints. from is inclusive and to is exclusive, so consecutive windows tile exactly. Reading does not consume the plan send quota. Messages reach textbee within a few seconds of arriving on the phone, so when waiting for a code, wait briefly and call again rather than tight-polling.
List the Android phones registered to this textbee account: id, name, enabled state, which one is the default sender, when each last checked in, and message counts. Call this when a send fails with a device error, when the user asks which phone will be used, or when you need a device_id. Takes no arguments and sends no SMS.
Send an SMS through the user's own textbee account and Android phone. Recipients must be in international E.164 format such as +15550100123. The sending phone is chosen automatically: the account default device, otherwise the enabled device with the most recent heartbeat. Only pass device_id when the user explicitly names a phone; ids come from list_devices. Sending costs the user a real message against their textbee plan quota, so do not send speculatively and do not retry a send that may already have gone out. When the account has SMS queueing enabled the result includes an sms_batch_id; pass it to get_messages as sms_batch_id to check per-recipient delivery status.
Output schemas not formally documented. Response structures inferred from descriptions and format.ts, not declared as JSON Schema. LLMs cannot know exact fields, types, and constraints of returned messages or devices without inspecting implementation code.
send_sms parameter 'sim_subscription_id' documented as 'server does not validate this: a wrong value is silently ignored.' Silent failure violates pattern:error-classification, should either validate and return 'invalid SIM ID' error with guidance, or accept and echo back the chosen SIM to confirm.
get_messages 'search' parameter lacks case-sensitivity and regex behavior documentation. LLMs will guess whether 'search' is case-sensitive, exact match, or substring. Should clarify: 'Case-insensitive substring search across message body and sender number.'
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | B | 71 | 2026-07-28+ | v2 |