MCP server
Connect AI apps and agents to CommSync over the Model Context Protocol — every inbox, contact, label, and channel action available as a tool. Sign in with OAuth, or use an API key.
CommSync speaks the Model Context Protocol. Point an MCP-capable app or agent at the endpoint. It can then read threads, send messages, manage contacts and labels, and more.
There are two ways to authenticate, and both reach the same tools:
- OAuth 2.1 is the primary way. The app signs you in with no shared secret. See Connect AI apps.
- An API key is the alternative for scripts and servers. Send it as a Bearer token. See API keys.
OAuth is how Claude, ChatGPT, Codex, Cursor, and VS Code connect.
The signed-in user and their org role scope every operation.
Looking for the machine-readable version?
Agents can fetch /docs/mcp.txt for the same catalog as plain text with full parameter details — one request, no scraping.
Connect
The server is a single stateless HTTP endpoint. To connect an AI app, paste the endpoint URL into the app and sign in. The Connect AI apps page has a guide for each app.
To call the endpoint from your own code with an API key:
Mint an API key
In CommSync, open Settings → API Keys and create a key. CommSync shows it once — store it securely. See API keys.
Call the endpoint
POST JSON-RPC to the /api/mcp route on your CommSync API origin.
curl -X POST "$COMMSYNC_API/api/mcp" \
-H "Authorization: Bearer csk_your_api_key" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Call a tool
Use tools/call with the tool name and its arguments.
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": { "name": "list_threads", "arguments": { "limit": 20 } }
}| Endpoint | POST /api/mcp (on your CommSync API origin) |
| Transport | HTTP, stateless — one request per call |
| Auth | OAuth 2.1 access token, or Authorization: Bearer csk_… |
Authentication
OAuth 2.1
CommSync is its own authorization server. A client needs only the endpoint URL, because it discovers everything else:
- A request with no token gets
401and aWWW-Authenticateheader. The header names the protected-resource metadata (/.well-known/oauth-protected-resource/api/mcp, RFC 9728). - That document names the authorization server. Its metadata is at
/.well-known/oauth-authorization-server(RFC 8414). - The client registers, sends you to the consent screen, and exchanges the code for tokens.
| Grant | Authorization code with PKCE (S256 only) |
| Client registration | Dynamic registration at POST /oauth/register (RFC 7591), or a Client ID Metadata Document: an https URL as the client_id |
| Client authentication | none (public clients), client_secret_post, client_secret_basic |
| Scope | mcp (the default when you omit scope) |
| Resource | The endpoint URL (RFC 8707). CommSync binds each token to it |
| Access token | csat_…, valid for one hour |
| Refresh token | csrt_…, valid for 90 days. It rotates on every use. For 30 seconds after a use, the same token gets the same new pair again, for a client that refreshes twice at once. After that, a used token revokes its token family |
| Revocation | POST /oauth/revoke (RFC 7009) |
The authorization response carries iss (RFC 9207). A loopback redirect
(http://127.0.0.1, http://localhost, http://[::1]) can use any port.
A code is single-use. A second exchange that passes the PKCE check revokes the tokens that the first exchange issued. CommSync refuses a second exchange without the right verifier, and that exchange changes nothing.
API key
Send Authorization: Bearer csk_…. A key does not expire, and you revoke it
under Settings, in API keys. A key suits a script or a server-side
agent.
Authorization model
Every request resolves your credential (an OAuth token or an API key) to
(userId, orgId, role, accessibleChannels).
Each tool sits behind one of five gates. The server rejects a call that
exceeds your access before anything happens.
any member any user in the org channel access needs access to the relevant channel agents access owner / admin owner only
- any member — any user with org membership.
- channel access — you must have access to the channel involved.
- agents access — owners and admins, and members when the workspace lets members use Agents.
- owner / admin — reserved for org owners and admins.
- owner only — the single workspace owner (for example, billing).
Owners and admins have channel access implicitly; members get it per channel — see Roles & permissions.
CommSync also tags tools by effect: read (no change), write (mutates), or
destructive (removes data — use with care).
Channel-scoped keys and apps
An API key or a connected app can be fine-tuned to specific lines instead of your full channel access. For a key, choose Specific lines when you create or edit it under Settings, in API keys. For an app, choose it on the consent screen. You can change it later under Settings, in Connect AI apps. Pick the email addresses and phone numbers it can touch.
The server then intersects your live channel access with the allowlist on every request. A scoped key or app can only read, send, and act on the chosen lines. Threads on other channels are invisible to it, and CommSync refuses sends from other channels. Channel listings only show what is in scope.
- The default is All channels: the key follows your live access.
- This includes lines you connect later; CommSync migrated pre-existing keys this way.
- A scoped key never out-privileges you.
- If you lose access, or someone deletes the line, it drops from the key's scope too.
- Per-user surfaces (contacts, labels, AI, webhooks, profile) do not belong to a channel, so scope does not affect them.
- The agent tools show only the agents, turns, and threads on the chosen lines.
- They pause or activate only an agent with every line in scope. They do not return the agent stats.
Security details
Each key and each app has one more setting: Security details. It decides how much of your account security mail the key or app reads. You set it on the consent screen. To change it later, click the key under API keys or the app under Connect AI apps.
| Setting | Security events | One-time code | Body of a security message |
|---|---|---|---|
| Full (default) | The event, the service, the time, and the device and place the mail states | As you see it | As you see it |
| Redacted | The event and the time only. The service reads "an account", and no sender shows | Not returned | Reads "[security message withheld]". The sender and the text of a file on that message read the same, and a download is refused |
Choose Redacted for a key that a script or a shared tool holds. No setting ever returns a link, a token, or a code from a security event, because CommSync never stores one.
Tool catalog
Threads
Reads follow your channel access and return a compact shape for an AI app.
A message carries its plain-text body, the sender, the attachments, the
call details, and your read and star state. It also carries the
identityId of the other party, which send_sms and send_email take.
CommSync cuts a body longer than maxBodyChars (default 4,000 characters)
and sets truncated: true. The HTML body of an email comes back only when
you set includeHtml: true.
Every action changes only your own view of the thread, and your open web and
iPhone apps show the change at once. An action works on every thread that
list_threads shows you, also a thread on a line that an owner removed. On
a line that you connected with Google sign-in, the read, archive, spam,
Trash, restore, and star actions also change Gmail. Only a key or app with
access to all channels does this.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_threads | channel access | read | List threads visible to you, as compact rows |
get_thread_summary | channel access | read | One thread in the compact row shape |
get_thread_messages | channel access | read | Paginated messages for a thread, in the compact shape |
get_message | channel access | read | One message by id, in the compact shape |
get_unread_counts | channel access | read | The count of unread threads in each folder |
mark_thread_read | channel access | write | Clear your unread count on the thread and the other chains of the contact |
mark_thread_unread | channel access | write | Force a thread unread for you |
archive_thread | channel access | write | Archive (per-user) |
unarchive_thread | channel access | write | Unarchive (per-user) |
mark_thread_spam | channel access | write | Move to Spam (per-user) |
mark_thread_promotions | channel access | write | Move to Promotions (per-user) |
mark_thread_automated | channel access | write | Move to Automated Messages — non-human mail (per-user) |
move_thread_to_inbox | channel access | write | Clear bucket flags (per-user) |
snooze_thread | channel access | write | Snooze until a timestamp (per-user) |
unsnooze_thread | channel access | write | Clear a snooze (per-user) |
mute_thread | channel access | write | Mute: new messages no longer raise your unread count |
unmute_thread | channel access | write | Unmute |
delete_thread | channel access | destructive | Move the thread to your Trash; teammates keep it |
restore_thread | channel access | write | Restore a thread from your Trash |
hard_delete_thread | channel access | destructive | Delete a thread permanently from your Trash. While a teammate still has it, only your view goes. Otherwise CommSync deletes the thread and removes the email from the mail server |
bulk_update_threads | channel access | destructive | One action on up to 100 threads: read, unread, archive, unarchive, trash, restore, inbox, spam, promotions, or automated |
mark_message_read | channel access | write | Mark one message read for you |
mark_message_unread | channel access | write | Mark one message unread for you |
star_message | channel access | write | Star one message for you |
unstar_message | channel access | write | Remove the star from one message |
delete_message | channel access | destructive | Hide a message from you |
Outbound sends
CommSync enforces channel access before any send. Compose and forward also need at least one accessible channel of the right kind.
| Tool | Access | Kind | Description |
|---|---|---|---|
send_sms | channel access | write | Reply on a current SMS thread, with optional pictures (MMS) |
send_email | channel access | write | Reply on a current email thread, with optional Cc, Bcc, files, and reply-all |
compose_sms | channel access | write | Start a new SMS conversation |
compose_email | channel access | write | Start a new email conversation, with optional Cc, Bcc, and files |
forward_message | channel access | write | Forward a message to a new recipient |
resend_failed_message | channel access | write | Retry a failed outbound message |
list_scheduled_messages | channel access | read | Your scheduled sends that have not gone out |
reschedule_message | channel access | write | Move a scheduled send to a new time |
cancel_scheduled_message | channel access | destructive | Stop a scheduled send before it goes out |
get_send_options | channel access | read | The lines that can reply on a thread, and whether a group reply works |
upload_attachment | any member | write | Store one file and get an id for a send or a draft |
get_send_capacity | channel access | read | Sustainable send rate per line, plus any active rate-limit pause |
Group threads and reply-all
A group thread has more than one other person in it. On a group thread,
leave identityId out.
SMS. send_sms sends one text to every member, from the line of
the group. Some phone platforms cannot send a text to a group. On those
lines the tool answers GROUP_SEND_UNSUPPORTED with the app to reply
in, and sends nothing. It never sends a private text to one member.
Email. send_email answers the latest inbound sender and copies
everyone else. On a 1:1 thread, set replyMode to REPLY_ALL to do the
same. CommSync then reads To and Cc from the message you answer, and
leaves out your own mailbox. inReplyToMessageId picks that message.
Call get_send_options first to see the lines that can reply and
whether a group reply can reach every member.
Files and scheduled sends
upload_attachment takes one file as base64 text and returns an id. Pass
the ids in attachmentIds of send_email, compose_email,
forward_message, send_sms, or compose_sms. A text takes images
only, at most 10 files and 5 MB in total. The limit of 25 MB for a
request applies to the base64 text, so one file can be about 18 MB. CommSync
deletes a file that no send or draft uses within 24 hours. A file type that
can run a program, such as .exe, .js, or .sh, gets the error
FILE_TYPE_BLOCKED.
send_sms, send_email, compose_sms, and compose_email take
scheduledFor, a future time with a UTC offset, such as
2026-10-05T09:00:00-04:00. The message waits with the status
SCHEDULED. list_scheduled_messages lists your scheduled sends.
reschedule_message moves one, and cancel_scheduled_message stops
one. A stopped send stays on the thread as failed, so
resend_failed_message can still send it.
Email bodies
send_email and compose_email take two body fields: bodyText and
bodyHtml. Give one of them or both. A call with neither fails before
CommSync sends anything.
Plain text alone is fine. CommSync builds the HTML part from bodyText.
It escapes the text, keeps the line breaks, and turns each http:// or
https:// link into a clickable link. When you give bodyHtml, CommSync
sends your HTML unchanged. When you give only bodyHtml, CommSync makes
the plain-text part from it. The account signature and the "Sent from
CommSync" footer, when they are on, go after your text in both parts.
Rate limits never reach you
CommSync accepts every authorised send and owns delivery from that point
on — this covers carrier and mail-host rate limits too. Send tools do
not return 429 and never ask you to retry. When a provider throttles us
the message stays queued, backs off, and goes out on its own.
Every send tool returns a receipt that describes where the message actually is:
{
"accepted": true,
"messageId": "cm9x…",
"threadId": "cm7a…",
"state": "waiting_on_line",
"estimatedSendAt": "2026-07-29T18:41:12.000Z",
"pacing": {
"provider": "<platform name>",
"sustainedPerMinute": 54,
"rateLimited": true,
"reason": "<platform name> rate limit — waiting 45s"
}
}state is one of dispatching, waiting_on_line, scheduled, sent, or
failed. Never call a send tool twice for the same message — CommSync
has already queued a waiting_on_line message and will deliver it.
Before a bulk run, call get_send_capacity for the sustainable rate on each
line you can send from. If you exceed it, that is safe — messages queue
rather than fail; they simply take longer to go out.
Retry safely with an idempotency key
A call can time out, or the connection can drop, after CommSync has
already accepted the message. A plain retry then sends a second copy. To
prevent that, give each message an idempotencyKey. The key is a string
of 1 to 200 characters that you choose. A UUID works well.
send_sms, send_email, compose_sms, compose_email, and
forward_message all take the key. When you call a tool again with a key
that you already used, CommSync sends nothing. It returns the receipt of
the first message, with "deduplicated": true.
{
"to": "maya.chen@northwind.example",
"subject": "Your lab results",
"bodyText": "Hi Maya, your report is ready.",
"idempotencyKey": "6f1c2a9e-3b7d-4e2a-9c55-0d8e41b7a3f2"
}- Use a new key for each new message. A reused key returns the old message, even with new text.
- Your keys are private to your account. A teammate who picks the same key gets their own message, never yours.
- Without a key, each call sends a new message.
Channel management
| Tool | Access | Kind | Description |
|---|---|---|---|
list_email_accounts | channel access | read | List email-account channels you can see, with how each signs in and its history import |
add_email_account | any member | write | Link an IMAP/SMTP mailbox to the org with a password and start its sync. Set importHistoryDays to also import older mail. A Microsoft mailbox connects only in Settings |
delete_email_account | owner / admin | destructive | Remove an email account. CommSync also revokes a Google sign-in grant at Google |
test_email_account | channel access | read | Test stored IMAP/SMTP credentials |
list_phone_numbers | channel access | read | List phone-number channels you can see |
add_phone_number | any member | write | Link a number that you already have at an SMS provider, on a connected provider account, and classify its past senders. CommSync does not sell numbers |
delete_phone_number | owner / admin | destructive | Remove a phone number. Its messages and conversations stay. The page of each platform says what CommSync clears at that platform |
Billing
| Tool | Access | Kind | Description |
|---|---|---|---|
get_billing_state | any member | read | The state of the Plan & billing page: tier, provider, seats, trial, caps, usage, credits |
change_tier | owner only | write | Change the tier of a card-billed plan (prorates) |
set_seats | owner only | write | Set the paid seat count of a card-billed plan (prorates). A new member adds a seat by itself |
seats_preview | owner only | read | Dry-run a prorated seat change |
Contacts
The contact graph is private per user — these never leak across users. A
contact that a teammate shares with you opens with get_contact and
list_contact_threads, without its owner’s notes.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_contacts | any member | read | List your contacts, one page at a time |
get_contact | any member | read | A contact, with its channels and your permissions. Your own contact also lists its labels and details |
list_contact_threads | any member | read | Every conversation with a contact: 1:1 and group, SMS and email |
create_contact | any member | write | Create a new contact |
update_contact | any member | write | Rename a contact or change its notes. A rename becomes the title of its conversations |
delete_contact | any member | destructive | Delete your contact; its channels become unnamed contacts again |
merge_contacts | any member | destructive | Merge whole contacts into one survivor; CommSync deletes the sources |
merge_identities | any member | write | Merge two identities under one contact |
split_identity | any member | write | Detach an identity into an orphan |
attach_identity_to_contact | any member | write | Attach an orphan to a contact |
promote_identity_to_contact | any member | write | Promote an orphan into a new contact |
Identities
| Tool | Access | Kind | Description |
|---|---|---|---|
get_identity | any member | read | An identity and its contact |
update_identity_notes | any member | write | Edit per-channel notes |
list_orphaned_identities | any member | read | Identities not yet attached to a contact |
list_all_identities | any member | read | Every identity you own |
Labels
| Tool | Access | Kind | Description |
|---|---|---|---|
list_labels | any member | read | List labels with usage counts |
create_label | any member | write | Create a label (name and hex color) |
update_label | any member | write | Update the name, color, or AI prompt |
delete_label | any member | destructive | Delete a label everywhere |
assign_label | any member | write | Apply a label to a contact or identity |
unassign_label | any member | write | Remove a label |
AI
| Tool | Access | Kind | Description |
|---|---|---|---|
get_ai_settings | any member | read | Read your AI settings and the workspace spend cap |
update_ai_settings | any member | write | Change your AI settings. It takes the fields of the AI page in Settings |
get_todays_digest | any member | read | The newest Daily Brief, or the brief of a date |
list_digests | any member | read | The Daily Brief archive, one page at a time |
dismiss_digest | any member | write | Mark a digest dismissed |
trigger_digest_run | any member | write | Run a digest now. At most 10 runs an hour, counted together with the runs you start in the app |
list_ai_runs | any member | read | Recent AI activity entries |
trigger_inbox_backfill | any member | write | Classify historical senders into Promotions or Spam |
Attachments
These tools read the files on messages you can read. A key or app limited to some lines reads only the files on those lines.
| Tool | Access | Kind | Description |
|---|---|---|---|
get_attachment | channel access | read | File details and one page of its text (PDF text, image text, document contents) |
download_attachment | channel access | read | The file as base64, for a file of 5 MB or less |
search_attachments | channel access | read | Search files by name, by their text, or by document kind |
semantic_search | channel access | read | Search messages and file text by meaning. Each call uses a small amount of AI credits |
Message entities
The bills, invoices, receipts, subscriptions, shipments, reservations,
deadlines, phone numbers, addresses, people, and security events that
CommSync read out of your messages. get_message and
get_thread_messages also return them on each message. The
security details setting applies.
| Tool | Access | Kind | Description |
|---|---|---|---|
search_entities | channel access | read | Find items by kind, sender, date, and paid status, with totals per kind and currency |
Mailing lists
The mailing lists and marketing text senders that mail your lines. An unsubscribe applies to the whole line and needs send authority on it. CommSync never unsubscribes from a message with a caution strip or a spam verdict, and these tools never send a STOP text. See Unsubscribe from mailing lists.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_mailing_lists | channel access | read | The lists that mail your lines, sorted by mail in 30 days, with weekly counts and the unsubscribe state |
unsubscribe_mailing_list | channel access | write | Unsubscribe the line of one message: one-click, else an email from the line, else the web page for a person to finish |
Search, account & webhooks
| Tool | Access | Kind | Description |
|---|---|---|---|
search | any member | read | Search contacts, identities, messages |
search_threads | any member | read | Full thread-centric search: every conversation that matches a query, ranked and paginated, with match snippets |
get_profile | any member | read | Your profile (id, email, name) |
update_profile | any member | write | Update your display name |
list_webhooks | any member | read | List your webhook endpoints |
get_webhook | any member | read | A single endpoint |
register_webhook | any member | write | Create an endpoint (returns secret once) |
update_webhook | any member | write | Patch url / events / mode / status |
rotate_webhook_secret | any member | write | Rotate the signing secret. For 24 h the old secret also signs, as an extra v1= part (Webhooks) |
delete_webhook | any member | destructive | Delete an endpoint + its history |
list_webhook_deliveries | any member | read | Paginated delivery log |
resend_webhook_delivery | any member | write | Retry a delivery |
Drafts
A draft is your own unsent email or SMS. A draft never sends. You send it from the app, or the AI app sends the message with a send tool and then deletes the draft. A key or app limited to some lines sees only the drafts on those lines.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_drafts | any member | read | Your drafts, newest first, with a short preview |
get_draft | any member | read | One draft: recipients, subject, plain-text body, line, attachments |
get_thread_draft | channel access | read | Your reply draft on one conversation |
save_draft | any member | write | Create or update a draft of a new message or a reply. Sends nothing |
delete_draft | any member | destructive | Delete one draft |
Notes
Your private note and checklist on one conversation. Teammates never see it.
| Tool | Access | Kind | Description |
|---|---|---|---|
get_thread_note | channel access | read | The note text, color, and checklist |
update_thread_note | channel access | write | Set the note text or color |
add_note_item | channel access | write | Add a checklist item |
update_note_item | channel access | write | Edit an item, or mark it done |
delete_note_item | channel access | destructive | Delete a checklist item |
Home
Your to-dos and the two reply lists of Home, as Home shows them.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_todos | any member | read | Your to-dos by status (open by default) |
create_todo | any member | write | Add a to-do, on a conversation or on its own |
update_todo | any member | write | Mark a to-do done, dismiss it, reopen it, or edit it |
list_waiting | any member | read | The two reply lists: Waiting on you and Waiting on them |
dismiss_waiting | channel access | write | Take a conversation off the two reply lists until a newer message |
Team comments
Team comments on one conversation. The customer never sees them. The rules are the rules of the app: any share permit reads, and VIEW or above writes, except a shared-contact VIEW permit, which only reads. An @mention must name a teammate who can read the conversation, and that teammate gets the same email as from the app.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_thread_comments | channel access | read | Discussions, the teammates you can @mention, and your permit |
post_thread_comment | channel access | write | Start a discussion |
reply_to_comment | channel access | write | Reply in a discussion |
edit_comment | channel access | write | Edit your own comment |
delete_comment | channel access | destructive | Delete your own comment, or any comment as a manager |
resolve_comment | channel access | write | Resolve or reopen a discussion |
pin_comment | channel access | write | Pin or unpin a comment |
react_to_comment | channel access | write | Add or remove your emoji reaction |
Teams and shared contacts
These tools only read. A team or a shared contact can give teammates access to conversations, so members, permits, transfers, and coverage decisions stay in the app. A team never shows a conversation that you cannot already read.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_teams | any member | read | Teams you hold a permit on |
get_team | any member | read | One team: contacts, lines, members, permits |
list_team_threads | channel access | read | The team's conversations that you can read |
list_shared_contacts | any member | read | Shared contacts you hold a permit on |
get_shared_contact | any member | read | One shared contact: addresses, members, permits |
list_shared_contact_threads | channel access | read | The conversations you can read through one shared contact |
Agents
Agents are the AI teammates that answer inbound texts and email. An AI app can do everything that the Agents pages do: build an agent, give it knowledge and tools, test it, and supervise it. The tables below split the tools by job.
The permission rules are the rules of the app:
- Every agent tool needs agents access. Owners and admins always have it.
- Members have agents access when the workspace lets members use agents.
- A member sees only the activity on the lines they hold.
- To change, test, pause, or activate an agent, a member needs every line of that agent.
- A key or an app limited to some lines follows the same line rule.
- A key or an app limited to some lines can read knowledge, webhook tools, and MCP connections. It cannot change them.
- A key or an app limited to some lines cannot create or delete an agent.
- The approval queue is for owners and admins.
- Anyone who can see a conversation can take it over.
- No tool returns a secret or a credential.
- The one exception is the signing secret of a webhook tool.
- You get the signing secret once, when you create or rotate it.
The first table is for supervision.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_agents | agents access | read | Your agents, with status, mode, safety level, and lines |
get_agent | agents access | read | The setup of one agent, with no secrets |
list_agent_turns | agents access | read | The activity of one agent, newest first |
get_agent_stats | agents access | read | Outcome counts and AI spend for each agent |
get_thread_agent_status | channel access | read | The agent of a conversation, and whether a person took it over |
list_pending_agent_replies | owner / admin | read | Drafts that wait for approval |
approve_agent_reply | owner / admin | destructive | Send a draft as written or edited. Takes an idempotencyKey |
reject_agent_reply | owner / admin | write | Reject a draft. CommSync sends nothing |
list_agent_escalations | owner / admin | read | Conversations an agent handed to a person |
resolve_agent_escalation | owner / admin | write | Take an escalation out of the queue |
take_over_thread | channel access | write | No agent on the line replies in this conversation until you hand it back |
hand_thread_back_to_agents | channel access | write | End a takeover |
pause_agent | agents access | write | Pause an agent on all of its lines |
activate_agent | agents access | destructive | Turn an agent on. In Supervised or Automatic mode it then sends by itself |
Agent setup
| Tool | Access | Kind | Description |
|---|---|---|---|
create_agent | agents access | write | Create an agent in Draft status with no lines. templateKey picks the starter goals for its kind. Not for a key or an app limited to some lines |
update_agent | agents access | write | Change the persona, rules, reply style, mode, safety level, limits, quiet hours, group email, or footer of an agent |
delete_agent | agents access | destructive | Delete an agent with its activity, memories, and opt-outs. You cannot undo it |
set_agent_lines | channel access | write | Replace the full list of lines that one agent answers on |
update_agent_line | agents access | write | Set the work that an agent does, and never does, on one of its lines |
draft_agent_instructions | agents access | write | Write first-draft instructions from a name, a role, and a brief. Uses AI credits |
draft_agent | agents access | write | Draft a whole agent from a description: the name, the instructions, the kind, tests, and goals. Saves nothing. Uses AI credits |
list_line_routing | agents access | read | Each line with agents: tasks, default agent, no-match policy, and never-reply policy |
set_line_routing | channel access | write | Save the default agent, the no-match policy, the never-reply policy, and the agent tasks of one line |
list_agent_versions | agents access | read | The History of an agent: one version per save, newest first, with who, when, and what changed |
get_agent_version | agents access | read | One version of an agent, with its snapshot of the setup, settings, lines, tools, tests, and goals |
restore_agent_version | agents access | destructive | Bring back the setup, the rules, the reply style, and the settings of an older version. Lines, tools, tests, and goals stay as they are |
set_members_can_use_agents | owner / admin | write | Turn on or off the workspace setting that lets members use agents |
Agent inspection
| Tool | Access | Kind | Description |
|---|---|---|---|
get_agent_turn | agents access | read | One turn with its step trace, route decision, safety reasons, and cost |
list_agent_memories | agents access | read | What one agent remembers about each contact |
delete_agent_memory | agents access | destructive | Delete what an agent remembers about one contact |
list_agent_opt_outs | agents access | read | The phone numbers and addresses that one agent never answers |
add_agent_opt_out | agents access | write | Add a phone number or an email address that the agent never answers |
remove_agent_opt_out | agents access | destructive | Remove a manual opt-out. An opt-out that the contact sent stays |
list_conversation_variables | agents access | read | The values that webhook tools stored on one conversation you can see |
Agent test runs
A test run shows what an agent would do with a message, on a real conversation or one you type. It uses the same instructions, tools, and safety check as a real reply. CommSync sends nothing and writes nothing to the conversation. Each run uses AI credits like a real reply.
A saved test keeps a conversation and what passes, so you can run it again after each change to the agent. A test checks the next reply, a tool call, or a whole conversation with a simulated contact.
| Tool | Access | Kind | Description |
|---|---|---|---|
run_agent_test_turn | agents access | write | Do a dry run of an agent on a real or typed conversation. CommSync sends nothing |
evaluate_agent | agents access | write | Run up to 10 test cases against one agent and report each pass or fail |
list_agent_tests | agents access | read | The saved tests of one agent, each with its last result |
create_agent_test | agents access | write | Save a test from a typed conversation or a copy of a real one |
update_agent_test | agents access | write | Change the name, conversation, expectation, or stand-in results of a saved test |
delete_agent_test | agents access | destructive | Delete one saved test |
run_agent_tests | agents access | write | Run all or some saved tests 1, 3, or 5 times. Waits up to 45 seconds for the result |
get_agent_test_run | agents access | read | One run of saved tests, or the newest, with each result and the failure groups |
Agent analysis
After an agent conversation ends, a model judges the goals of the agent ("Did it book a visit?") and captures its fields ("Visit date", "Budget"). Set the goals and fields, try drafts on past conversations, and read each conversation with its outcome and results. Search the conversations of every agent with the filters of the Conversations view. Read a transcript, rate a conversation, or correct a result. Analyze again, or export a CSV file.
Set the alerts of an agent, and read or build its topics.
A key or an app limited to some lines sees only the conversations whose every thread is on its lines. It never sees a field marked sensitive. Only an owner or admin on a key or app with every line can export sensitive fields.
| Tool | Access | Kind | Description |
|---|---|---|---|
get_agent_analysis | agents access | read | The analysis settings, goals with their 30-day counts, and fields of one agent |
update_agent_analysis_settings | agents access | write | Turn analysis on or off, and set the depth, end windows, sample rate, and switches |
create_agent_goal | agents access | write | Add a goal: a question a model answers after each conversation |
update_agent_goal | agents access | write | Change a goal. A change the judge reads starts a new version |
delete_agent_goal | agents access | destructive | Delete a goal and its results |
create_agent_field | agents access | write | Add a field: a detail to capture from each conversation |
update_agent_field | agents access | write | Change a field. A change the model reads starts a new version |
delete_agent_field | agents access | destructive | Delete a field and its values |
apply_agent_analysis_template | agents access | write | Add the goals and fields of a starter template |
try_agent_analysis | agents access | write | Try draft goals or fields on up to 5 ended conversations. Saves nothing. Uses AI credits |
list_agent_conversations | agents access | read | The conversations of one agent, newest first, with the outcome, counts, and analysis |
get_agent_conversation | agents access | read | One agent conversation with its goal results and captured fields |
rerun_agent_analysis | agents access | write | Analyze one ended conversation again. Uses AI credits |
search_agent_conversations | agents access | read | Search the conversations of every agent you can reach, with every filter of the Conversations view |
get_agent_analysis_overview | agents access | read | The numbers of the Analysis Overview for a range: totals against the period before, a time series, goals with judge agreement, fields, breakdowns, and tools |
get_agent_conversation_transcript | agents access | read | The messages of one conversation, with the agent steps between them |
correct_agent_goal_result | agents access | write | Overturn the judge for one goal of one conversation |
correct_agent_field_value | agents access | write | Fix the captured value of one field of one conversation |
rate_agent_conversation | agents access | write | Your rating, note, and thumbs on each agent reply |
mark_agent_conversation_reviewed | agents access | write | Mark one conversation reviewed, or take the mark away |
rerun_agent_conversations | agents access | write | Analyze again every ended conversation that matches a filter. A dry run by default. Uses AI credits |
export_agent_conversations | agents access | read | The matching conversations as CSV text, at most 1,000 rows |
list_agent_alerts | agents access | read | The alerts of one agent, with what each one watches and when it last fired |
create_agent_alert | agents access | write | Add an alert: a critical goal not met, a goal rate below a percent, or a detail that matches. It notifies owners and admins, never a contact |
update_agent_alert | agents access | write | Change an alert, or turn it off |
delete_agent_alert | agents access | destructive | Delete an alert |
list_agent_topics | agents access | read | The nightly topics of one agent, with the count, moods, and success rate of each |
rebuild_agent_topics | owner / admin | write | Build the topics of one agent now. Needs 10 analyzed conversations in the last 30 days. Uses AI credits |
Knowledge
| Tool | Access | Kind | Description |
|---|---|---|---|
list_knowledge_sources | agents access | read | The documents and websites that agents and Ask answer from |
search_knowledge | agents access | read | Find the passages of the knowledge base that answer a question. Each search uses a little of your AI credits |
add_knowledge_website | agents access | write | Add a public website. CommSync reads up to 30 pages for agents and Ask |
add_knowledge_file | agents access | write | Add one document. Readable text only, at most 15 MB |
add_knowledge_text | agents access | write | Add plain text. CommSync stores it as a .txt document |
delete_knowledge_source | agents access | destructive | Delete one knowledge source and its index for good |
refresh_knowledge_source | agents access | write | Read a ready or failed source again. A website gets a new crawl |
list_knowledge_pages | agents access | read | The pages that CommSync read from one source, with passage counts |
set_agent_knowledge | agents access | write | Replace the knowledge sources that one agent answers from |
Agent webhook tools
Webhook tools are the HTTP endpoints that an agent calls while it works on a reply.
| Tool | Access | Kind | Description |
|---|---|---|---|
list_webhook_tools | agents access | read | The webhook tools of the workspace, with settings and health. No secret values |
get_webhook_tool | agents access | read | One webhook tool, with settings and health. No secret values |
create_webhook_tool | agents access | write | Create a webhook tool. You get the signing secret one time |
update_webhook_tool | agents access | write | Change one webhook tool, or turn it on or off |
delete_webhook_tool | agents access | destructive | Delete one webhook tool and its secrets for good |
test_webhook_tool | agents access | write | Send one real test request, or do a dry run. Shows the request and the response |
rotate_webhook_tool_secret | agents access | write | Make a new signing secret. The old secret stops at once |
set_agent_webhook_tools | agents access | write | Replace the webhook tools that one agent can call |
Agent MCP connections
These tools connect the external MCP servers that agents and Ask use.
| Tool | Access | Kind | Description |
|---|---|---|---|
search_mcp_catalog | agents access | read | Search the verified catalog of MCP servers. Shows the servers you already connected |
list_mcp_connections | agents access | read | The external MCP connections of the workspace, or of one agent. No credentials |
add_mcp_connection | agents access | write | Connect a catalog server or a custom https server, with an optional bearer token |
update_mcp_connection | agents access | write | Change the name, the tool allowlist, the bearer token, or the status of a connection |
test_mcp_connection | agents access | write | Connect to the external server and list the tools it offers |
start_mcp_sign_in | agents access | write | Start the OAuth sign-in. A person must open the returned link in a browser |
sign_out_mcp_connection | agents access | write | Delete the OAuth tokens of a connection. The connection and its allowlist stay |
delete_mcp_connection | agents access | destructive | Delete a connection and its credentials. Every agent loses its tools |
set_agent_mcp_connections | agents access | write | Replace the connections that one agent uses, at most 10 for each agent |
Resources
Beyond tools, the server exposes MCP resources for direct reads:
commsync://threads/{threadId}/messages — the newest 200 messages, compact
commsync://contacts/{personId} — a contact's detail
commsync://digests/{localDate} — the AI digest for a dateCommon workflows
Triage the inbox
list_threads → get_thread_messages(threadId) to read the latest.
Reply
get_thread_messages(threadId) to find the identity a message came in on →
send_sms or send_email with that identityId.
On a group thread, leave identityId out.
Merge a duplicate contact
list_orphaned_identities (or search) to find the stray identity →
merge_identities(identityAId, identityBId) or
attach_identity_to_contact(personId, identityId). For two whole
contact records of the same human, confirm both with get_contact and
call merge_contacts(survivorPersonId, sourcePersonIds) instead.
Work the agent approval queue
list_pending_agent_replies → read the draft →
approve_agent_reply(turnId, body?, idempotencyKey) or
reject_agent_reply(turnId). For a handover, call
list_agent_escalations, reply in the thread yourself, then call
resolve_agent_escalation(turnId).
React in real time
You do not have to call list_threads again and again. Register a
webhook and call back into MCP only when an
event fires.
Next
Connect an app in Connect AI apps, or create a key in API keys. Then wire up webhooks, so your agent reacts to messages and does not have to ask again and again. Full parameter reference: /docs/mcp.txt.