Skip to main content
Glama
textbee

textbee-mcp

Official

@textbee/mcp

npm version CI license

MCP server for textbee.dev, the open source SMS gateway that turns an Android phone into an SMS API. Gives Claude Desktop, Claude Code, Cursor, and any MCP client the ability to send and read SMS through your own phone and your own number.

Three tools, no per-message markup, works with self-hosted textbee instances.

Setup

You need a textbee account with a paired Android device and an API key from the dashboard. The key has full account access; treat it like a password.

Claude Code

claude mcp add textbee -s user -e TEXTBEE_API_KEY=your-key -- npx -y @textbee/mcp

Claude Desktop

Add to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "textbee": {
      "command": "npx",
      "args": ["-y", "@textbee/mcp"],
      "env": { "TEXTBEE_API_KEY": "your-key" }
    }
  }
}

Cursor

The same object in ~/.cursor/mcp.json.

Slow first start

npx downloads the package on first run. If your client times out waiting, install globally once and point the config at the binary:

npm install -g @textbee/mcp
{ "mcpServers": { "textbee": { "command": "textbee-mcp", "env": { "TEXTBEE_API_KEY": "your-key" } } } }

Related MCP server: commune-mcp

Tools

send_sms

Send an SMS to one or more recipients (E.164 format, for example +15550100123). The sending phone is chosen automatically: your default device, otherwise the enabled device with the most recent heartbeat. Optional device_id, sim_subscription_id, and scheduled_at. Returns an sms_batch_id for delivery checks when the account uses the SMS queue.

get_messages

Read messages across every device on the account. Defaults to received messages, newest first. Filter by direction (received, sent, all), free-text search, sms_batch_id (per-recipient delivery status of a send), device_ids, and a from/to time window. Supports cursor pagination for polling without duplicates or gaps.

list_devices

The phones on the account: ids, enabled state, which one sends by default, last check-in, and message counts.

Self-hosted textbee

Point the server at your own instance:

"env": {
  "TEXTBEE_API_KEY": "your-key",
  "TEXTBEE_BASE_URL": "https://sms.example.com"
}

The /api/v1 suffix is optional and added automatically. Subpath deployments like https://example.com/textbee work too. An invalid URL is an error rather than a silent fallback, so a typo never sends your key to the public API.

Environment variables

Variable

Required

Default

Purpose

TEXTBEE_API_KEY

yes

none

API key from the textbee dashboard

TEXTBEE_BASE_URL

no

https://api.textbee.dev

Your instance's URL when self-hosting

TEXTBEE_TIMEOUT_MS

no

30000

Per-request timeout in milliseconds

Notes

  • Your key stays on your machine: this server talks only to the textbee API at the base URL above.

  • Sends count against your textbee plan quota, and the plan's rate limits apply server-side.

  • All diagnostics go to stderr; stdout is reserved for the MCP protocol.

Using it as a library

The package also exports its tool definitions for embedding in another MCP host (this is how the hosted remote endpoint reuses them):

import { createTextbeeMcpServer, staticCredentials, loadConfig } from '@textbee/mcp'

const server = createTextbeeMcpServer({
  credentials: staticCredentials(loadConfig(process.env)),
})

Credentials are resolved per tool call, so a multi-tenant host can inject a different key per request. See credentialsFromAuthInfoExtra.

License

MIT. Part of the textbee project.

Available Tools

3 tools
get_messagesRead messagesA
Read-only

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoExclusive upper bound, same format as from. Exclusive so consecutive windows never double-count a boundary message.
fromNoInclusive lower bound on when textbee stored the message. ISO 8601 with an explicit timezone, for example 2026-08-20T00:00:00Z.
limitNoMessages per call, 1 to 100. Default 25.
orderNodesc (default) for newest first; asc to walk forward in time when polling.
cursorNoOpaque position from a previous result's next_cursor. Returns messages after that position, with no repeats and no gaps.
searchNoFree text match across the message body and the other party's number. Use this instead of paging when looking for a specific code or keyword. Encrypted messages cannot be searched.
directionNoWhich direction to return. Defaults to "received" ("all" when sms_batch_id is set, since a batch's messages are outbound). "sent" reviews outgoing messages and their delivery status.
device_idsNoOnly messages from these devices. Ids come from list_devices. Omit for every device.
sms_batch_idNoOnly messages from this batch, using the sms_batch_id a send returned. This is how to check a send's delivery: each row carries its status.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already include readOnlyHint=true (the tool is read-only) and openWorldHint=true (results may change between calls). The description goes beyond this by disclosing that reading doesn't consume send quota, that messages have a few seconds of delay, and that 'from' is inclusive while 'to' is exclusive to avoid double-counting. It also mentions that encrypted messages cannot be searched. These behavioral traits are not implied by the annotations and add significant value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but well-organized, opening with the core purpose and then layering usage patterns (defaults, polling, batch checks). It is front-loaded with essential info (no device id needed, direction default) and later details are relevant to specific use cases. It is longer than ideal but every sentence adds value, and the structure helps the agent parse the key information without unnecessary fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (9 parameters, no output schema, no required params), the description is comprehensive: it covers direction semantics, polling mechanics, batch handling, device filtering, and search limitations. The absence of an output schema is partly mitigated by describing what results include (delivery status per row, next_cursor). Minor gaps include not specifying pagination details for direction='all' or explicitly saying that results are ordered, but the overall completeness is strong.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all nine parameters. The description adds crucial semantics beyond the schema: it clarifies the default direction and its rationale, explains that 'from' is inclusive and 'to' is exclusive for boundary handling, and describes the cursor's role in polling. It also integrates parameters like sms_batch_id and device_ids into workflows. The description substantially enhances the agent's understanding, justifying a score above the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads SMS messages from the user's textbee account, covering all devices without needing device IDs. It explicitly contrasts with siblings: it is for reading, not sending (send_sms) or listing devices (list_devices). The scope, direction defaults, and batch filtering are all specified, making its purpose unambiguous and distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides rich usage guidance: it says when to use the default direction 'received' (for replies or one-time codes), when to use 'sent' (reviewing outgoing), and when to use 'all' or 'sms_batch_id' (checking delivery). It describes a complete polling pattern with order, from, and cursor, and explicitly advises waiting and retrying instead of tight-polling. No siblings are alternatives for reading, but the description covers all relevant scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_devicesList devicesA
Read-only

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the description's statement 'sends no SMS' adds behavioral context beyond annotations, reinforcing the read-only nature. It also mentions the details of what is returned (last checked-in time, message counts), which is transparent. No contradiction; the description complements the annotations well. The 4 reflects solid but not exhaustive behavioral detail (e.g., no mention of data freshness).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no fluff, with the purpose and key content in the first sentence and usage triggers in the second. The description is efficiently structured and front-loaded, every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list operation with no parameters and no output schema, the description fully covers what it does, what it returns (list of fields), when to use it, and what it doesn't do (no SMS). An agent has all necessary information to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the baseline is 4. The description explicitly states 'Takes no arguments,' aligning with the empty schema and leaving no ambiguity about parameter expectations. Nothing more is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists Android phones registered to the account, enumerating the specific fields returned (id, name, enabled state, default sender, last check-in, message counts). It uses a specific verb 'list' and a clear resource, distinguishing it from send_sms by explicitly noting it sends no SMS.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use triggers: 'when a send fails with a device error, when the user asks which phone will be used, or when you need a device_id.' It also implies exclusion from sending by stating 'sends no SMS,' giving clear guidance on when not to use it (for sending). This is complete and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_smsSend SMSA

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
messageYesThe SMS body, plain text. Long messages are split into segments by the carrier and each segment counts against the quota; the result reports the segment count.
device_idNoWhich registered phone sends the message. Omit in almost every case and let textbee choose. Pass it only when the user asks for a specific phone. Ids come from list_devices.
recipientsYesPhone numbers in international E.164 format including the country code, for example ["+15550100123"]. Each recipient counts as one message. The plan caps how many recipients one send may have; the server rejects the send beyond it.
scheduled_atNoISO 8601 timestamp to send later instead of now, for example 2026-09-01T14:30:00Z. Must be in the future, and requires the account's server to have queueing enabled. Omit to send immediately.
sim_subscription_idNoWhich SIM sends on a dual-SIM phone. The server does not validate this: a wrong value is silently ignored and the phone default SIM is used. The id is shown in the textbee Android app.

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare openWorld=true and idempotentHint=false, and the description adds real-account consequences (message counts against plan quota), automatic device/account selection, silent SIM id failure, and non-retry advice. It falls slightly short of explaining the strict return/error shape on failure, but on the whole the description adds meaningful context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense but well-structured paragraphs grouped by concern — send/cost, device selection rule, recipients, scheduled send, SIM fallback. Every sentence carries operational value; no filler or repetition despite the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers a surprising amount of edge cases: plan limits, max recipients, quota-capped segments, queue-enabled scheduling, a specific source device, account defaulting, a boolean for queue failure in get_messages, and a full sibling handoff. The only missing piece is what the success response looks like — but the omission is defensible because get_messages is assigned for delivery status.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers 100% of parameters, and the prose substantially raises the bar: E.164 validation, recipients counted as one each, long messages over 1600 chars segmented and each segment counted, omit device_id by default and source it from list_devices, sched_at requires future+queuing, sim_subscription_id silently ignored. This is much more than a restated schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb–object pairing: “Send an SMS” through the user's own textbee account/Android phone. Scope is sharply delimited from siblings: unlike list_devices/get_messages, this sends. Distinctive constraints are stated (E.164 recipients, auto-selected phone, explicit device_id only when the user names a device).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit operational rules: omit device_id in almost every case; pass it only when the user asks for a specific phone; do not speculative-send, do not retry a send that may have succeeded; use sched_at only with queuing, and route batch status to get_messages. No ambiguity about when to use the tool or its siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 3 tool updatesv0.0.2
    • First observedget_messages
    • First observedlist_devices
    • First observedsend_sms

TDQS

A4.7/5.0
Disambiguation5/5

Each tool has a completely distinct purpose: sending SMS, reading messages, and listing devices. The descriptions clearly delineate when to use each, with no overlap in functionality.

Naming Consistency5/5

All three tools follow a consistent verb_noun pattern with snake_case: send_sms, get_messages, list_devices. This makes the API predictable and easy to navigate.

Tool Count5/5

The server is tightly scoped to core SMS operations, and three tools fully cover that scope. Each tool earns its place—there is no redundancy or unnecessary bloat.

Completeness5/5

The tool set covers the essential SMS workflow: sending, reading (including delivery status), and device management. For a narrow SMS gateway, there are no obvious gaps that would hinder an agent.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Give Claude (or any MCP client) a real email inbox and SMS. Your AI agent can read and send email, manage inboxes, track delivery, and handle SMS.
    27
    1
    Apache 2.0
  • A
    license
    B
    quality
    B
    maintenance
    AndroidAPI.net MCP Connector lets Claude send SMS, WhatsApp messages, and OTPs via your linked Android device or gateway credits. Features * 52 tools covering SMS, WhatsApp, OTP, Contacts, Android devices * Works with Claude Desktop and Claude Code * Install: npx -y androidapi-mcp Setup Set ANDROIDAPI_SECRET env var with your API key from AndroidAPI.net → Tools → API Keys
    52
    55
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    MCP server for sending SMS via the SMSPM API. Send transactional SMS from Claude Desktop, Cursor, Windsurf, Cline, or any MCP client.
    1
    48
    MIT

Latest Blog Posts

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/textbee/textbee-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server