Connect an MCP client to your dashboard
Point your own Claude or any MCP client at your AISA conversations, labels, reports, agent versions, pages and starter questions, authenticated as your organization. Forty-one tools, twenty-four of them write, and three ready-made prompts.
You can point your own MCP client (your own Claude, Claude Desktop, or any MCP client) at your AISA dashboard data, authenticated as your organization via WorkOS. This is a different server from the docs MCP server: that one is public and unauthenticated and only knows about documentation pages; this one is org-scoped and works with your actual data.
Most of the server reads. It finds and returns conversations, their labels, the dashboard's reports, label counts, your sites, the configuration of your agent versions, and your site's pages and starter questions. It doesn't analyze anything itself: your client's model reads what the tools return and does the analysis.
Twenty-four tools write. They create a site from its storefront address, switch its hosted page on or off, import pages from a sitemap, add and read pages (one by one or all at once), keep pages out of discovery, ask for generated starter questions, create, edit and switch starter questions, change a site's automation settings, its panel (side, opening mode and colours), its Panel reduced state button and its tag monitoring, check a site's tag now, check a connector now, start, extend and stop a site's holdout test, start, stop and promote an agent's A/B test, and delete pages, questions or exclusions. A write is done as the member who connected the client, needs that member's permission, is recorded in Admin activity and applies at once. A write tool never edits an agent's instructions or versions, apart from the assistant that provision_site_from_url creates on a new site and puts live, or a site's existing assistant it puts live when no assistant answers there yet. Starting an agent A/B test locks the two versions it compares, and promoting one puts it live. See Write tools.
It only knows what the assistant did: the conversations it had, the ratings and labels they got, and the widget events around them. Beyond each page's views over 30 days, it has no site traffic, no revenue or order value outside the sales report, and no market or competitor data. See What the server doesn't give you.
Connect
Open the connect card
Go to Settings in your dashboard. You'll see a Connect an MCP client card with a URL.
Copy the URL
Copy the URL from the card. It's the same for every conversation and every client: the server figures out which organization you belong to from how you authenticate, not from anything in the URL.
Add it to your MCP client
Add it as a remote server in your client's configuration. For Claude Desktop or Claude.ai's custom connectors, this is normally a "Connect" or "Add custom connector" step where you paste the URL:
{
"mcpServers": {
"iadvize-dashboard": {
"url": "https://iadvize.ai/api/mcp"
}
}
}Authorize the connection
Your client detects that this server requires authorization and redirects you to sign in with your iAdvize account (the same WorkOS login the dashboard uses), then asks you to grant it access. Once you approve, the client holds a short-lived, scoped token. Nothing is pasted or stored by hand.
Ask it a question
Ask your client something like "which conversations about sizing went unresolved last week?". It picks the tools it needs. See A worked example for the calls it makes.
Tools
The server has forty-one tools: seventeen read and twenty-four write. None takes an organization argument: the organization is the one you authorized.
| Tool | Does what |
|---|---|
list_sites | List your sites (id, name, URL, platform, automation settings, tag monitoring, panel colours, panel side and opening mode, Panel reduced state button settings, hosted page and its link, the agent answering on the site, analysis state), each with its agents (id, name, type, status live or offline), the number, label and id (agtv_...) of the live agent's version, and for an offline agent the same for its latest version. The version fields need Agents: View or Agents: Edit, and read null without. |
list_label_vocabulary | List every label of the conversation taxonomy with its block, kind, allowed values and an English display name for each, plus the derived tokens. These are the only tokens search_conversations accepts. |
search_conversations | Find conversations that match a filter, newest first, as compact items. Searches every site unless you pass siteId. |
get_conversation | Read one conversation by id: its full transcript and its metadata. |
get_conversations | Read up to 20 conversations by id in one call: metadata, a compact transcript and the label record of each. |
get_conversation_labels | Read the label record of one conversation: its status and, once labeled, the resolution, review reason, scores and every answer with the ids of the messages that justify it. |
get_report | Read one of the dashboard's reports for one site over a range of UTC days, optionally next to the previous period: conversations, quality, engagement, starter questions (one page of questions, with a device, a sort and a cursor), add-to-carts, add-to-cart insights (sessions that added to the cart and the median cart value) or sales (revenue and orders). |
list_exposures | Read the raw engagement events of one site over a range of UTC days, newest first, one page at a time. A debug view of single events, not a metric. |
list_page_views | Read the most viewed pages of one site over the last 30 UTC days, at most 50, as the Engagement report's Page views tab lists them. Takes only siteId. |
get_label_breakdown | Count the conversations per value of one label, such as the transfer reasons or the resolution outcomes, over a filter, optionally next to the previous period. |
get_agent_version | Read what one agent version runs with (instructions, enabled tools and capabilities, engine) or what changed between two versions. Needs the Agents: View or Agents: Edit permission. |
get_agent_experiment | Read. An agent's A/B test: the running one, else its latest, or one by id. Its state, the floor and progress, each version's conversations, conversion rate (the main driver) and secondary drivers, the verdict, the always-valid bands and the daily series. Needs Agents: View or Agents: Edit. |
list_site_pages | Read a site's pages with their status, views over 30 days, source, type, language and questions written, the last sitemap import and, on request, the exclusions; or one page with its text, structured content and runs. Needs Site pages: View or Edit. |
list_starter_questions | Read a site's starter questions with their state, source and 14-day performance, or one question in detail. Needs Starter questions: View or Edit. |
add_site_pages | Write. Add up to 50 addresses or paths as pages and start reading them. Needs Site pages: Edit. |
refresh_site_pages | Write. Read up to 50 pages, for the first time or again, optionally generating questions after. Needs Site pages: Edit, and Starter questions: Edit with generateAfter. |
read_all_site_pages | Write. Read every Not read page of a site in the background. Needs Site pages: Edit. |
generate_starter_questions | Write. Ask for starter questions from up to 50 read pages. They arrive switched off unless the site setting or enable switches them on. Needs Site pages: Edit and Starter questions: Edit. |
create_starter_questions | Write. Create or copy up to 50 starter questions. Needs Starter questions: Edit. |
update_starter_questions | Write. Edit the wording, the targeting or the place of up to 50 starter questions. Needs Starter questions: Edit. |
set_starter_questions_enabled | Write. Switch up to 50 starter questions on or off. Needs Starter questions: Edit. |
provision_site_from_url | Write. Create a site, its assistant and, on Shopify, its catalog connector from up to 5 storefront addresses. The analysis and the sitemap import run in the background. Needs Sites: Edit and Agents: Edit, and the terms accepted in the dashboard. |
set_site_hosted_page | Write. Switch the hosted page (the AI Storefront) of up to 50 sites on or off and read its link back. Needs Sites: Edit. |
set_site_automation | Write. Change a site's automation settings: automatic starter generation, page-view counting, add-to-cart counting on your pages, automatic reading and its threshold. Needs Sites: Edit. |
set_site_panel_appearance | Write. Set a site's conversation panel: its side, how it opens, and its colours (replacing the stored ones). Needs Sites: Edit. |
list_alerts | List the organization's alerts, open or resolved, each with its kind, severity, its site, the widget, test or connector it concerns for a widget, test or connector alert (an orders alert concerns the site only), and for a tag alert when the tag was last seen and checked. Open to every member. |
set_site_tag_monitoring | Write. Turn a site's hourly check of the tag on or off. Turning it off closes the site's open alert. Needs Sites: Edit. |
check_site_tag | Write. Check now whether the tag is on a site's homepage: loads the page once and opens or closes the site's alert as the hourly check would. Needs Sites: Edit. |
check_connector | Write. Check now whether a connector still answers: calls its server once, records the outcome and opens or closes the connector's alert as the hourly check would. At most once a minute per connector. Needs Connectors: Edit. |
list_site_holdouts | Read. A site's holdout tests, newest first, the running one included: dates, planned duration, each group's sessions and add-to-cart share, the effect, the result, the mobile effect and the validity. Filters: status, outcome, from, to, cursor, limit (up to 50, 25 by default). Open to every member. |
get_site_holdout | Read. A site's holdout test: the running one, else the latest ended one. Its state, each group's sessions and add-to-cart share, the progress to the traffic floor, and the effect or the detection limit. Open to every member. |
get_storefront_activity | Read. When a site last received an add-to-cart and an order from its storefront, and an order from an order webhook. Each time is null until the first one. Open to every member. |
start_site_holdout | Write. Start a holdout test on a site: half of its sessions are served no assistant. Needs Sites: Edit. |
extend_site_holdout | Write. Extend the site's running holdout test by 7, 14 or 28 days. Needs Sites: Edit. |
stop_site_holdout | Write. Stop the site's running holdout test. Needs Sites: Edit. |
start_agent_experiment | Write. Start an A/B test of an agent's live version against another saved version of the same agent. Needs Agents: Edit. |
stop_agent_experiment | Write. Stop an agent's running A/B test. The live version stays live. Needs Agents: Edit. |
promote_agent_experiment | Write. Put the candidate of a running A/B test live and end the test as promoted. Needs Agents: Edit. |
set_site_resume_button | Write. Change where a site's Panel reduced state button sits and how it looks: side, offsets, colours, icon, size, corners, shadow. Needs Sites: Edit. |
discover_site_pages | Write. Start a sitemap import for a site. Needs Site pages: Edit. |
exclude_site_pages | Write. Add up to 50 path rules that keep pages out of discovery, removing the pages they match. Needs Site pages: Edit. |
delete_object | Write. Delete up to 50 pages, starter questions or page exclusions. Needs Site pages: Edit for pages and exclusions, Starter questions: Edit for questions. |
Every result carries asOf, the time the server read the data, in UTC. The server tells the assistant to resolve "last week" or "yesterday" against it. Every conversation names its site and carries a dashboard link, so you can open it from the answer. The text of a conversation also gives the exact saved state of the agent version that handled it, as the dashboard names it (V2.1), with its id, and list_sites gives the id of the live version (or, for an offline agent, of its latest version), so a client that reads only text can pass either to get_agent_version. list_sites also gives, for each site, its automation settings: whether starter questions are generated automatically, whether generated questions are written switched on, whether page views are counted, and whether discovered pages are read automatically, with the threshold. It also gives tagMonitoringEnabled, whether the hourly tag check is on, hostedPage (enabled, and its link while it is on, null otherwise), defaultAgentId (the agent answering on the site, null when none does) and analysisState (see Create a site from its address). It also gives the Panel reduced state button's settings, each null when left at its default; the text names only the ones set on the site, or reads "default".
Find conversations
search_conversations takes the same filters as the REST conversation list, written as JSON instead of query parameters, and returns the same conversations for the same filters.
| Field | Does what |
|---|---|
siteId | Restrict the search to one site. Omit it to search every site of your organization. |
from, to | Creation time, ISO 8601 with an offset. from is inclusive, to is exclusive. |
channel | web, hosted or playground. |
agentId | An agent id from list_sites. |
language | The language the conversation was held in. |
device | Conversations started on this device: desktop, mobile, tablet or unknown. unknown also covers every hosted and playground conversation and any with no recorded start. Safari on iPadOS presents a desktop browser: those iPads now count as tablet, while iPad conversations started before the detection shipped (see the changelog) stay desktop. |
feedback | positive or negative: at least one shopper rating of that kind. |
keywords | Terms that must all appear in the conversation title. They are not matched against the messages. |
labels | Label tokens (<label>:<value>) in all (every token), any (groups of tokens: one match per group) and none (true/false tokens to exclude). |
quality, service, trust | Bounds on the three scores, each as { "min": 0.5, "max": 1 }, from 0 to 1. |
labelStatus | labeled, pending, failed or not_eligible. |
pageType | The kind of page the conversation started from: home, product, category, content or blog. checkout is not a page type and the tool refuses it as invalid input. A conversation with no recorded page never matches, and neither does one recorded as checkout before it was removed. Only a type your tag declares is recorded: the type your site's pages hold for an address is used to target widgets and is never stored on a conversation. |
productId, categoryName | The exact product id or category name of the page the conversation started from, as your tag declared it (1 to 200 characters). |
entryWidgetId | An engagement widget id (ewgt_...): conversations opened from that widget, whichever version of it. |
agentVersionIds | Up to 20 agent version ids (agtv_...): conversations held by any of those versions. A search result gives the id of the version that handled it. Applies together with agentId. |
commerce | Commerce outcomes addedToCart, reachedCheckout, purchased, each true or false. See Commerce outcomes. |
limit | Page size, 25 by default, at most 100. |
cursor | The nextCursor of the previous page. Send it with the same filters. |
count | Also return how many conversations match, capped at 10,000. |
A token the taxonomy doesn't define is refused, and the error names it and points to list_label_vocabulary. The rules for labels.none, score bounds and cursors are the ones on Filter and paginate conversations. A field the tool doesn't define is refused, never ignored.
The six fields from pageType down exist only on the MCP tool. The REST conversation list doesn't take them: it refuses them as unknown query parameters. Filters combine: a conversation has to match all of the ones you set. That includes agentId and agentVersionIds: with both, a conversation has to belong to that agent and be held by one of those versions, so a version of another agent matches nothing. The page of origin and the entry widget of each result are in its pageContext and entryWidget, which is where to read a productId or an entryWidgetId to filter on. When a page filter finds nothing, the text adds that a conversation whose page of origin wasn't recorded never matches one.
Commerce outcomes
Every item of a search carries commerce with three outcomes, addedToCart, reachedCheckout and purchased, and the result carries commerceTrackingSince: the time of your organization's first add-to-cart, checkout or purchase recorded, or null if it has none. Only an add to cart the assistant made counts here, not one a shopper made on your own pages.
Each outcome is true, false or null. addedToCart and reachedCheckout read the conversation's own events:
true: an event of that stage was recorded for the conversation.false: the conversation was created at or aftercommerceTrackingSinceand no event of that stage was recorded for it.null: unknown. The conversation was created beforecommerceTrackingSince, or the organization has no commerce event at all. It is neverfalse, because it may well have reached that stage before anything was recorded.
purchased reads orders, by the rule the sales report uses for the assistant's conversion rate. On the same data, the conversations it reports as purchased are the ones that rate counts as converted.
true: an order is credited to the conversation. The order belongs to your organization, carries the conversation's join key, is not a test order, is not cancelled, and was placed within 24 hours of the shopper's last message before it. The conversation must also be one the rate counts: on the web or AI Storefront channel, with at least one shopper message and at least one assistant answer with content. A credited order counts whenever it was recorded, so this can betrueon a conversation created beforecommerceTrackingSince.false: the conversation has a join key and was created at or aftercommerceTrackingSince, and no order is credited to it. That covers an order placed after the 24 hours, a cancelled or test order, and a conversation the rate doesn't count.null: unknown. The conversation has no join key, it was created beforecommerceTrackingSince, or the organization has no commerce event at all. No order could have been matched to it.
Each outcome stands on its own: a purchase doesn't imply a checkout or an add to cart. A purchase event is never read by conversation: an order reaches a conversation only through its join key.
The commerce filter matches exactly the conversations whose field reads the value you ask for. true keeps the conversations that read true. false keeps only the ones that read false. A conversation whose outcome is unknown matches neither.
Checkout events aren't recorded yet. The assistant's adds to cart and your orders are recorded, but nothing in the product writes a checkout event. reachedCheckout is therefore never true today: it reads false on a conversation created at or after commerceTrackingSince and null before. Until your organization records its first add to cart or order, commerceTrackingSince is null, every outcome is null and a commerce filter matches nothing, false included. The search still answers, and the text says so.
No revenue and no order value come back, only the three yes/no stages.
Read conversations
get_conversationreturns the full transcript: each message has arole(shopperorassistant), an orderedcontentlist of typed blocks (text, product cards, questions, quick replies, hand-off, files, tool calls) and the shopper'sfeedbackrating, ornullif there is none. It also returns the conversation's site, agent, channel, language, device, page of origin, entry widget, message count, duration, product engagement, label status and label summary. This is the shape Get a conversation returns, plus the site's name and the dashboard link. It also listsattributedOrders, the orders carrying the conversation's join key: each with itsorderRef,placedAt,lastShopperMessageAt,currency,netAmount(minor units),refundedandstatus(credited,cancelled,out_of_windoworexcluded), the same list the conversation's Result section shows. The text has one line per order, or says no order is linked to the conversation. Your client should ignore block types it doesn't know.get_conversationsis for comparing or reviewing a set. The transcripts are compact: text is kept, and every other block becomes a one-line marker such as[product cards: 3 shown (...)]. Each conversation carries its label record, ornullwhen it isn'tlabeled. An id that is unknown, or that belongs to another organization, comes back innotFound. The call refuses more than 20 ids.- Tool calls. An assistant message carries a
tool_callblock before the block that tool produced, one per call the assistant made, from AISA's own tools or from one of your connectors. It holds the tool'sname, itssource(owned,connectororinstructions), theconnectorit came from, whether the callsucceeded,failedor wasrefused, itsinput, and thepagesof your site it read (their address and the date AISA read them). The input is bounded: each value is cut at 200 characters and the whole at 2,000,inputCutsays when anything was cut, and the value of a key that names personal or credential data (an email, a phone number, a name, an address, a token, a card) is replaced by[redacted]. The result of a tool is never exposed, only what the shopper saw of it in the blocks that follow. A call still running has no block yet. Inget_conversationsthe block becomes a marker such as[tool call: search_site_pages succeeded; input {"query":"returns"}; pages https://shop.example/pages/returns (read 2026-10-05)]. get_conversation_labelsreturns the label record as the REST labels endpoint does. Theevidenceof an answer lists message ids. To read those messages, useget_conversation.
If an id doesn't exist, or belongs to a conversation outside your organization, the tool returns an error. It won't tell you which case it was.
Read a report
get_report returns one of the dashboard's reports for one site, from the same report functions the dashboard pages read.
| Field | Does what |
|---|---|
siteId | Required. A site id from list_sites. Reports are per site. |
report | Required. conversations, quality, engagement, starter_questions, add_to_cart, add_to_cart_insights or sales. |
from | Required. The first day, YYYY-MM-DD, UTC, included. |
to | Required. The last day, YYYY-MM-DD, UTC, included. |
compare | Also read the previous period, of the same length and ending the day before from. Not available for starter_questions, add_to_cart and add_to_cart_insights. Available for sales. |
currency | add_to_cart, add_to_cart_insights and sales only. The ISO 4217 code to read: three letters, any case (EUR). add_to_cart and add_to_cart_insights: left out, every currency has its own row. sales: left out, the currency with the most orders in the period. |
device | starter_questions, add_to_cart and add_to_cart_insights only. Count only this device: desktop, mobile, tablet or unknown. One value. On the add-to-cart reports it is the device each event recorded. |
timeZone | add_to_cart_insights only. The IANA time zone the hours of the day are counted in, such as Europe/Paris. UTC by default. |
sort | starter_questions only. impressions (default), clicks or rate. It orders the whole result, not just the page. |
order | starter_questions only. asc or desc. desc by default. |
limit | starter_questions only. The page size, 1 to 100, 50 by default. |
cursor | starter_questions only. The nextCursor of the previous page. Send it with the same other inputs. |
A period can span at most 366 days. A to before from, a day that doesn't exist (2026-02-30), a compare on starter_questions, add_to_cart or add_to_cart_insights, currency on any report but add_to_cart, add_to_cart_insights and sales, device on any report but starter_questions, add_to_cart and add_to_cart_insights, timeZone on any report but add_to_cart_insights, or sort, order, limit or cursor on any report but starter_questions are refused with a message that says what to change.
What each report returns:
conversations: the total, average messages and duration per conversation, the assisted rate (the share of conversations where the assistant used a tool), conversations per day or hour, per agent, per language and per UTC hour, tool usage, and product-card impressions and clicks. The text also gives the volume week by week (Monday to Sunday, UTC, with the first and last week cut to your period and labeled with their first and last day) and, for a period of 14 days or fewer, day by day. Withcompare, the previous period gets the same lines. Thevolumefield of the result holds every day.quality: ratings, positive and negative counts, the satisfaction rate, the share of rated conversations with a negative rating, ratings per day or hour, negative ratings by category and ratings per agent. The rating comments and the conversation titles of the dashboard's "recent negatives" list aren't included.engagement: the widget funnel, the engagement rate, a split by device and opens by page type. Thesummaryholdsexposed(sessions the tag was active in),loaded(sessions where a widget was applied and eligible on a page),mounted(sessions where a widget was inserted in the page),views(sessions that saw a widget),opened(sessions that opened the conversation from a widget),engaged(sessions that did both),started(sessions where the shopper sent a first message) andengagementRate.engagementRateisengagedoverviews, the unrounded ratio (0.0701, not 7.1%), ornullwhen no session saw a widget. The text form shows it with one decimal, rounded up, as the dashboard does. EachbyDeviceentry is{ device, views, opened, engagementRate }, and a device with no widget view has no entry.started,loadedandmountedhave a start date:startedis counted from the date the result gives instartedCountedSince, andloadedandmountedare exact from the date inwidgetLifecycleExactSince, before which they count only the sessions that saw a widget. Earlier days read low. The rate does not depend on any of them.starter_questions: one page of the questions shown in the period, each with itsid, impressions, clicks and click rate, in total and per surface, plusmatching(how many questions were shown at least once, whatever the page),nextCursorandnotShownCount(the questions of the library with no impression). The label is the question in the site's default language, or its first language if that one is missing. Theidis the onelist_starter_questionsand the REST API use.siteClickRateis the site's rate over the whole period, not over the page.
Starter questions are now paged
A starter_questions call with none of the new inputs used to return every
question shown in the period. It now returns the first page: at most 50
questions, most shown first, plus a nextCursor. A client that read the whole
list from one call must follow nextCursor (the text of the result says so),
passing the same from, to, device, sort, order and limit with it.
nextCursor is null on the last page.
device counts one device only, as on the REST endpoint. The add-to-cart reports take it too. For several devices, call once per device. A cursor is bound to the period, the device and the sort it was issued for.
add_to_cart: see Add-to-cart counts below.add_to_cart_insights: see Add-to-cart insights below.sales: see Sales below.
Add-to-cart counts
The add_to_cart report returns the result under addToCart. It counts add-to-cart events, one per cart line added: a shopper who adds one product with a quantity of 3 is one event, not three. Playground conversations are never counted.
| Field | Meaning |
|---|---|
panel | { count, trackingSince }. Adds the assistant made in the conversation panel, on the web tag and on the AI Storefront (hosted conversations are included). |
storefront | { count, trackingSince }. Adds shoppers made on your own pages, reported by the Shopify pixel. |
total | panel plus storefront. |
withConversation | The panel adds, plus the storefront adds whose session key had a conversation started on the same site before the add. Divide it by total for the assistant's share. |
withoutConversation | The storefront adds not in withConversation, including every one that carries no session key. |
amounts | The amount of the add-to-carts that carry one, one row per currency (see below). Empty when none carries an amount. |
granularity, series | The same counts over time. granularity is hour on a period of two calendar days or fewer and day beyond, UTC, as for the other reports. Every bucket is present. A point has date, panel, storefront, total, withConversation and withoutConversation. |
trackingSince is the ISO 8601 instant of the first event recorded for that origin on the site, or null when there is none yet. A first period that starts after it is complete. One that contains it is partial, so don't read it as a drop.
A null count means not measured, never zero. An origin's count is null while the site has no event of that origin or the period ends before the first one. total, withConversation and withoutConversation are null unless both origins are measured, because a total missing one side would read as the assistant making 100% of the adds. In the series the same rule applies per bucket, and a bucket that has not started yet is null too. A site without the pixel therefore has a null storefront, and a null total. The text form leaves those buckets out of its summary and says so.
Both origins are Shopify only. The panel adds come from the assistant's successful cart write through a Shopify connector, and a failed or unreadable write records nothing. The result has no compare and no previous period: read the earlier period with a second call. The same numbers are on REST, as Get a site's add-to-cart counts.
Amounts. Each row of amounts is { currency, total, withConversation }. currency is the ISO 4217 code, upper case. total and withConversation are each { amountMinor, addToCartsWithAmount } or null:
amountMinoris the sum of the amounts in the currency's minor unit (2 decimals for EUR, so 1250 is 12.50 EUR; 0 for JPY). Your client formats it.addToCartsWithAmountis how many add-to-carts carry an amount in that currency. The others are counted in the totals above and not valued.totalfollows thetotalcount andwithConversationfollows thewithConversationcount (same add-to-carts, so an amount and a count never disagree on which adds had a conversation). Each isnull, never zero, while its count isnull(not measured).
Rows are ordered by most add-to-carts with an amount first, then by currency code. There is never a sum across currencies. With currency, only that currency's row is returned, and an empty amounts means that currency has no amount in the period. An add-to-cart with no amount or no currency appears in no row. The amount is the value of what was added to carts, not revenue. An amount the merchant's pixel reports is declared by the pixel and not verified. withConversation is an indicator, not what the assistant added on top of what would have happened anyway. The text form lists one line per currency, with the number of add-to-carts each figure covers.
Add-to-cart insights
The add_to_cart_insights report returns the result under addToCartInsights. It is what the Carts page of the Sales report shows beyond the counts, and the same read as Get a site's add-to-cart insights on REST. It takes device, currency and timeZone. It has no compare: read the earlier period with a second call.
The groups are of sessions and carts that had a conversation, not of what the assistant added. Shoppers who start a conversation are not a random sample, so read the gap as an observation, not as an effect.
| Field | Meaning |
|---|---|
rate | { withConversation, withoutConversation }, each { sessions, added }. Counts only: divide added by sessions for a rate. withConversation is the sessions in which a conversation started. A session added when the assistant made an add in the panel, or an add on your pages was received after its first conversation began. withoutConversation is the sessions where the assistant was shown and no conversation started. A session added when it made an add on your pages. null unless both origins of add-to-carts are measured. |
cartValue | One row per currency, most carts first, never summed across currencies: { currency, withConversation, withoutConversation }. Each group is { carts, medianMinor }. A cart is the add-to-carts that carry the same cart token, valued by the sum of its lines' amounts in the currency, and with a conversation when one of its lines is. medianMinor is in the currency's minor unit, null for a group with no cart. Both groups are null while the counts are not measured. |
devices | { device, count } per device, highest first. |
hours, timeZone | 24 add-to-cart counts, hour 0 to 23, zero-filled, in timeZone (UTC by default). |
priceBands | Per currency, the add-to-carts with an amount by unit price (the amount divided by the quantity added), in five bands of major units: min included, max excluded, max null on the top band. The edges are 0, 25, 50, 100 and 200. |
amountsSince, cartTokensSince | The ISO 8601 instant of the first add-to-cart that carries an amount, and the first that carries a cart token, null when there is none. They do not follow device. |
rate, devices, hours and priceBands are null, not zero, while one origin of add-to-carts is not measured for the period. An add-to-cart with no cart token is in no cart, and a line with no amount or no currency adds nothing to a cart's value. With currency, cartValue and priceBands keep that currency's row. The text form gives every count behind a figure.
Sales
The sales report returns the result under sales: what your site sold over the period, what the assistant is credited with, and the same over time. It is the same read as the dashboard's Sales report and Get a site's revenue and the assistant's share on REST. compare is available.
Revenue is attributed, never incremental: an order counts for the assistant when it follows a conversation within windowHours (24 hours by default, last touch). Amounts are integers in the minor units of currency (cents for EUR), net of recorded refunds and cancellations, after discounts and before shipping. They are never added across currencies. currency picks one. Without it, the currency with the most orders is used, and currencies lists every one the period holds.
| Field | Meaning |
|---|---|
windowHours | The attribution window, in hours. |
currency, currencies | The currency of every amount (null when the period holds no order) and the currencies the period has orders in, the one with the most orders first. |
site | { orders, revenue, aov } over every recorded order of the currency, assisted or not. A cancelled order is not counted in orders. aov is null with no order. site is null when the period holds no order. |
assistant | The same shape, over the orders credited to the assistant. null means not measured, never 0. |
conversationRate | The assistant's conversion rate: { status: "not_measured" }, { status: "no_conversations" } or { status: "measured", rate, numerator, denominator }, with rate between 0 and 1. |
previous | With compare, { currency, site, assistant, conversationRate } for the previous period, read in the same currency as currency. site and assistant are null when the previous period has no order in that currency. null otherwise. |
granularity, series | hour on a period of two calendar days or fewer, day beyond, UTC. Every bucket is present. A point has date, siteRevenue, assistantRevenue and conversionRate. |
A currency with no order in the period is replaced by the currency with the most orders: read currency in the result to see which one you got. assistant is null until the site has started a conversation that carries a join key, because no order can be credited before then. The site's figures are returned anyway. conversationRate reads not_measured until the site has a join key and a recorded order. A bucket that has not started yet has null revenues. In series, conversionRate counts a conversation in the bucket it started, so a past bucket can still rise when an order lands later, and it is null when there is nothing to divide. Amounts in the text form read as minor units, for instance 12000 minor units of EUR.
Volume per day or per hour
The volume field of the conversations, quality and engagement results has a step, granularity. It is hour when the period covers two calendar days or fewer (24 or 48 points), and day for a longer one, as the dashboard's charts do. The step follows the period, you can't choose it. Whole UTC days are always read, never a sliding 24 hours.
| Report | Shape of volume |
|---|---|
conversations | { granularity, current: [{ date, count }], previous: [{ date, count }] or null }. previous is null unless compare is set, and has the same step. |
quality | { granularity, points: [{ date, positive, negative }] } |
engagement | { granularity, points: [{ date, exposed, views, opened, started }] } |
date is a UTC day (2026-09-21) when granularity is day, and the ISO 8601 instant at which a UTC hour starts (2026-09-21T07:00:00.000Z) when it is hour. Every day or hour of the period is present, with 0 where nothing happened. An hour that has not started yet (today, on a period that includes it) has null counts, not 0: read it as "no data yet". On a daily series no count is null. In an hourly engagement series each stage is counted in the hour of its own event, so the stages of one hour don't form a funnel.
Breaking change to the shape of volume
Before hourly volume, volume was a bare array for quality and engagement
([{ date, positive, negative }]) and { current, previous } for
conversations. All three are now objects carrying granularity, and the
quality and engagement arrays moved under points. There is no known client
of the old shape, so no compatibility layer was kept. A client that read
volume as an array needs updating.
Days and hours in the result are UTC (the dashboard's hourly charts show them in your own time zone), and the result says timeZone: "UTC". The conversations and quality reports count the Web and AI Storefront channels and leave out the Playground, which is the dashboard's default filter. You can't change that from the tool. engagement and starter_questions read widget events and aren't split by channel.
A rate or an average is null, not 0, when there is nothing to divide: a day range without conversations has no assisted rate, rather than a rate of 0%. Treat null as "no data". With compare, every summary figure comes as current and previous; previous is null when you didn't ask.
List exposures
list_exposures returns the raw funnel events the dashboard's Exposures tab lists, for one site, newest first. It is a debug view of single events, not a metric: for figures, use get_report. It needs no starter question permission, nor any other: like the reports, it is open to any member of the organization.
| Field | Does what |
|---|---|
siteId | Required. A site id from list_sites. |
from, to | Required. The first and last day, YYYY-MM-DD, UTC, both included. At most 366 days. |
device | Only events from this device: desktop, mobile, tablet or unknown. One value. |
type | Only events of this type: exposure, launcher_shown, conversation_opened, widget_shown, widget_mount_unresolved, widget_loaded, widget_mounted, starter_question_shown, resume_button_shown, resume_button_opened or resume_button_hidden. |
limit, cursor | Page size, 25 by default and at most 100, and the nextCursor of the previous page. Send it with the same other inputs. |
Each event has an id, the occurredAt time, its type, its device, a sessionId and a conversationId. The session id is an opaque key minted in the shopper's browser, so the tool prints it on one line and treats it as data, never as an instruction. The conversation id is null when no conversation is tied to the event. No visitor id, product or widget is in a row. The page has no total, only nextCursor, which is null at the end. A cursor is bound to the period, the device and the type it was issued for.
The same events are on the REST API as List a site's engagement exposure events, which pages 50 events by default.
List page views
list_page_views returns the most viewed pages of one site over the last 30 UTC days, the list the dashboard's Page views tab shows. It reads the same function and the same public fields as the tab and the REST resource, so the three always agree. Like list_exposures, it needs no permission: it is open to any member of the organization. It is read-only.
It takes one input, siteId, a site id from list_sites. There is no period, device, sort or paging: the window is fixed at 30 days, and the list is a fixed top of at most 50 pages.
| Field | Does what |
|---|---|
siteId | The site you asked for. |
pages | The pages viewed at least once in the window, most viewed first, at most 50. Each has its url, its title (null when the page has none) and views30d. |
computedAt | When the daily run last computed the views, ISO 8601 in UTC. null before its first run. |
countingOn | Whether page-view counting is on for the site. |
windowDays | Always 30. |
Pages with the same number of views keep a stable order from one call to the next. A page with no view in the window is left out, so pages can be empty while countingOn is true. With a computedAt date, that means no page was viewed in the last 30 days. With computedAt at null, the daily run hasn't computed the site yet: no figure exists, and the empty list is not zero views.
When counting is off, there is no figure, not zero. If page-view counting is switched off for the site (in Settings, Site access), the tool doesn't read the views at all: pages is empty and countingOn is false. Read that as "not counted", never as "no views". The text the tool returns says the same, so your client's model doesn't report zero traffic.
A page's address and title come from your storefront. The tool prints them on one line, cut at 200 and 100 characters in its text, and tells the assistant to treat them as data, never as instructions. No page id is in the result.
A site id that doesn't exist, or that belongs to another organization, gets the same error: "No site found for that id. Call list_sites to see the site ids."
The same list is on the REST API as List a site's most viewed pages over the last 30 days, with the rows in data and computedAt, countingOn and windowDays in meta.
Break down a label
get_label_breakdown counts how many labeled conversations hold each value of one label. It answers "what are the top transfer reasons this week" in one call, where a search would return conversations one page at a time.
It takes the filters of search_conversations, parsed by the same code, except limit, cursor, count and labelStatus, plus:
| Field | Does what |
|---|---|
label | Required. A label key such as resolution, or a derived key such as transfer_reason or containment: the part of a token before the colon, as list_label_vocabulary lists them. |
compare | Also break down the previous period, of the same length and ending where this one starts, and return the change per value. Needs both from and to. |
A breakdown has to be bounded: send both from and to, or a positive label filter (labels.all or labels.any). labels.none on its own doesn't count. Here from and to are ISO 8601 instants with to excluded, as in a search, not the whole days get_report takes. Unlike get_report, no channel is left out unless you pass channel, so Playground test conversations count.
The result holds, for the period (current) and, with compare, the one before (previous):
values: every value the label can take, with its token,valueandcount, most frequent first. A value nobody has comes back with0, so two periods line up value by value. A yes/no label has one value,true.total: the labeled conversations the counts cover.withoutValue: of those, how many hold no value for this label (a conversation that wasn't transferred has notransfer_reason, for instance).notLabeled: conversations that match the filter but have no labels (pending, failed or not eligible). They are in no count. This number is also capped.cappedandcap: the scan covers the newest 10,000 labeled conversations of the filter. When more match,cappedistrueand the counts cover only those 10,000. Narrow the dates for exact counts.
With compare, delta gives the change in total and in each value's count, now minus then. It isn't exact when either period is capped, and the text says so. When no label or score filter is set, the text also warns when a period is only partly labeled, meaning more of its conversations have no labels than have some (for example 3 labeled and 73 not): the changes then compare unequal samples, so the text calls them apparent and leaves the numbers as they are. Both periods print their instants the same way. A commerce filter works here too, and the result then carries commerceTrackingSince.
A label key the taxonomy doesn't define is refused, and the error points to list_label_vocabulary. The counts agree with search: the count for a token equals the count of search_conversations filtered on that token with the same filters, up to the cap. As everywhere, only labeled conversations are counted: see Labels and the labeled channels.
Read an agent version
get_agent_version shows what one version of an agent runs with, so the assistant can explain how a conversation was handled or what a release changed.
| Field | Does what |
|---|---|
agentVersionId | Required. An agent version id (agtv_...). list_sites gives the id of the live version, or of an offline agent's latest version. The result of get_conversation, get_conversations and search_conversations gives the id of the version that handled each conversation. |
baseVersionId | Optional. Another version of the same agent. The result then also says what changed from it to agentVersionId. |
It returns the version number, its status and the engine's display name, then your instructions in order (each block with its name, slug, type, text and condition), the tools and the capabilities the version enables, and the other versions of the same agent, newest first. Tools here are the assistant's built-in ones. Connector tools aren't listed. Capabilities are attachment (file upload), voice_dictation, quick_replies (suggested replies) and out_of_stock_products (out-of-stock products). The text has a Capabilities enabled: line next to Tools enabled:. The retired suggest_replies tool never appears in the tools list.
The status is the one shoppers get, the same rule as the dashboard: live only while the agent answers on its site with that saved state, offline otherwise. That includes the version of an agent taken offline, and every earlier save of the live version. The other versions, and the base version, carry their status the same way. The stored statuses (draft, candidate, champion, archived) no longer appear in this tool.
The version, the base version and each of the other versions also carry locked and lockedReason. A locked version is kept as it is: a save on it is refused, so changes go into a new version (see Locked versions). lockedReason is live when the version has been live, experiment when it is part of an A/B test, and null when the version isn't locked. Starting an A/B test locks both versions it compares. A version that was already locked keeps its reason, so the live version usually reads live and the candidate experiment. The text says the same: a line under the heading reads either "Not locked" or "Locked" with the reason, and the list of versions marks each locked one, for example V2.1 offline, locked (live) or, for the candidate of an A/B test, V3.0 offline, locked (experiment).
Version numbers and labels
The MCP tools number versions the way the dashboard does. A version is V2; each save on it is a saved state, counted from 0, so its saved states read V2.0, V2.1, V2.2 (see Change history). A named version reads as its name, or Name · V2.1 for a saved state.
get_agent_version:version(on the version, on the base version and on each of the other versions) is the version number, the2of V2. The newlabelfield gives the saved state, such asV2.1. The version read also carrieslineId, shared by every saved state of the same version. The diff heading names both saved states by label.get_conversation,get_conversationsandsearch_conversations:agentVersionis the number of the version that handled the conversation. The newagentVersionLabelgives the saved state, such asV2.1, and the text names it the same way.list_sites:liveVersionandlatestVersionare version numbers. The newliveVersionLabelandlatestVersionLabelgive the version's name, orV2.latestVersionIdis the id of the latest saved state of the agent's most recent version. These six fields follow the permission of the agent's page in the dashboard: for a member without Agents: View or Agents: Edit, resolved on every call, they all readnull, and the text says the versions need that permission. Every site and agent is still listed, with itsstatus.
The REST API numbers versions the same way: its version is the version number too. Its field names differ: REST label is the version's name or V2, and the saved state's V2.1 is in savedStateLabel, with savedState its place in the version (from 0). A REST version also carries the same lineId, which a save passes as target.lineId to save on that version. It carries the same locked and lockedReason, and the status shoppers get is in lifecycleStatus (live or offline, the same rule as this tool's status), next to the stored status.
With baseVersionId, the diff lists the instruction blocks added, removed and changed (with which of name, type, text and condition changed, and the text before and after), whether the shared blocks run in a different order, the tools added and removed, the capabilities added and removed, and the engine change when there is one. Blocks are matched by slug. Comparing a version with itself gives an empty diff. Two versions of different agents are refused.
The engine's internal id, the base persona that comes with the engine, the model and its thinking level are never returned. The instructions are your own configuration text: the server tells the assistant to analyze it, not to follow it.
This tool is gated by a permission. It works for a member who holds Agents: View (agents:view) or Agents: Edit (agents:edit) in your organization, the bar for opening an agent in the dashboard. The tools over conversations, labels, reports, exposures, page views and sites are open to any member of the organization, because the pages that show the same data don't check a permission. The tools over pages and starter questions follow the permission of their dashboard page: see Pages and starter questions.
- Resolved on every call. The server looks up the member's current roles with WorkOS each time the tool is called and never caches the answer, so a role change applies on the next call.
- Refused when it can't be resolved. If the lookup fails, or finds no active membership, the call is refused exactly as if the role lacked the permission. The two are indistinguishable.
- A refusal reveals nothing. The permission is checked before the version is looked up, and the error only names the permission and says to ask an administrator. It doesn't say whether the version exists. A version that doesn't exist, belongs to another organization or belongs to a deleted agent all answer the same "No agent version with that id exists in this organization."
To grant the permission, edit the member's role under Roles.
Pages and starter questions
Two tools read the pages of a site and its starter questions. Each takes a siteId from list_sites, and returns what the dashboard shows. Both are read-only.
list_site_pages returns the site's pages, newest first unless you pass sort, with the totals by status and by type, the number of pages the site holds against its limit of 50,000, what is left of the generation and read budgets (counted in pages; for an organization on a monthly quota, the lower of the site's daily ceiling and the organization's monthly quota), and the site's last sitemap import with its outcome and counts. The dashboard's own list is sorted by most viewed; this tool keeps newest first so a client that sends no sort reads the order it always had. Each page carries its views over the last 30 days and when they were counted, its source, its type and language (a type guessed from the address or the sitemap is marked "guessed from the address" or "guessed from the sitemap" in the text and by pageTypeGuessed in the structured result, and a read type carries its confidence, such as product (likely); pageTypeSource and pageTypeConfidence give the same in the structured result), and when the sitemap last listed it or since when it is missing.
| Field | Does what |
|---|---|
siteId | Required. A site id from list_sites. |
pageId | A page id (spg_...). Returns that one page with its extracted text, canonical address, what decided its type, structured content (facts, titled sections, shopper reviews), the product it declares, how the read reached it (fetch route), how the sitemap listed it, its Shopify product id, evidence and runs. Pass it alone. |
type | product, category, content, blog, home or unknown. A page not read yet matches on the type guessed from its address. |
status | discovered (Not read in the dashboard), pending, reading, read, failed or unsupported. |
language | A language code such as en or fr. Matches the language read, or the guess for a page not read yet. |
source | sitemap (found by a sitemap import), tag (found from shopper traffic) or manual (added by a member). |
missingFromSitemap | true for pages a complete sitemap import no longer listed, false for the others. |
starters | with (pages that have questions), none (those that have none) or generating (generation in progress). Exclusive: a page being generated is only under generating. |
startersGenerated | true for pages that produced questions, false for those that did not. Older boolean: it does not leave out a page being generated. |
lastGeneration | The outcome of the latest generation: written, none_passed, skipped, failed, read or unsupported. |
sort | newest (the default), most_viewed (views over 30 days), address or last_read. |
order | asc or desc. Absent, each sort keeps its own: address ascending, the others descending. last_read keeps never-read pages last both ways. |
includeExclusions | true to also return the site's exclusions (removed addresses and rules, newest first, at most 100) with their counts by kind. false by default. |
q | Text to find in the address or the title. |
limit, cursor | Page size, 25 by default and at most 100, and the nextCursor of the previous page. Send it with the same filters, sort and order. |
list_starter_questions returns the library, by default in the order shoppers get it, with the totals by state and by source and matching, the number of questions the filters leave.
| Field | Does what |
|---|---|
siteId | Required. A site id from list_sites. |
questionId | A question id (stq_...). Returns that one question with its figures per surface and per day. Pass it alone. |
source | manual, ai_generated, ai_generated_edited, or generated for both kinds of generated question. |
state | live, partial, needs_setup or offline. |
verdict | never_shown, not_enough_data, promising, workhorse or underperforming. |
enabled | true for switched on, false for switched off. |
sourcePageId | Only the questions generated from this page. |
appliesTo | { path, language, pageType }: only the questions a shopper would be offered on that page and in that language. pageType is optional. |
search | Text in the question or the message, in any language. At most 200 characters. |
reachesPageType | home, product, category, content or blog: the questions shown on all pages or on that page type. |
language | A language the site serves, with languageMatch: has (default) for the questions with text in it, missing for those without. |
sort, order | position (default), updated, state, click_rate or performance, then asc (default) or desc. Ties keep the library order. |
limit, cursor | As for pages. A cursor is bound to the filters and the sort it was issued for. |
A page's text, its title and its address come from a public web page, and a question's wording is merchant text. The tools deliver them as data, indented, and the server tells the assistant not to follow them. No cost, token or usage figure is in any result.
Both tools are gated like the dashboard pages. list_site_pages needs Site pages: View (site-pages:view) or Site pages: Edit (site-pages:edit). list_starter_questions needs Starter questions: View (starter-questions:view) or Starter questions: Edit (starter-questions:edit). Resolution, refusal and the way a refusal reveals nothing work as for get_agent_version.
Read alerts
list_alerts lists the organization's alerts, as the Alerts page does. It takes state: open (the default), most severe then oldest first, or resolved, the history, most recently resolved first. It checks no permission: every member of the organization can read alerts.
Each alert has its id, kind (tag_missing, widget_mount_failed for an inline widget that is not showing, experiment_guardrail_paused for an A/B test a safety check paused, connector_unavailable for a connector that failed two checks in a row, orders_fall or orders_stopped for a site's orders, widget_engagement_fall for a widget whose engagement rate fell, or quota_conversations, quota_page_reads or quota_generations for a monthly quota), severity (critical or warning), the site (siteId, siteName, siteUrl), subject, openedAt, resolvedAt and resolution (tag_back, monitoring_off, quota_raised, month_rollover, below_threshold, site_deleted, subject_deleted, mount_recovered, widget_disabled, widget_not_inline, experiment_restarted, expired, engagement_recovered or orders_recovered, null while open), and lastSeenAt and lastCheckedAt, the last time the check saw the tag and the last time it ran on the site, set on a tag alert only and null on every other kind. A widget alert, an engagement alert included, names its widget in subject (type widget, id and name, the name kept after the widget is deleted); every other alert has subject null, except a test alert, whose subject has type experiment, the test's id and the widget's name. The text output shows the tag times on a tag alert only. A quota alert has no site and no tag times, and carries no usage figure. An orders alert has a site and subject null. A widget alert carries no share and no session count, a test alert no guardrail name, rate or session count, an orders alert no order count, and an engagement alert no rate, usual level or session count. Alerts open and close by themselves: no tool does either. It is the same data as GET /api/v1/alerts.
Check storefront activity
get_storefront_activity takes siteId and says whether a site's storefront still sends data to AISA, one time per channel. It answers siteId and three times, in UTC:
lastStorefrontAddAt: the latest add-to-cart sent from the storefront, such as by the Shopify pixel. Adds the assistant makes in the panel don't count.lastStorefrontOrderAt: the latest order sent from the storefront, by the Shopify pixel or by your own sender.lastWebhookOrderAt: the latest order sent by the Shopify order webhooks. Test orders count. Refunds and cancellations don't.
Each time is when AISA received the event, not when it happened on your store, and is null until the first one arrives. A time that stops moving while your store is busy points to a channel that stopped sending. The tool answers for any site, whatever its platform or connectors, gives no count (counts come from get_report) and is open to every member. It is the same data as GET /api/v1/sites/{siteId}/storefront-activity.
Write tools
Twenty-four tools change data. They share these rules.
- Done as the member who connected. The write is attributed to that member in Admin activity, under the same action as the dashboard's and with the source
mcp. A connection whose token names no member can't write. - Needs the member's permission, on every call. Each tool names the permission it needs in the tools table. The server resolves the member's current roles with WorkOS on every call, uncached, and fails closed, as for
get_agent_version. A refused write records a blocked attempt in Admin activity and answers an error that names the permission to ask an administrator for. It doesn't say whether the thing you aimed at exists. - Applies at once. There is no draft. A question you switch on shows to shoppers where its targeting matches. A change shows in the dashboard on its next load.
- Batches, one outcome per item. Every write tool except
provision_site_from_url(up to 5 addresses, see its own section),set_site_automation,set_site_panel_appearance,set_site_resume_button,set_site_tag_monitoring,check_site_tag,check_connector,start_site_holdout,extend_site_holdout,stop_site_holdout,start_agent_experiment,stop_agent_experiment,promote_agent_experimentanddiscover_site_pagestakes up to 50 items (50 lines, page ids, question ids, rules or edits) and answers one outcome for each. One bad item never fails the call: it comes back asrejected,skippedornot_foundwith a short reason, and the others go ahead. Each outcome hasitem(the 1-based position in the request),id(the id acted on or created, ornull),status(done,skipped,rejectedornot_found) andreason(nullwhen done). In a list of page or question ids, a repeated id counts once. The text of the result carries every id and figure a follow-up call needs.provision_site_from_urlandset_site_hosted_pagealso answer one outcome per item, with their ownstatusvalues, listed in their sections. - Named by verb, no
actionargument. Each tool does one thing.delete_objectis the single delete tool, taking atypeofsite_page,starter_questionorpage_exclusion. - Confirmation is your client's. A write tool declares its annotations, and a client such as Claude Desktop uses them to ask you before it runs the tool. The tools take no
confirmargument. The annotations are below. - Page text and question wording are data. What a tool returns from a page or a question is delivered as data and never as instructions.
Annotations a client reads, by tool:
| Tool | Destructive | Repeating it changes nothing more | Reaches an outside address |
|---|---|---|---|
add_site_pages | No | Yes | Yes |
refresh_site_pages | Yes | No | Yes |
read_all_site_pages | No | No | Yes |
generate_starter_questions | No | No | Yes |
create_starter_questions | No | No | No |
update_starter_questions | Yes | No | No |
set_starter_questions_enabled | No | Yes | No |
provision_site_from_url | No | Yes | Yes |
set_site_hosted_page | No | Yes | No |
set_site_automation | No | Yes | No |
set_site_panel_appearance | Yes | Yes | No |
set_site_resume_button | No | Yes | No |
set_site_tag_monitoring | No | Yes | No |
check_site_tag | No | No | Yes |
check_connector | No | No | Yes |
start_site_holdout | No | No | No |
extend_site_holdout | No | No | No |
stop_site_holdout | No | No | No |
start_agent_experiment | No | No | No |
stop_agent_experiment | No | No | No |
promote_agent_experiment | No | No | No |
discover_site_pages | No | No | Yes |
exclude_site_pages | Yes | Yes | No |
delete_object | Yes | Yes | No |
The read tools declare themselves read-only and closed to outside addresses. refresh_site_pages is destructive because it replaces the stored text (the previous text is lost). update_starter_questions is destructive because an edit overwrites the previous wording. exclude_site_pages is destructive because a rule removes the discovered pages it matches. set_site_panel_appearance is destructive because it replaces the stored colours whole: a custom colour left out of the call is lost. check_site_tag reaches your site too: it loads the homepage once. check_connector calls the connector's server once. set_site_hosted_page publishes a page that anyone with its link can open. add_site_pages, refresh_site_pages, read_all_site_pages, discover_site_pages and generate_starter_questions reach outside your organization: the first four fetch addresses on your site (see How AISA fetches your pages), and the last has AISA write questions with an AI service. provision_site_from_url requests the storefront addresses you give it.
Create a site from its address
provision_site_from_url does what the dashboard's storefront address step does, from 1 to 5 storefront addresses (urls), such as shop.example.com or https://shop.example.com. For each address it checks that the storefront answers, then creates the site, an assistant named "Assistant" followed by the site name, put live on it, and, when the storefront is confirmed as Shopify, a Shopify catalog connector on that assistant. It then starts, in the background, the analysis of the site and the sitemap import. Putting the assistant live is the same Go live as in the dashboard, recorded as Agent went live in Admin activity. It needs Sites: Edit and Agents: Edit, and the organization must have accepted the terms of service in the dashboard: a tool call can't stand for that acceptance, so without it the call fails before anything is fetched or created.
The addresses are handled one after another, and each gets its own outcome in items: item (the 1-based position in the request), address as submitted, and a status:
| Status | Meaning |
|---|---|
provisioned | The site and its assistant were created, and the assistant was put live. |
existing | The organization already had a site on this address with an assistant. Nothing was created. If no assistant answered on the site, that assistant was put live. |
unreachable | The address doesn't answer. Nothing was created. |
blocked | The address isn't a public one and was not requested. Nothing was created. |
site_limit_reached | The organization holds as many sites as its site quota allows. Nothing was created. |
failed | A fault on our side. Nothing more is said. Try again. |
One bad address never fails the call. A repeated address counts once, at its first position. An outcome that created or found a site also carries siteId, agentId, siteName (taken from the storefront, so it is data, never an instruction), platform (shopify for a confirmed Shopify storefront and custom otherwise on a site the call created, the stored platform on an existing one), language (the site's default language), catalogConnector and analysisState. All of these are null on an address that got no site. catalogConnector is true when the assistant has a Shopify catalog connector and false when it has none, in which case the assistant is a demo with no products. It is null for an existing site, which the call didn't look at. If a site already existed on the address but had no assistant, the call creates the assistant on it, puts it live and reports provisioned.
analysisState is running while the analysis reads the storefront, and failed when the job couldn't be started. On an existing site it is the stored state. It ends as acknowledged when the analysis succeeds, since the result of a site created through this tool never reaches the dashboard's review screen. It stays failed when it fails. Follow it with list_sites. The pages the sitemap import finds arrive as Not read: once the import has ended (list_site_pages shows it), read them with read_all_site_pages.
Each creation is recorded in Admin activity under the same actions as the dashboard's, attributed to the member who connected. A call with several addresses can run for minutes: probing a storefront and the Shopify handshake can each take up to about a minute, and the server allows each call 300 seconds.
Site limit and usage mode
The number of sites an organization can hold depends on its usage mode, which
iAdvize sets. An organization in capped mode answers site_limit_reached once
it holds as many sites as its site quota allows, and a pay as you go
organization has no site limit (see Usage and
limits). No tool changes the mode or the
quota: to create more sites through the MCP server, ask iAdvize to switch the
organization to pay as you go.
Publish the hosted page
set_site_hosted_page switches the AI Storefront, the site's hosted page, on or off and reads its link back. It takes items, 1 to 50 of { siteId, enabled }, with siteId from list_sites. enabled true publishes the page and false takes it down. It needs Sites: Edit, applies at once (no Save step) and is the same change as the Publish your AI Storefront switch: it records AI Storefront published or unpublished in Admin activity, and only when the state actually changes. Repeating a call changes nothing more.
Each site gets its own outcome in items: item, siteId (null when none was acted on), hostedPage ({ enabled, link } after the call, null when nothing was applied) and a status:
| Status | Meaning |
|---|---|
enabled | The page is on. hostedPage.link is its address. |
disabled | The page is off. |
no_default_agent | The page can't be switched on and stays off: no agent answers on the site. Put an agent live in the dashboard first. |
agent_not_live | The page can't be switched on and stays off: the answering agent has no live version. Put a version live first. |
not_found | No such site in this organization. |
invalid_id | The value is not a site id. |
failed | A fault on our side. Nothing more is said. |
One unknown site never fails the call. Switching the page off keeps the site's key, so the same link works again when it is switched back on. The key itself is never returned, only the link. Anyone who has the link can talk to the assistant, with no login: publish it only for a site you want to be reachable. A site created by provision_site_from_url starts with its hosted page off. Read the current state of every site with list_sites. See AI Storefront for what visitors get.
Add and read pages
add_site_pages takes siteId and lines, 1 to 50 addresses or paths of the site, one per entry. It judges them as the dashboard does: https, on the site's own origin, cleaned, repeats ignored. Each line gets its own outcome (accepted with the page id created, ignored or refused with the reason), with the counts. Reading starts in the background: started says whether it was handed over. Follow it with list_site_pages. Adding an address the site already holds changes nothing. Adding an excluded address lifts its exclusion, as in the dashboard. More than 50 non-empty lines is an error and nothing is added.
refresh_site_pages takes siteId, pageIds (1 to 50 page ids from list_site_pages), generateAfter (default false), replace (default true) and enable. It reads a discovered page for the first time and any other page again, within the read budget (the site's daily ceiling and, for an organization on a monthly quota, that quota). Each id gets done (queued), or skipped (it is already being read) or not_found. With generateAfter, starter questions are generated for each page that ends read, within the daily generation budget, and arrive switched off, unless enable is true or the site's switchOnGeneratedStarters setting is on: the dashboard's Read and generate starters. enable left out follows the site setting, read when the call is made. enable false writes them switched off even when the site setting is on. That needs Starter questions: Edit too, checked before any page is queued. With replace on, earlier generated questions from those pages that no one has edited or switched on or off are replaced, whether they are on or off, as generate_starter_questions does; with replace off, they are kept beside the new ones. A question a member switched on or off, edited or hand-wrote is never touched. The answer carries generateAfter, replace and enable as applied (enable is null without generateAfter). Without generateAfter, replace is ignored and questions already generated are not touched.
read_all_site_pages takes siteId only. It reads every Not read page of the site in the background, as Read all pages does in the dashboard, and answers at once with started, toRead (the Not read pages in an enabled language, the upper bound), willReadToday (toRead, or the reads left today when fewer) and reason. It reads the pages found before the call, skips pages in a disabled language and pages that failed, never generates starter questions, and stops when the read budget is spent, the site's daily ceiling or the organization's monthly quota: ask again after the reset (midnight UTC, or the 1st of the month for the quota) for the rest. The reading can take hours. Follow it with list_site_pages. Nothing starts, and reason says why, when there is nothing to read (nothing_to_do, with onlyDisabledLanguages true when the Not read pages are all in a language the site has not enabled), the site's daily ceiling is spent (daily_limit_reached), the organization's monthly page read quota is spent (monthly_limit_reached, capped organizations only), pages of the site are already being read (read_in_progress), or the reading could not be started (could_not_start). The tool takes no confirmation argument: your client's prompt is the confirmation. See Read all pages.
Import pages from the sitemap
discover_site_pages takes siteId and an optional sitemapUrl. Without it, AISA looks for the sitemap in robots.txt, then at the usual locations. It answers at once with the import (its id, state and counts so far) and runs in the background. Pages it finds arrive as discovered and are read only with refresh_site_pages or by automatic reading. Nothing starts, and refusal says why, when an import of the site is already running (discovery_already_running) or when sitemapUrl is not on the site (sitemap_not_on_site, no request made to it). Read the outcome with list_site_pages, which carries the last import. See Import from the sitemap.
Keep pages out of discovery
exclude_site_pages takes siteId and rules, 1 to 50 path patterns without the domain, such as blogs/* or */cart (* matches any run of characters, one leading / is removed). Each rule removes at once the pages a sitemap import or shopper traffic found whose path it matches, and no later import or traffic run adds them back. Pages added by hand are never removed. Their starter questions stay. Each rule gets done with the number of pages it removed, skipped (already_excluded when the site holds it, duplicate when it repeats an earlier rule of the call) or rejected (not_a_valid_rule, too_long). A site holds at most 50 rules: a call that would pass that rejects every new rule with rule_limit_reached and changes nothing. List the rules with list_site_pages and includeExclusions, and remove one with delete_object. See Exclusions.
Generate starter questions
generate_starter_questions takes siteId, pageIds (1 to 50 ids of read pages), replace (default true) and enable (optional). Each page gets done (accepted) or skipped with why: for example not_read_yet, language_not_enabled, daily_limit_reached or monthly_limit_reached. A page of any type qualifies once it is read: home, product, category, content, blog and pages of unknown type. A page that was marked unsupported before every type was read can still answer content_page until it is read again. The answer carries the generation budget left, in pages: the lower of the site's daily ceiling and, for an organization on a monthly quota, what is left of that quota. When it is the monthly quota that refuses, the tool says the monthly limit is reached and the budget line reads "this month". The work goes on in the background, and the questions arrive switched off by default: find them with list_starter_questions (source ai_generated, enabled false), read them, then switch them on with set_starter_questions_enabled. With enable true, or with enable left out while the site's switchOnGeneratedStarters setting is on, they arrive switched on and are live on their pages as soon as they are written: your client should ask you first. enable false writes them switched off whatever the site setting says. The answer carries enable as resolved for the call. With replace on, the questions generated earlier from these pages that no one has edited or switched on or off are deleted when new ones are written, whether they are on or off.
This tool needs both Site pages: Edit and Starter questions: Edit.
The limits are the dashboard's. Each site has a daily ceiling of 25,000 page reads and 12,500 generated pages, counted in UTC and resetting at midnight UTC. An organization in capped mode also has a monthly quota of page reads and starter generations, set by iAdvize, that resets on the 1st of the month (UTC). The lower of the two applies, and a refusal says which one: daily_limit_reached or monthly_limit_reached. In pay as you go mode only the daily ceiling applies. See Limits and Usage and limits.
Create, edit and switch starter questions
create_starter_questions takes siteId and items, 1 to 50. An item is either a new question or a copy, never both.
| Item field | Does what |
|---|---|
texts | The wording per language code the site serves: { "en": { "label": "...", "message": "..." } }. At least one language. label is up to 60 characters, message up to 500 and optional. |
targeting | { mode, pageTypes, urlPatterns } with mode one of all_pages, page_types or url_patterns. All pages when omitted. |
enabled | Switched on at once. true by default. |
duplicateOf | A question id of this site to copy to the head of the library. Cannot be combined with the other fields. The copy is written by you. |
New questions go to the head of the library in order, so the last item ends up first. A question created through the tool is always written by you: no field sets its source. A language the site does not serve is refused for that item. So is a question with a * URL pattern once the site holds 100 of them, switched on or off: the item is rejected with the reason wildcard_question_limit_reached and nothing is written for it. Each outcome carries the question as created, with its id.
update_starter_questions takes siteId and items, 1 to 50 edits. Each names a question id and at least one of texts (wording per language, null to remove a language, languages not named are kept), targeting (replaces the whole targeting) and moveBy (a non-zero whole number of places, up to 100: positive moves it later, negative earlier). It doesn't switch a question on or off. An edit that gives a question a * URL pattern is rejected with wildcard_question_limit_reached once the site holds 100 such questions. The first edit of a generated question's wording or targeting marks it AI, edited, as in the dashboard. Each outcome carries the question as it is after.
set_starter_questions_enabled takes siteId, ids (1 to 50 question ids) and enabled. This is the step that publishes generated questions: read them first.
Change the automation settings
set_site_automation takes siteId and at least one of these, and leaves the others as they are:
| Field | Does what |
|---|---|
enabled | Automatic starter generation for pages the site reads. |
switchOnGeneratedStarters | Whether generated questions are written switched on, live at once with no review, or switched off, for review. Off by default. It changes only the questions written from then on. |
pageViewCountingEnabled | Counting page views per page and day, with nothing that identifies a shopper, to rank pages and find new ones. |
storefrontCartCountingEnabled | Counting the add-to-carts shoppers make on your own pages and the orders they complete, reported by the Shopify pixel. On by default. Off, the pixel's adds and orders are dropped; the assistant's own adds and the webhooks' orders are still counted. |
autoReadPages | Reading discovered pages automatically once a day, most viewed first, within the daily read budget. On by default. |
autoReadMinViews | The views over 30 days a discovered page needs to be read automatically, a whole number from 0 to 1,000,000. 10 by default. 0 makes every discovered page eligible, read most viewed first, or oldest first when page views are not counted. |
It answers every setting as it is after the call, and changed, the settings the call wrote. Each change has its own audit entry. It needs Sites: Edit, as the Site access settings tab does. Each change applies at once, to what happens from now on. list_sites gives the current values.
Set the panel appearance
set_site_panel_appearance takes siteId and any of three settings, as the Appearance page sets them. Each is optional, and one left out stays as it is:
panelPosition:rightorleft, the side the embedded panel docks to.panelBackdrop:falseopens the panel alongside the page (the page stays visible and usable),truewith focus on the chat (the page dimmed and paused). See Choose how the panel opens.panelColors: the colours of the conversation panel.
The side and the opening mode apply on the storefront's next page load. A call that changes either records one audit entry naming what changed, and a call that changes neither records nothing. A call with none of the three writes nothing and answers the site's current settings.
panelColors replaces the stored colours whole: give every colour to keep, and null clears them all. A colour left out follows its default rule, derived from the site's brand colours.
| Group | Colours |
|---|---|
panel | background |
actions | fill, text, hover, border |
visitor | fill, text |
highlights | fill, text |
assistant | text |
links | color |
suggestions | fill, text, border |
A value is a brand reference (primary, secondary, text for the font colour, background) that follows later brand changes, a #rrggbb hex, or none, on fills and borders only. Any other key or value fails the call and nothing is written. It answers panelColors as stored after the call, panelPosition and panelBackdrop after the call, changed, the colour groups it changed, which one audit entry names (empty when no colour changed, and then no colour entry is recorded), and changedDisplay, the display settings it changed (position, backdrop, or empty). The colours apply on the panel's next load, with nothing to publish, and the Appearance page shows them on its next load. It needs Sites: Edit. list_sites gives the current colours, null when none is set, and the current panelPosition and panelBackdrop.
Change the Panel reduced state button
set_site_resume_button changes the Panel reduced state button, the floating button that brings a shopper back to a conversation in progress. It takes siteId and at least one of these, and leaves the others as they are. null returns a setting to its default:
| Field | Does what |
|---|---|
position | The side of the screen: left or right. right by default. |
offsetBottom | The distance from the bottom of the screen, 0 to 200 px. 20 by default. |
offsetSide | The distance from the side of the screen, 0 to 200 px. 20 by default. |
offsetBottomNarrow | The distance from the bottom on screens narrower than 768 px, 0 to 200 px. Not set by default: offsetBottom then applies at every width. |
offsetSideNarrow | The distance from the side on screens narrower than 768 px, 0 to 200 px. Not set by default: offsetSide then applies at every width. |
colors | background, icon and border, each a #rrggbb colour, a brand colour that follows the site's branding (primary, secondary, text, background), none, or null for its default. icon can't be none. colors: null returns all three to their defaults. |
icon | sparkle (default), ai_bubble, minimal_bubble, chat, message or question. |
size | sm, md (default) or lg: 48, 56 or 64 px. |
radius | none, sm, md, lg or full (default). |
shadow | none, sm, md (default) or lg. |
The defaults are those of a chat bubble with no appearance set: see the Brand settings for what each colour's default is. It answers every setting after the call (null for one left at its default) and changed, the settings the call wrote, empty when every value given was already set. A call that changes something records one Branding changed entry in Admin activity, the dashboard's action for the same card. It needs Sites: Edit, as the Brand tab does. The change reaches the storefront on the next page load. list_sites gives the current values.
Switch tag monitoring
set_site_tag_monitoring turns the hourly check of the tag on or off for one site. It takes siteId and enabled. When it is on, AISA loads the site's homepage every hour, and if a tag that was seen before is gone it opens an alert and emails the organization's admins. When it is off, nothing is checked, no alert opens and no email is sent, and the site's open alert is closed.
It answers siteId, siteName and tagMonitoringEnabled, the setting after the call. It needs Sites: Edit, applies at once, and records one Tag monitoring changed entry in Admin activity, the same as the dashboard switch. It doesn't return what the check last saw or the alerts: read the setting with list_sites and the alerts with list_alerts.
Check a site's tag now
check_site_tag takes siteId and runs the same check as Check now on the Installation tab and the REST endpoint: it loads the site's homepage once, records what it found, and opens or closes the site's alert as the hourly check would. If the first load misses the tag it loads the page a second time first.
It answers siteId, outcome and alertOpen. outcome is present (the tag is in the page), absent (it is not) or unverifiable (the page could not be read, so nothing was decided). alertOpen says whether the site has an open tag alert after the check.
It needs Sites: Edit, changes no setting and records no entry in Admin activity. A site can be checked once a minute, counting the hourly run too: a call inside that minute fails and says how many seconds to wait. It also fails when tag monitoring is off or the site has no address; switch it on with set_site_tag_monitoring.
Check a connector now
check_connector takes connectorId, the subject.id of a connector_unavailable alert from list_alerts. It runs the same check as Check now on the connector's page and the REST endpoint: AISA calls the connector's server, records the outcome, and opens or closes the connector's alert as the hourly check would. The alert opens at the second failed check in a row, counting the hourly ones, and closes at the first success. When the call opens the alert, your admins get the alert email.
It answers connectorId, answered (whether the connector answered this check), checkedAt and alertOpen (whether the connector has an open alert after the check). It never returns the server's error text, an address or a token.
It needs Connectors: Edit (connectors:edit), changes no setting and records no entry in Admin activity. A connector can be checked once a minute, counting the hourly check too: a call inside that minute fails and says how many seconds to wait, and the connector is not called. An unknown id, a deleted connector and another organization's connector all fail with the same "No connector ... found" message. A connector no live agent uses can be checked, and its outcome never opens an alert.
Start, extend, stop and read a holdout test
list_site_holdouts takes siteId, and optionally status, outcome, from and to (ISO 8601 instants on the start date), cursor and limit. It answers runs (the same fields as GET /api/v1/sites/{siteId}/holdouts), matching and nextCursor. get_site_holdout also takes an optional holdoutId from that list and then returns that test in detail, like GET /api/v1/sites/{siteId}/holdouts/{holdoutId}, in run. An id that is not a test of the site is a not-found.
get_site_holdout, start_site_holdout, extend_site_holdout and stop_site_holdout answer the site's latest holdout test: siteId and holdout, which is null for a site that never had one. holdout has the same fields as GET /api/v1/sites/{siteId}/holdout, including the planned end, the forecast and, per group, the add-to-cart events and the value added. The text of the answer carries each group's sessions, add-to-cart share and the verdict line.
get_site_holdout and stop_site_holdout take only siteId. get_site_holdout reads and is open to every member. It also returns startOptions, the same as GET /api/v1/sites/{siteId}/holdout/start-options: the durations 3, 7, 14 and 28 days with the sessions per group and the smallest gap each could confirm on this site's traffic, and the recommended one. The write tools answer startOptions as null. Reading a running test also checks that its split is still even, and ends the test as invalid when it is not.
start_site_holdout takes siteId and an optional durationDays (3, 7, 14 or 28). Without it, the start uses the recommendation, and 14 days when nothing can be estimated. extend_site_holdout takes siteId and days (7, 14 or 28) and moves the planned end later.
The three write tools need Sites: Edit and apply at once. A start records Holdout test started in Admin activity, a stop Holdout test stopped, and an extension its own entry. They take no share: the split is always 50/50. A start refused because a test already runs, because a widget experiment runs on the site, or because the Shopify pixel is not recording, comes back as a tool error with the reason. So does an extension of a test that has ended, reached its planned end or has none, and a stop when no test runs. A start hides the assistant from real shoppers, so confirm with the person first that their storefront does not open the assistant from its own code.
Start, stop, promote and read an agent experiment
These four tools drive an A/B test of two agent versions. get_agent_experiment takes either agentId (agt_..., from list_sites), which answers the agent's running test, else its latest, or experimentId (agxp_...), never both. start_agent_experiment takes agentId, candidateVersionId (agtv_..., another saved version of the same agent) and an optional maxConversationsPerVersion (an integer, at least 1,000). stop_agent_experiment and promote_agent_experiment take experimentId. None takes a split or a floor: the split is 50/50 and the system sets the floor.
Each answers agentId and experiment, the same fields as GET /api/v1/sites/{siteId}/agents/{id}/experiments/{experimentId}, with the daily series. experiment is null for an agent that never had one. The text carries the ids and figures a follow-up call needs: each version's conversations, conversion rate and orders, the verdict line, and the limits of the measure. A result that is not conclusive is never worded as "no difference".
get_agent_experiment needs Agents: View or Agents: Edit. The three writes need Agents: Edit, apply at once and record Agent experiment started, Agent experiment stopped and Agent experiment promoted in Admin activity. Refusals come back as tool errors the assistant can act on: a test already running, a start refused with its reason (the codes of agent_experiment_refused), a stop or promote on a test that already ended, and a promote on a candidate that is not ready to go live, which leaves the test running. A promote changes what shoppers are served whatever the verdict says, so confirm it with the person first. The same operations over REST: list, start, get, stop and promote.
Delete pages, questions and exclusions
delete_object takes type (site_page, starter_question or page_exclusion), siteId and ids (1 to 50 ids of that type). Deletion can't be undone. An id the site doesn't hold comes back not_found.
site_page(spg_...): deleting a page keeps the questions it produced, with no source page. A page that a sitemap import or traffic found leaves its address as an exclusion, so discovery does not add it back.starter_question(stq_...): a deleted question stops showing to shoppers at once.page_exclusion(spgx_..., fromlist_site_pageswithincludeExclusions): discovery may find those pages again from the next import or traffic run. Nothing is restored at once.
Errors
A failure comes back as a tool error, not as a broken connection, with a message the assistant can act on. A wrong input names the problem. A conversation or site that isn't visible to you answers one message whether it is unknown or someone else's. A server fault answers "The request failed. Try again." and nothing more. A write that was understood but refused for one item is not an error: it is that item's outcome. Refusing a whole call (a permission, a site that isn't yours, a batch that is too large) is an error.
Prompts
The server also offers three prompts. A client such as Claude Desktop lists them as ready-made requests. Each one is a template that tells the assistant which tools to call, in what order, and how to structure its answer in four parts. It must cite the message id behind each claim. They hold none of your data, only the arguments you type.
| Prompt | Arguments | Does what |
|---|---|---|
analyze_conversation | conversationId | Reads one conversation and its labels, then explains what happened and why. |
compare_conversations | conversationIds (comma-separated, 2 to 20) or filter (a plain description) | Compares the conversations you name, or finds the ones a description matches, then says what they share and where they differ. |
weekly_review | siteId (optional), weekOf (optional date, YYYY-MM-DD) | Reviews one Monday-to-Sunday week (UTC) for a site or the whole organization: volume, problems, what worked and three changes to make. |
compare_conversations needs conversationIds or filter. With neither, or with ids that aren't conversation ids, the client gets an error. weekly_review without weekOf reviews the last complete week before the asOf time the tools return.
A worked example
You ask: "Find unresolved conversations about sizing last week."
The assistant starts with no list of valid label tokens and no clock, so it calls the tools in this order. The arguments below are what a client would plausibly send. The dates assume the server's asOf is 2026-10-01, a Thursday, so last week is Monday 2026-09-21 to Sunday 2026-09-27.
list_label_vocabulary
No arguments. The assistant reads the tokens the search accepts, with an English display name for each label, value and block, the same names the REST vocabulary returns. It uses the names to explain a label to you and filters on the tokens. The taxonomy has no label named "sizing". The size-related tokens it can use are objection_size_fit:true (a purchase objection about size or fit), gap_info_topic:size_fit (the product information the shopper needed about size was missing) and capability_needed:size_recommendation (the shopper needed the assistant to turn measurements into a size). Resolution has the value unresolved.
search_conversations
{
"from": "2026-09-21T00:00:00Z",
"to": "2026-09-28T00:00:00Z",
"labels": {
"all": ["resolution:unresolved"],
"any": [
[
"objection_size_fit:true",
"gap_info_topic:size_fit",
"capability_needed:size_recommendation"
]
]
},
"count": true
}Every site is searched, since no siteId is given. all requires resolution:unresolved. The one group in any needs at least one of the three size tokens. The result is a page of compact items, newest first (id, title, site, agent, channel, language, device, ratings, label summary, dashboard link), a count, and a nextCursor when there are more than the 25 default. The assistant reads the next page by calling again with the same filters and that cursor.
get_conversations
{
"conversationIds": [
"conv_01kvnwmagvf27rc9cze5rm9e1r",
"conv_01kvnwmagwf27rc9d7zef4qksf"
]
}The ids are the first ones from the search (the values here are made up). The assistant gets each transcript in compact form with its label record, and reads where the answer failed. For a single conversation it calls get_conversation instead, to see the full content blocks. To see why the judge labeled one conversation as it did, it calls get_conversation_labels and resolves the message ids it cites with get_conversation.
It then answers from what the tools returned, with the dashboard links of the conversations it cites. Results vary with your data and aren't shown here.
A report and a breakdown with comparison
You ask: "How did last week go on our UK site, and why were conversations handed off to a human?"
The dates assume asOf is 2026-10-01 again, so last week is Monday 2026-09-21 to Sunday 2026-09-27. The assistant calls list_sites first to turn "our UK site" into a site id.
get_report
{
"siteId": "site_01kvnwmagvf27rc9cze5rm9e1r",
"report": "conversations",
"from": "2026-09-21",
"to": "2026-09-27",
"compare": true
}Both days are included, so this reads seven UTC days. compare adds the seven days before, 2026-09-14 to 2026-09-20. The result gives each summary figure as current and previous, with the daily volume of both periods. A figure with nothing to divide is null.
get_label_breakdown
{
"label": "transfer_reason",
"siteId": "site_01kvnwmagvf27rc9cze5rm9e1r",
"from": "2026-09-21T00:00:00Z",
"to": "2026-09-28T00:00:00Z",
"compare": true
}to is excluded, so this covers the same seven days. The result lists every transfer reason with its count for the week, its count the week before and the change, plus how many labeled conversations had no transfer reason (withoutValue) and how many matching conversations have no labels yet (notLabeled). If capped is true, the counts cover only the newest 10,000 labeled conversations and the changes aren't exact. The assistant can then call search_conversations with a token such as transfer_reason:capability_missing to read the conversations behind a count.
The site id here is made up, like the ones above. Results vary with your data and aren't shown here.
Labels and the labeled channels
Labels come from the conversation labeling pipeline, which runs in the background. It labels conversations on the Web, AI Storefront and Playground channels (web, hosted, playground), every channel a conversation can come from.
- Labels usually arrive 30 to 90 minutes after a conversation goes quiet, sometimes later. An hourly pass labels a conversation once it has had no new message for 30 minutes. A recent conversation can read
pending: it has no labels yet, a label filter can miss it, andget_conversation_labelsreturns the status and no answers. - An older conversation isn't labeled. One whose last activity is more than 30 days old isn't picked up.
- A conversation that isn't
labeledhas no labels. Itslabelsfield isnulland itslabelSummaryisnull. The status ispending,failedornot_eligible: see Label status for what each means. Fornot_eligible, the server doesn't say which reason applies. - A missing label means "not labeled", not "no issue". A search on a label token returns only labeled conversations, so a token that is absent says nothing about a conversation that hasn't been labeled.
- Label names are for people. The text a tool returns writes a label as its key with an English name beside it, for example
grounded (Stuck to known facts). The name explains the label. Filters and the structured result use the keys and tokens, never the names. - The assistant is told this at connection. The server sends instructions when a session starts, so your client's model is asked to say that a conversation isn't labeled rather than guess its labels, and to filter on tokens, not on names.
To see which conversations a label filter can't cover yet, search with labelStatus set to pending or failed.
Rate limit
Tool calls are limited per organization: 300 calls per minute, shared by every member and every client connected to your organization, across all forty-one tools. Writes count like reads. The limit is there so that one client stuck in a loop can't take the server away from the others.
Over the limit, a tool answers an error: "Your organization is making too many requests. Wait 60 seconds, then retry." The call reads nothing. Rely on that retry hint rather than on the figure: 300 is a starting value, and iAdvize can change it.
What the server doesn't give you
- Anything outside your organization. Every read is scoped to the organization you authorized.
- Shopper identity. No field of a conversation identifies the shopper. What a shopper typed is still in the transcript. A shopper identifier such as
visitorIdin a tool's input is refused as an unknown field. - Reasoning, cost and token usage. None of it is in a tool's result.
- Tool inputs and outputs of the shopper chat. A transcript shows what the shopper saw (text, product cards, questions, quick replies, hand-off, files), not the assistant's internal tool calls.
- Site traffic. Beyond each page's views over the last 30 days in
list_site_pages, the server has no visits, bounce rate or conversion rate of your site. The engagement report counts the sessions the assistant's widget was shown to, not the visitors of your site. - Revenue and order value per conversation. The commerce outcomes of a conversation are yes, no or unknown, with no amount: see Commerce outcomes. Revenue and order value of a whole site over a period come from the
salesreport only, attributed and not per conversation. - Market and competitor data. The server only knows the conversations your assistant had. It has nothing on your market, your competitors' prices or what shoppers do elsewhere.
- Catalog data beyond what a product card showed the shopper (current prices, stock), what a human agent said after a hand-off, and benchmarks across organizations. This data isn't in the server.
The assistant is told not to estimate any of this. A question that needs it gets an answer that says so, or a figure from another tool that you should not read as a substitute.
This gives your MCP client the same visibility as a dashboard user
A conversation transcript can contain shopper-provided personal information. Connecting an MCP client gives it exactly the same access a person logged into your dashboard already has: nothing more, nothing less. Only connect clients and organizations you trust with that data.
Limitations today
- Writes cover creating a site, its hosted page, pages, starter questions, a site's settings and agent A/B tests. An MCP client can create sites from their address, switch a hosted page on or off, import, add, read and exclude pages, ask for, create, edit, switch and delete starter questions, and change a site's automation, panel, Panel reduced state button and tag monitoring settings. It can start, stop and promote an agent A/B test. It can't edit your agents or their versions (apart from
provision_site_from_url, which creates an assistant and puts it live), your connectors, your site's other settings, the usage mode and quotas of your organization or your members. A starter question you switch on is live to shoppers at once, so the assistant that does it should have your approval first: your client asks, see Write tools. - Reports are per site.
get_reportreads one site at a time. There is no cross-site total, and no filter by agent, language or keyword on a report. Only the starter questions and add-to-cart reports take a device. - Checkout is not measured. No checkout event is recorded yet, so
reachedCheckoutis nevertrue. A purchase is known only for a conversation that carries a join key. See Commerce outcomes. - Labels take time and cover recent conversations. See Labels and the labeled channels.