> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpressbot.org/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP tool catalog

> Every tool the MCP server can offer, grouped by area, with its description, mode, and required permission.

## What is this?

The full catalog of tools the [MCP server](https://docs.xpressbot.org/api-reference/mcp/overview.md) can expose to a connected client (Claude, Cursor, VS Code, or any other MCP client), grouped in the same order they appear in the app.

This exact list — same names, same descriptions, same order — is always visible live in-app under **Developer → Reference → MCP**, generated from the same tool registry as this page. A given API key's actual available tools are narrower: only tools whose required permission the key's owner holds are ever offered, re-checked on every call, and only inside the one channel the connection was made for.

> [!NOTE]
>
> MCP must be enabled on your installation and included in your plan. Without it the Developer Portal's MCP tab is hidden or shows an **Upgrade** badge, and the server answers `403`.
>
> Only non-destructive tools are ever exposed over MCP — nothing that deletes or cancels something permanently is offered here, no matter what permissions the key has. Every **Write** tool also needs your MCP client's own approval step before it runs (the same tool-approval prompt any MCP client shows), on top of your workspace permissions.

\[SCREENSHOT: mcp-tools-list — The Developer Portal's MCP tab showing the Available tools list grouped by area, with mode and permission badges]

## What can I do here?

* Look up which tools an assistant gets once connected, before you connect it
* Check which permission a team member needs for a given tool to appear for their API key
* See which tools are **Write** (need your client's approval before running) versus **Read** (run immediately)
* See which tools reach customers (they are labelled **Reaches customers** in the Developer Portal): sending a template or Direct Send message, creating a campaign, triggering or activating an automation, and publishing an AI agent

## Tool reference

Columns: **Tool** (the name a model calls), **Description** (exactly what it does), **Mode** (Read runs immediately, Write asks your MCP client to confirm first), **Permission needed** (the permission the API key's owner must hold for this tool to appear at all; "None" means every connected key sees it).

### Workspace & team

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `get_workspace_overview` | Summary of the user's current channel: its name and counts of contacts, automations by status, and templates by status. Only sections the user is allowed to see are included. | Read | None |
| `list_channels` | List the channels this user can work in (name, WhatsApp number or connected Instagram/Facebook/web chat, active, health), marking the current one. Other channels are only listed here; every other tool works in the current channel. | Read | None |
| `list_team_members` | List the people who work in the user's current channel: the owner and team members, with their user id, role, status and last login. Use it to find who can take a conversation. | Read | `team:view` |
| `get_activity_summary` | Activity of the user's current channel over the last N days (1-30, default 7): messages received and sent, delivery results of sent messages (sent, delivered, read, failed), new conversations and new contacts. | Read | `analytics:view` |
| `get_connected_networks` | Which messaging networks the user's current channel has connected and whether each is healthy: WhatsApp number, Instagram account, Facebook Page, Telegram bot, TikTok account and web chat sites, with status, webhook state and token expiry where they apply. Use it for "is my Instagram connected?" or "why am I not receiving Telegram messages?". | Read | `channels:view` |
| `get_google_connection` | Whether the user's current channel has a Google account connected (for Google Calendar and Google Sheets), which account, and how many calendars and sheets are available. Call it before offering or building anything that needs Google. If it isn't connected, the assistant builds with plain fields instead. | Read | `google:view` |

### Inbox & conversations

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `get_inbox_overview` | The inbox workload of the user's current channel: conversations by status, how many have unread messages, how many open ones nobody is assigned to, and how many were active in the last 24 hours. Users limited to their assigned conversations only get their own numbers. | Read | `inbox:view` |
| `list_conversations` | The most recently active conversations in the user's current channel: contact name, channel type, status, priority, whether it is assigned, unread count and a preview of the last message. Filter by status or to unread only. Users limited to their assigned conversations only see their own. | Read | `inbox:view` |
| `get_conversation` | Open a conversation in the user's current channel: status, priority, whether it is assigned, unread count, the customer's 24-hour reply window, and the contact (name, phone, email, labels). Pass conversationId (from list\_conversations) or contactId (from search\_contacts) to get that contact's conversations. Then use list\_messages to read what was said. | Read | `inbox:view` |
| `list_messages` | Read the messages of one conversation (from list\_conversations or get\_conversation), oldest to newest in the returned page. Each message has direction (inbound = from the customer), who sent it (user, bot, automation, system), type, text, delivery status and any delivery error. Returns the latest messages by default; pass the returned nextBefore as before to read earlier ones. | Read | `inbox:view` |
| `list_notes` | Read the internal notes on one conversation (from list\_conversations or get\_conversation), newest first: text, type (internal, follow-up, reminder, warning, info), status, reminder time and author. Customers never see notes. | Read | `inbox:view` |
| `add_note` | Add an internal note to a conversation (from list\_conversations or get\_conversation). Notes are visible only to the team, never to the customer. Use for context, follow-ups or warnings the team should see. | Write | `notes:create` |
| `list_canned_responses` | The user's own saved replies in the current channel (shortcut and text), for suggesting a ready-made answer. | Read | `inbox:view` |
| `close_conversation` | Close (resolve) a conversation. | Write | `inbox:close` |
| `handoff_to_human` | Hand a conversation over to the human team: stops the AI on it and puts it in the unassigned queue. | Write | `inbox:assign` |

### Contacts & CRM

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `search_contacts` | Search contacts in the user's current channel by name, phone or email, optionally filtered to one label. Returns at most 20 contacts; say so when the answer may be incomplete. | Read | `contacts:view` |
| `get_contact` | Get one contact's details (name, phone, email, status, labels, custom fields). | Read | `contacts:view` |
| `list_labels` | List the contact labels defined in the user's current channel (name, description). Use it before tagging a contact or filtering contacts by label: only these exact names are valid. | Read | `labels:view` |
| `list_custom_fields` | List the custom contact fields defined in the user's current channel with their type and, for dropdowns, the allowed options. Use it before reading or setting a custom field value. | Read | `custom_fields:view` |
| `list_pipelines` | List the sales/process pipelines of the user's current channel with their stages in board order. Use it before moving a contact to a stage or when the user asks about their pipeline setup. | Read | `pipeline:view` |
| `update_contact` | Change a contact's name, email or status (active, blocked, unsubscribed). | Write | `contacts:edit` |
| `set_custom_field` | Set one custom field on a contact. The field must already exist for this channel. | Write | `contacts:edit` |
| `add_contact_label` | Add an existing label to a contact. The label must already be defined for this channel. | Write | `contacts:edit` |
| `remove_contact_label` | Remove a label from a contact. | Write | `contacts:edit` |
| `move_pipeline_stage` | Move a contact to another stage of a CRM pipeline in this channel. | Write | `pipeline:edit` |
| `create_label` | Create a new contact label in the user's current channel. Check `list_labels` first — names are unique per channel (case-insensitive), so an existing label is reported instead of duplicated. | Write | `labels:create` |
| `create_custom_field` | Create a new contact custom field in the user's current channel. Check `list_custom_fields` first — names are unique per channel. For dropdown fields, options must be supplied. | Write | `custom_fields:create` |
| `create_pipeline` | Create a new CRM pipeline in the user's current channel, with its stages in order. Without stages it gets the standard set (New Lead, Follow-up, Converted, Not Interested). Check `list_pipelines` first to avoid a duplicate name. | Write | `pipeline:create` |
| `add_pipeline_stage` | Add a stage to the end of one of the channel's pipelines (id from `list_pipelines`). | Write | `pipeline:create` |
| `apply_as_bulk` | Apply one change to many contacts or conversations at once, chosen by a filter (never a list) — for example "add the label VIP to every contact whose name starts with A" or "close all conversations with no customer message for 30 days". One approval covers the whole change, which shows how many records match (up to 50,000 per change). It runs in the background; check it with `get_bulk_job`. Labels, custom fields and stages must already exist. | Write | The permission of the change being applied |
| `get_bulk_job` | Progress of a bulk change started with `apply_as_bulk`: status, how many records are done, succeeded and failed. | Read | None |

### Automations

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `list_automations` | List automations (chatbot flows) in the user's current channel, newest first. Use to answer questions like which automations exist, which are active, or how often they ran. | Read | `automations:view` |
| `create_automation` | Build an automation (chatbot flow) from a description and save it as a DRAFT: it is created INACTIVE and does not run until it is activated with activate\_automation. Give the channelType (default WhatsApp), the trigger (a keyword, a new conversation, or a contact field change) and the steps as a flat list. Each step goes on to the next one in the list unless it points elsewhere by step id (give the target steps an id), so branches can go as deep as needed and can loop or jump. Steps: send\_text, send\_buttons, send\_list, send\_media, send\_cta, send\_contact, send\_location, send\_template (approved templates only), send\_flow, ask\_question (text, number, email, phone, date, location, address, image, video, audio, file; with max attempts, an invalid-answer message, a deadline, and separate answered / not-answered paths), add\_label / remove\_label, set\_field, create\_note, wait, assign\_team\_member, resolve\_conversation, condition, branch (several values), working\_hours, jump\_to, switch\_automation, http\_request and ai\_reply. The flow is checked with the same rules the dashboard flow builder applies, so it opens there without errors. Not covered: payments, product and catalog steps, carousels, Google Sheets / Calendar, Shopify / WooCommerce, sequences; build those in the dashboard. Use list\_automations first so you do not duplicate one, list\_labels, list\_team\_members and list\_templates for names. Write the messages from what the user told you; do not invent offers, prices or policies. If the user has not said what the flow should do, ask before proposing. | Write | `automations:create` |
| `update_automation` | Replace the flow of an automation that is OFF with a new description (same shape as create\_automation: name, trigger and the complete list of steps). It REPLACES the whole flow, so read the current one with get\_automation first and send everything you want to keep. An automation that is on must be turned off first (pause\_automation), and one with runs in progress is refused. Only flows made of the supported steps can be described (see create\_automation); for anything else use the dashboard flow builder. | Write | `automations:edit` |
| `activate_automation` | Turn an automation ON (automationId from list\_automations). It then runs for real customers, so use it only when the user has asked for it. It checks the flow is valid first. Suggest reviewing the flow in the dashboard before activating a new draft. | Write | `automations:edit` |
| `pause_automation` | Turn an automation OFF so it stops starting for new customers (automationId from list\_automations). Runs already in progress are not deleted. | Write | `automations:edit` |
| `get_automation` | Get one automation from the user's current channel by id: its trigger, status, and the ordered list of steps it contains. Get the id from list\_automations first — never guess it. | Read | `automations:view` |
| `list_automation_building_blocks` | List the step types an automation can use on a given channel type (messages, questions, logic, actions, integrations), with what each does. Use to answer whether an automation can do something — never claim a capability that is not listed. | Read | `automations:view` |
| `list_automation_runs` | Recent runs of the channel's automations, newest first: which automation, for which contact, status (running, completed, failed), error and timing. Filter by automationId or status. Use it for "did my automation run?" or "why did it fail?", then get\_automation\_run for the step-by-step log. | Read | `automations:view` |
| `get_automation_run` | One automation run (from list\_automation\_runs) with its step log: each step's type, status and error. | Read | `automations:view` |
| `trigger_automation` | Start one of this channel's active automations for the customer of a conversation. Get the id from list\_automations. | Write | `inbox:send` |

### WhatsApp

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `send_template` | Send one of this channel's approved WhatsApp templates to the customer of a conversation. Templates have fixed text approved by WhatsApp: you cannot write a new message here, only pick an existing template (exact name from list\_templates) and fill its `{{1}}`, `{{2}}`… variables in order with `parameters` (exactly as many as it has). | Write | `inbox:send` |
| `direct_send` | Send a free-form WhatsApp utility or authentication message to the customer of a conversation without a pre-approved template (Meta's Direct Send beta). Use this only when no matching approved template exists via list\_templates — prefer send\_template whenever an approved template already fits. Only for utility (order/appointment/status updates) or authentication (verification codes) content; never for marketing, which must use an approved template. `templateName` (business-named templates) works with utility only, never authentication. Authentication category and Direct Send itself are restricted by Meta per WABA — a channel that isn't onboarded will get a clear rejection. | Write | `inbox:send` |
| `create_campaign` | Create a WhatsApp campaign that sends an approved template to a set of contacts, now or at a scheduled time. Find the template with list\_templates and labels with list\_labels first; fill every `{{n}}` placeholder in the template body, one `variables` entry each (fixed text, the contact's name/phone/email, or a custom field). The user sees one Confirm card with the template, audience, number of recipients and the send time; nothing is sent until they confirm. Once started, a campaign can only be stopped from the dashboard. | Write | `campaigns:create` |
| `create_template_draft` | Write a WhatsApp message template and save it as a DRAFT in the user's current channel (text templates only: optional header text, body with `{{1}}` `{{2}}` placeholders and an example value for each, optional footer, up to 3 buttons). Nothing is sent to WhatsApp and nothing reaches customers: the user opens it in Templates, reviews it and submits it for approval, which can take minutes to a day. A campaign can only use an approved template. Check list\_templates first so you do not duplicate one. Write the text from what the user said; never invent offers, prices or links. Marketing templates should read as marketing, utility templates as plain updates. Templates with a header image, video or document, carousels and authentication codes are made in the dashboard. | Write | `templates:create` |
| `list_campaigns` | List WhatsApp campaigns in the user's current channel, newest first, with status, template and results (recipients, sent, delivered, read, replied, failed, pending, and delivery/read/reply/failure rates). | Read | `campaigns:view` |
| `get_campaign` | Details and results of one campaign: audience labels, template, schedule, progress, totals, rates and the failure reason when it failed. Pass campaignId from list\_campaigns, or the campaign's name when you only know the name (e.g. a campaign named earlier in the chat). | Read | `campaigns:view` |
| `list_templates` | Find WhatsApp message templates in the user's current channel: name, category, language, approval status, the template's fixed text, how many `{{n}}` body values it takes, which URL buttons need a value, and whether it needs a header file. Use `search` (part of the name or text) whenever you are looking for a specific template; `total` tells you how many match, and if it is larger than what was returned, search more narrowly instead of guessing. Only approved templates can be sent, and their text cannot be changed; only the values are filled. | Read | `templates:view` |
| `list_whatsapp_flows` | List the WhatsApp Flows (in-chat forms) of the user's current channel with their id, name, and status (such as DRAFT or PUBLISHED). Use it before creating one so you don't duplicate a flow, and to find a flow id for a Send Flow automation step. | Read | `flows:view` |
| `create_whatsapp_flow_draft` | Build a WhatsApp Flow (a multi-screen form that opens inside the chat) from a description and save it as a **draft** on WhatsApp. It isn't published and isn't sent to anyone — you open it in **Flows**, review it in the builder and phone preview, and save it there (saving publishes it). Screens can contain headings, text, short answers (text, number, email, or phone), paragraphs, dates, single and multiple choice, dropdowns, and an opt-in. Images, photo or document upload, the calendar picker, conditional If/Switch parts, lists that navigate, dynamic data from an endpoint, and mapping answers to contact fields are not covered — build those in Flows. | Write | `flows:create` |

### Instagram

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `list_instagram_ref_links` | Instagram referral links (ig.me links that start a conversation with a tracking reference) of the user's current channel, most clicked first: label, campaign, source, clicks, last used and whether active. | Read | `instagram:view` |

### Telegram

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `list_telegram_campaigns` | Telegram campaigns (broadcasts) of the user's current channel, newest first: status, schedule and results (recipients, sent, failed, blocked the bot). | Read | `telegram:view` |
| `get_telegram_campaign` | One Telegram campaign (from list\_telegram\_campaigns): audience, schedule, results, recipients by status and the latest delivery errors. | Read | `telegram:view` |
| `list_telegram_groups` | Telegram groups the channel's bot is in: title, type, the bot's role (member or admin), member count, how many members have moderation warnings, and when it was last synced. | Read | `telegram:view` |

### TikTok

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `list_tiktok_posts` | TikTok posts published or scheduled from the user's current channel, newest first: caption, status, privacy, schedule, publish time and the failure reason when publishing failed. | Read | `tiktok:view` |

### Web chat

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `search_help_articles` | Search this channel's own Help Center articles: the web chat Knowledge Base, i.e. the FAQ and help content the business publishes for its customers. Not the product documentation (use search\_docs for how to use the platform). | Read | None |
| `get_webchat_visitors` | Visitors of the channel's web chat sites over the last N hours (default 1, up to 168): total visits, top countries, most visited pages and the latest visits (country, city, page, referrer, time). No IP addresses. | Read | `widgetbuilder:view` |

### AI agents

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `list_ai_agents` | List the AI agents of the user's current channel: name, type, description, status and tone. | Read | `ai:view` |
| `get_ai_agent` | Details of one AI agent (from list\_ai\_agents): description, status, tone, model provider, its instructions and which capabilities are turned on for it. | Read | `ai:view` |
| `create_ai_agent` | Create a new AI Agent (draft) in the user's current channel with a name, optional description, instructions and tone. The agent is created INACTIVE: it does not answer customers until it is published, and it has no knowledge, skills or tools yet. Check list\_ai\_agents first so you do not duplicate one. Write the instructions from what the user told you about their business; do not invent facts (prices, hours, policies). If the user has not said what the agent should do, ask before proposing. | Write | `ai:create` |
| `build_ai_agent` | Build a NEW AI Agent from the user's description in ONE step (one approval): the agent (created INACTIVE, a draft), its instructions and tone, knowledge (pasted text or web addresses), skills and which capabilities are on. Prefer this over create\_ai\_agent plus several add\_\* calls when the user describes a whole agent. Use only what the user told you: if you lack something that matters (what the business does, what the agent may or may not do, where its knowledge lives, who takes over), ask first; never invent prices, hours, policies or web addresses. Handoff recipients are NOT part of this (channel-wide: set\_handoff\_assignment). It does not publish: afterwards tell the user to test it, then offer check\_agent\_readiness and publish\_ai\_agent. | Write | `ai:create` |
| `update_ai_agent` | Change an existing AI Agent's name, description, instructions or tone (agentId from list\_ai\_agents). Only the fields you give are changed, and `systemInstructions` REPLACES the whole instructions text: read the current ones with get\_ai\_agent first (long ones are shown truncated; if so, tell the user and ask before replacing) and send the complete new text. It does not turn the agent on or off, and does not touch its knowledge, skills or tools. | Write | `ai:edit` |
| `add_agent_knowledge` | Give an existing AI Agent knowledge to answer from: pasted text the user provided, one web page, a sitemap or an llms.txt. It starts reading in the background (it is NOT ready instantly: say it is processing and that check\_agent\_readiness shows when it is done). Only use content or addresses the user gave you. Uploaded files cannot be added from here. | Write | `ai:create` |
| `add_agent_skill` | Add a skill to an existing AI Agent: a named procedure it looks up when a matching situation comes up (e.g. refund-policy, book-appointment) instead of cramming everything into its main instructions. Base it on what the user told you; do not invent policies. | Write | `ai:create` |
| `set_agent_capability` | Turn one of an AI Agent's capabilities (the actions it may take in a conversation, e.g. handoff\_to\_human, add\_contact\_label, close\_conversation) on or off, optionally with a guideline for when to use it. Read the agent's current capabilities with get\_ai\_agent first and use the exact `key` shown. Only for that agent; it does not change other agents. | Write | `ai:edit` |
| `set_handoff_assignment` | Choose who receives conversations an AI Agent hands over to a human: nobody in particular (shared unassigned queue), one team member, or a group taking turns (round\_robin) or the least busy (least\_busy). IMPORTANT: this is a setting of the whole channel, shared by every AI Agent on it. Get team members with list\_team\_members and pass their userIds. Turning handoff on or off for one agent is set\_agent\_capability with handoff\_to\_human. | Write | `ai:edit` |
| `check_agent_readiness` | Check whether an AI Agent is ready to go live: instructions, knowledge (ready / still processing / failed), skills, enabled capabilities, human handoff and the channel's AI model setting, plus whether the channel's AI Agent switch is on. Use it after building or changing an agent and before publish\_ai\_agent. Report what is missing in plain words. | Read | `ai:view` |
| `publish_ai_agent` | Put an AI Agent live so it starts answering real customers. Only when the user explicitly asks to publish or activate, after check\_agent\_readiness, and never in the same reply that builds the agent: the user should test it first (the dashboard's Playground). Set enableChannelAgenticMode true only if the user wants the channel's AI Agent switch turned on too (check\_agent\_readiness shows it); without that switch on, no agent answers customers. | Write | `ai:edit` |

### Storefront & orders

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `search_catalog` | Search this channel's product catalog by keyword. Returns up to 20 products. | Read | `catalogs:view` |
| `get_product` | Get one catalog product's details by id (from search\_catalog). | Read | `catalogs:view` |
| `list_orders` | Storefront orders of the user's current channel, newest first: order number, status, customer, total, quantity and payment method. Filter by status. | Read | `catalogs:view` |
| `get_order` | One storefront order by id or order number (e.g. ORD-...), with its items, prices, shipping and tax. | Read | `catalogs:view` |

### Events

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `search_events` | List this channel's published events. | Read | `events:view` |
| `get_event` | Get one event's details by its slug (from search\_events). | Read | `events:view` |
| `check_event_availability` | Check remaining capacity for an event on a date (YYYY-MM-DD). | Read | `events:view` |
| `get_registration` | List a contact's event registrations. | Read | `events:view` |
| `get_event_ticket` | Get a contact's ticket for an event. | Read | `events:view` |

### Booking Studio

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `search_services` | List this channel's published bookable services with their length, providers, and intake questions. | Read | `services:view` |
| `check_service_availability` | List free start times for a service over the next days, optionally for one provider and group size. | Read | `services:view` |
| `get_service_bookings` | List a contact's upcoming service bookings. | Read | `services:view` |
| `book_service` | Book a service for a contact at a free time (from check\_service\_availability). | Write | `services:edit` |
| `reschedule_service_booking` | Move one of a contact's service bookings to another free time. | Write | `services:edit` |
| `complete_service_booking` | Mark a service booking as completed after the visit and record the private visit notes. | Write | `services:edit` |

### Product docs

| Tool | Description | Mode | Permission needed |
| - | - | - | - |
| `search_docs` | Search the product documentation (how-to guides for every feature: channels, inbox, automation, AI agents, templates, campaigns, integrations, settings, API). Use it for any "how do I…", "where is…", "what does … mean" or setup question, then read the best page with read\_doc before answering. Returns page paths, titles, short descriptions and links. | Read | None |
| `read_doc` | Read one documentation page (from search\_docs, or the current page's docs path) as Markdown. Answer from it, and link the page with its url so the user can open the full guide. | Read | None |

## Troubleshooting / Technical Notes

* **A tool I expect isn't in the list the assistant sees.** The MCP server only offers tools whose required permission the API key's owner holds, re-checked on every call — grant the permission in the "Permission needed" column above (see [Team](https://docs.xpressbot.org/workspace/team.md)), then reconnect or retry.
* **A tool that changes something (Write) isn't in this catalog at all.** Some write actions — anything that deletes or cancels permanently, such as cancelling an event registration — are never exposed over MCP by design and stay dashboard-only, regardless of permissions.
* **A Write tool call seems to hang or never take effect.** Your MCP client (Claude Code, Claude Desktop, Cursor, VS Code) asks you to approve each Write tool call before it runs — check for a pending approval prompt in your client.
* **`create_ai_agent`, `create_automation`, or `build_ai_agent` worked but the agent or automation isn't answering customers.** By design: new AI agents and automations are created inactive (as drafts). Test the agent in the dashboard Playground, run `check_agent_readiness`, then use `publish_ai_agent`; or review the flow in the dashboard and use `activate_automation`. Publishing and activating only happen when you explicitly ask.
* **`update_automation` is refused.** It only replaces the flow of an automation that is **off** and has no runs in progress. Use `pause_automation` first, then retry. Automations using steps it can't describe (payments, catalog, carousels, Google Sheets / Calendar, Shopify / WooCommerce, sequences) are built in the dashboard flow builder.
* **`update_ai_agent` replaced instructions I wanted to keep.** `systemInstructions` replaces the whole text. Read the current instructions with `get_ai_agent` first and send the complete new text.
* **`set_handoff_assignment` changed other agents.** The handoff recipients are a setting of the whole channel, shared by every AI agent on it. Turning handoff on or off for one agent is `set_agent_capability` with `handoff_to_human`.
* **`direct_send` is rejected.** Direct Send is a Meta beta and is restricted per WhatsApp Business Account; it only covers utility and authentication messages, never marketing. If a matching approved template exists, use `send_template`.
* **The list here doesn't match what I see in-app.** It should always match — both are generated from the same tool registry. If they differ, refresh the Developer Portal's MCP tab; this page is updated separately from the live app.

## Related docs

* [MCP overview and connection setup](https://docs.xpressbot.org/api-reference/mcp/overview.md)
* [Introduction](https://docs.xpressbot.org/api-reference/introduction.md)
* [Authentication](https://docs.xpressbot.org/api-reference/authentication.md)
* [Developer Portal](https://docs.xpressbot.org/workspace/developer-portal.md)
* [Team](https://docs.xpressbot.org/workspace/team.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.