Skip to main content

MCP quick-start

The bubbl3 MCP server lets an AI agent send messages, read conversations and contacts, check lines and hand a conversation to a person. It uses the Model Context Protocol over Streamable HTTP.

1. Get a credential​

The server takes the same credentials as the API, as a bearer token:

  • An API key (b3_live_... or b3_test_...), or
  • A service identity: create one under Developers > MCP for each agent. It authenticates with its own linked key, can be limited to some lines and given fewer scopes than that key, and can be disabled on its own. Prefer one identity per agent, so you can see and stop each one.

The agent can do exactly what the credential allows, with the API's permissions, rate limits and sandbox rules. Give it the least it needs:

ToolsScope they need
send_message, reply_to_conversation, handoff_to_humansend
list_conversations, get_conversation, get_message_statusread
search_contacts, get_contact, check_imessage, list_linesread or admin
upsert_contactadmin

Start with a test key: the agent's messages then go to the simulator, never to a real phone.

2. Connect your client​

The server URL is:

https://mcp.bubbl3.com/mcp

Most clients take a JSON configuration like this:

{
"mcpServers": {
"bubbl3": {
"url": "https://mcp.bubbl3.com/mcp",
"headers": { "Authorization": "Bearer b3_test_..." }
}
}
}

The server is stateless: each request carries the bearer token and gets a JSON answer. A request without a key-shaped bearer token gets 401 with WWW-Authenticate: Bearer.

3. Tools and resources​

There are 11 tools and 2 resources. MCP tools lists each tool's input, generated from the same schemas tools/list returns.

ToolWhat it does
send_messageSend to a phone number or contact, with an optional pool and fallback
list_conversationsRecent conversations, filtered by status and assignee
get_conversationThe messages in a conversation
reply_to_conversationReply in an existing conversation
search_contactsSearch by name, phone, email or company
get_contactOne contact, by id or phone
upsert_contactCreate a contact or update the one with that phone number. Never changes consent
check_imessageWhether a number can receive iMessage (cached for 30 days)
list_linesLines with health and the new-contact capacity left today
get_message_statusA message's status and delivery timeline
handoff_to_humanHand the conversation to a person and notify the assigned team
ResourceReads
bubbl3://conversations/{id}A conversation and its messages
bubbl3://contacts/{id}A contact

send_message and reply_to_conversation take an optional idempotency_key, which works like the API's Idempotency-Key header: a retry with the same key returns the first message instead of sending again.

4. The sending rules​

The sending tools' descriptions tell the model these rules, so it doesn't trip the governor. Your own prompts should agree with them:

  • Consent. Never message a contact who opted out. When the workspace requires consent (the require_consent compliance setting), contacts who haven't opted in can't be messaged either. Both calls are refused.
  • Quiet hours. Sends outside 9 AM to 8 PM in the contact's local time (or your workspace's quiet hours) are deferred until the window opens, not refused.
  • First messages. Until a contact replies, messages must be under 300 characters, with no links, media, phone numbers or emails, and at most 3 can be sent.

Lines also have daily and hourly limits on new contacts. list_lines shows the capacity left, and a send over the limit waits for capacity rather than failing.

5. Errors and logging​

An API error comes back as a tool result with isError: true, the error code, the HTTP status and the request_id. The server never retries: the agent decides whether to call again.

Every tool call is logged in your workspace with the tool, the outcome, how long it took and which key or identity made it. Message bodies, phone numbers and credentials aren't stored in that log. See them under Developers > MCP.

6. Handoffs​

When an agent calls handoff_to_human, the conversation is marked for a person, the team is notified, and your agent.handoff webhook fires with reason: "tool" and the agent's note. The note is model-written: treat it as untrusted text.