Sakari MCP by usefulapi
Manage Sakari SMS contacts, conversations, templates and campaigns, and send texts.
Should I use this
Quality & Safety
Findings (3)
- HIGH
- MEDIUMin sakari_send_message
- INFOin sakari_send_message
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"sakari": {
"url": "https://sakari.usefulapi.io/mcp"
}
}
}Remote endpoints
https://sakari.usefulapi.io/mcpstreamable-httpWhat it can do
Tool inventory
Tools (23)
🟢sakari_get_account
The Sakari account these credentials belong to: name, plan, balance, default country, business info and options. API credentials are never returned. GET /v1/accounts/{accountId}.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_balance
Prepaid balance, default country, remaining segments and the price per segment. GET /v1/accounts/{accountId}/balance.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_contacts(first_name, last_name, mobile, email, tags, ...)
List or search contacts (partial matches on name, mobile or email; filter by tag). GET /v1/accounts/{accountId}/contacts.
Input Schema
{
"type": "object",
"properties": {
"first_name": {
"description": "Filter by first name or part of it.",
"type": "string",
"maxLength": 200
},
"last_name": {
"description": "Filter by last name or part of it.",
"type": "string",
"maxLength": 200
},
"mobile": {
"description": "Filter by mobile number or part of it.",
"type": "string",
"maxLength": 40
},
"email": {
"description": "Filter by email or part of it.",
"type": "string",
"maxLength": 254
},
"tags": {
"description": "Filter by tag(s).",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_contact(contact_id)
One contact by id: name, mobile (with validity and line type), email, lists, attributes, opt-in and blocked state. GET /v1/accounts/{accountId}/contacts/{contactId}.
Input Schema
{
"type": "object",
"properties": {
"contact_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari contact id."
}
},
"required": [
"contact_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴sakari_create_contact(mobile, country, first_name, last_name, email, ...)
WRITE: create a contact. If a contact with the same mobile number exists, merge_strategy decides what happens (append, core or remove, per Sakari). A contact is not opted in to messages by this call. POST /v1/accounts/{accountId}/contacts.
Input Schema
{
"type": "object",
"properties": {
"mobile": {
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$",
"description": "Mobile number in international format, e.g. +13471234567."
},
"country": {
"description": "2-letter country of the number (default: the account's default country).",
"type": "string",
"pattern": "^[A-Za-z]{2}$"
},
"first_name": {
"type": "string",
"maxLength": 200
},
"last_name": {
"type": "string",
"maxLength": 200
},
"email": {
"type": "string",
"maxLength": 254
},
"merge_strategy": {
"description": "How an existing contact with the same mobile is treated.",
"type": "string",
"enum": [
"append",
"core",
"remove"
]
}
},
"required": [
"mobile"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴sakari_update_contact(contact_id, first_name, last_name, email, mobile, ...)
WRITE: change a contact's name, email or mobile. Sakari's update replaces the contact, so this reads the current contact first and sends it back whole (lists, opt-in, blocked, attributes) with only your changes applied. PUT /v1/accounts/{accountId}/contacts/{contactId}.
Input Schema
{
"type": "object",
"properties": {
"contact_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari contact id."
},
"first_name": {
"type": "string",
"maxLength": 200
},
"last_name": {
"type": "string",
"maxLength": 200
},
"email": {
"type": "string",
"maxLength": 254
},
"mobile": {
"description": "New mobile number in international format.",
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$"
},
"country": {
"description": "2-letter country of the mobile number.",
"type": "string",
"pattern": "^[A-Za-z]{2}$"
}
},
"required": [
"contact_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_messages(contact_id, conversation_id, offset, limit)
List messages (sent and received) with status, segments, price and timestamps; filter by contact or conversation. GET /v1/accounts/{accountId}/messages.
Input Schema
{
"type": "object",
"properties": {
"contact_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari contact id."
},
"conversation_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari conversation id."
},
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_message(message_id)
One message by id: text, direction, status, segments, price, error. GET /v1/accounts/{accountId}/messages/{messageId}.
Input Schema
{
"type": "object",
"properties": {
"message_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari message id."
}
},
"required": [
"message_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴sakari_send_message(text, to_numbers, contact_ids, conversation_ids, type, ...)
WRITE: SEND REAL TEXT MESSAGES that cost account balance and cannot be recalled. Recipients: phone numbers (international format), existing contact ids, or conversation ids (max 100 in total). Only text people who opted in; Sakari enforces TCPA/CTIA rules and the sender is responsible. Confirm the recipients and the text with the user first. Placeholders like {{firstName}} are filled per contact. POST /v1/accounts/{accountId}/messages.
Input Schema
{
"type": "object",
"properties": {
"text": {
"type": "string",
"minLength": 1,
"maxLength": 1600,
"description": "Message text (the Sakari 'template')."
},
"to_numbers": {
"description": "Recipient phone numbers in international format.",
"maxItems": 100,
"type": "array",
"items": {
"type": "string",
"pattern": "^\\+[1-9]\\d{6,14}$"
}
},
"contact_ids": {
"description": "Existing Sakari contact ids.",
"maxItems": 100,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari contact id."
}
},
"conversation_ids": {
"description": "Existing conversation ids to reply into.",
"maxItems": 100,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari conversation id."
}
},
"type": {
"description": "SMS (default) or MMS.",
"type": "string",
"enum": [
"SMS",
"MMS"
]
},
"media_urls": {
"description": "Public media URLs to attach (MMS).",
"maxItems": 10,
"type": "array",
"items": {
"type": "string",
"maxLength": 2000,
"format": "uri"
}
},
"confirm_send": {
"type": "boolean",
"const": true,
"description": "Must be true: you confirm the user approved these recipients and this text, and that the texts go out now."
}
},
"required": [
"text",
"confirm_send"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_conversations(offset, limit)
List conversations (the inbox): contact, last message, unread count, open or closed. GET /v1/accounts/{accountId}/conversations.
Input Schema
{
"type": "object",
"properties": {
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_conversation(conversation_id)
One conversation by id. Use sakari_list_messages with conversation_id for its messages. GET /v1/accounts/{accountId}/conversations/{conversationId}.
Input Schema
{
"type": "object",
"properties": {
"conversation_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari conversation id."
}
},
"required": [
"conversation_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🔴sakari_close_conversation(conversation_id)
WRITE: mark a conversation closed in the Sakari inbox (a new inbound message reopens it). PUT /v1/accounts/{accountId}/conversations/{conversationId}/close.
Input Schema
{
"type": "object",
"properties": {
"conversation_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari conversation id."
}
},
"required": [
"conversation_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_templates(name, offset, limit)
List reusable message templates. GET /v1/accounts/{accountId}/templates.
Input Schema
{
"type": "object",
"properties": {
"name": {
"description": "Filter by name or part of it.",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_template(template_id)
One message template by id. GET /v1/accounts/{accountId}/templates/{templateId}.
Input Schema
{
"type": "object",
"properties": {
"template_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari template id."
}
},
"required": [
"template_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟡sakari_create_template(name, text)
WRITE: create a reusable SMS template (does not send anything). POST /v1/accounts/{accountId}/templates.
Input Schema
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Template name."
},
"text": {
"type": "string",
"minLength": 1,
"maxLength": 1600,
"description": "Template text; may contain placeholders such as {{firstName}}."
}
},
"required": [
"name",
"text"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_campaigns(name, offset, limit)
List message campaigns with schedule, template, status and reporting. GET /v1/accounts/{accountId}/campaigns.
Input Schema
{
"type": "object",
"properties": {
"name": {
"description": "Filter by name or part of it.",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_campaign(campaign_id)
One campaign by id. GET /v1/accounts/{accountId}/campaigns/{campaignId}.
Input Schema
{
"type": "object",
"properties": {
"campaign_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari campaign id."
}
},
"required": [
"campaign_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_calls(contact_id, conversation_id, direction, status, from, ...)
Call history (voice) with direction, status, duration and contact; filter by contact, conversation, direction, status or date range. GET /v1/accounts/{accountId}/calls.
Input Schema
{
"type": "object",
"properties": {
"contact_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari contact id."
},
"conversation_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari conversation id."
},
"direction": {
"type": "string",
"enum": [
"inbound",
"outbound"
]
},
"status": {
"type": "string",
"enum": [
"initiated",
"ringing",
"active",
"ended",
"rejected",
"forwarded",
"missed",
"transferring"
]
},
"from": {
"description": "Start of the date range (ISO 8601 date-time).",
"type": "string",
"minLength": 10,
"maxLength": 40
},
"to": {
"description": "End of the date range (ISO 8601 date-time).",
"type": "string",
"minLength": 10,
"maxLength": 40
},
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_get_call(call_id)
One call history record by id. GET /v1/accounts/{accountId}/calls/{callId}.
Input Schema
{
"type": "object",
"properties": {
"call_id": {
"type": "string",
"minLength": 1,
"maxLength": 128,
"description": "Sakari call id."
}
},
"required": [
"call_id"
],
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_links(q)
Shortened tracked links with destination, short URL and click stats. GET /v1/accounts/{accountId}/links.
Input Schema
{
"type": "object",
"properties": {
"q": {
"description": "Search term across link fields.",
"type": "string",
"maxLength": 200
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_forms(q, offset, limit)
Lead capture forms with active state, impressions and conversions. GET /v1/accounts/{accountId}/forms.
Input Schema
{
"type": "object",
"properties": {
"q": {
"description": "Search term across form fields.",
"type": "string",
"maxLength": 200
},
"offset": {
"description": "Results to skip (default 0). Pass the previous reply's next_offset.",
"type": "integer",
"minimum": 0,
"maximum": 10000000
},
"limit": {
"description": "Results per page, 1-100 (default 25).",
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_webhooks
Active webhook subscriptions (message event notifications). GET /v1/accounts/{accountId}/webhooks.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}🟢sakari_list_autoresponders
Autoresponders (automatic replies) configured on the account. GET /v1/accounts/{accountId}/autoresponders.
Input Schema
{
"type": "object",
"properties": {},
"$schema": "https://json-schema.org/draft/2020-12/schema"
}Community
Evidence