Skip to main content
Glama

Add a widget

add_widget

Add a chart to a dashboard. A widget is a saved insights query (the same event_type, filters, breakdown, group_by, measure and measure_property as run_insights_query: an event count, or the sum or average of a numeric detail, scroll_depth or time_on_page_seconds; or up to 4 series) shown over the dashboard's date range as a chart, a single value (visualization number) or a table, so run the query with run_insights_query first and only add it if it shows what the title says. Uses one of that dashboard's widget slots (get_project slots_left). Placed below the other widgets unless x and y are given (12-column grid). Pass run_id from start_setup_run so this undoes together with the rest of the setup; leave it out (never "") to start a new chat run, whose run_id is returned and should go on every later change.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "dashboard_id": "<dashboard_id>",
      "title": "<title>",
      "query": "<query>"
    },
    "name": "add_widget"
  }
}

Input Schema

NameRequiredDescriptionDefault
hNoHeight in rows. Default 4.
wNoWidth in columns, 1-12. Default 6.
xNoColumn 0-11. With y; omit both to place it below the other widgets.
yNoRow, from 0. With x.
queryYesThe insights query the widget runs; test it with run_insights_query first.
titleYesWhat the chart shows, in the customer's words.
run_idNoThe setup run this change belongs to, from start_setup_run. Omit to start a new chat run (its id is returned).
projectNoProject ID, from list_projects. Required when this connection covers more than one project; may be left out when it covers one (and with an API key, which belongs to one project).
dashboard_idYesDashboard ID, from list_dashboards or create_dashboard.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed9 schema fields changed
    • changedInput schema / properties / query / properties / filters / items / properties / operator / description
      Previous value: -"A plain filter's operator: equals, contains, starts_with, matches (a whole-value pattern where * stands for any text, e.g. *://t.co/* on referrer; a pattern of only * is refused, use exists) or exists (trait and automated: equals only), case-sensitive except on query.utm_source, query.utm_medium and query.ref."New value: +"A plain filter's operator: equals, contains, starts_with, matches (a whole-value pattern where * stands for any text, e.g. *://t.co/* on referrer; a pattern of only * is refused, use exists) or exists (trait and automated: equals only), case-sensitive except on query.utm_source, query.utm_medium and query.ref. scroll_depth and time_on_page_seconds take equals, greater_than, less_than (both strict, > and <: scroll_depth greater_than 74 is 75 or more) or exists (has a value), with a whole number in range as the value, digits only. attrs.KEY also takes greater_than and less_than (strict), comparing the detail as a number: attrs.order_value greater_than 100, with a plain decimal number as the value (100, 34.5, -3; no exponent or separators); an event without the detail or whose detail is not a number matches neither. greater_than and less_than work on nothing else."
    • changedInput schema / properties / query / properties / filters / items / properties / property / description
      Previous value: -"A plain filter's property: a standard property (page_origin, page_path, page_fragment, referrer, data_track, element_tag, element_selector, element_selector_generalized, element_text), attrs.KEY, query.PARAM, trait, or automated (true for automated visits: headless or program-driven browsers and AI agents browsing for a person; equals 'true' or 'false' only, e.g. automated equals false to count people only). Leave out in an any group."New value: +"A plain filter's property: a standard property (page_origin, page_path, page_fragment, referrer, data_track, element_tag, element_selector, element_selector_generalized, element_text), attrs.KEY, query.PARAM, trait, automated (true for automated visits: headless or program-driven browsers and AI agents browsing for a person; equals 'true' or 'false' only, e.g. automated equals false to count people only), or a page view's numbers: scroll_depth (how far down the page the visitor got, whole percent 0-100: 0 never scrolled, 100 the bottom) and time_on_page_seconds (active seconds on the page, 0-1800), null where no value arrived (an older tracker, a lost send), which no comparison matches. Leave out in an any group."
    • changedInput schema / properties / query / properties / filters / items / properties / value / description
      Previous value: -"A plain filter's value (for matches, the pattern); required except for exists."New value: +"A plain filter's value (for matches, the pattern; for scroll_depth and time_on_page_seconds a whole number such as 75; for greater_than or less_than on attrs.KEY a plain decimal number such as 100 or 34.5); required except for exists."
    • changedInput schema / properties / query / properties / measure / description
      Previous value: -"events (default), sum or average, as for run_insights_query: sum and average read the numeric event detail measure_property, per event, leave out values that are not numbers, and an average bucket with no numbers is empty, not 0."New value: +"events (default), sum or average, as for run_insights_query: sum and average read measure_property (a numeric event detail, or scroll_depth or time_on_page_seconds), per event, leave out values that are not numbers, and an average bucket with no numbers is empty, not 0."
    • changedInput schema / properties / query / properties / measure_property / description
      Previous value: -"For sum and average only, and then required: the event detail, attrs.KEY, as for run_insights_query."New value: +"For sum and average only, and then required: the event detail, attrs.KEY, or scroll_depth (average only) or time_on_page_seconds, as for run_insights_query."
    • changedInput schema / properties / query / properties / series / items / properties / filters / items / properties / operator / description
      Previous value: -"A plain filter's operator: equals, contains, starts_with, matches (a whole-value pattern where * stands for any text, e.g. *://t.co/* on referrer; a pattern of only * is refused, use exists) or exists (trait and automated: equals only), case-sensitive except on query.utm_source, query.utm_medium and query.ref."New value: +"A plain filter's operator: equals, contains, starts_with, matches (a whole-value pattern where * stands for any text, e.g. *://t.co/* on referrer; a pattern of only * is refused, use exists) or exists (trait and automated: equals only), case-sensitive except on query.utm_source, query.utm_medium and query.ref. scroll_depth and time_on_page_seconds take equals, greater_than, less_than (both strict, > and <: scroll_depth greater_than 74 is 75 or more) or exists (has a value), with a whole number in range as the value, digits only. attrs.KEY also takes greater_than and less_than (strict), comparing the detail as a number: attrs.order_value greater_than 100, with a plain decimal number as the value (100, 34.5, -3; no exponent or separators); an event without the detail or whose detail is not a number matches neither. greater_than and less_than work on nothing else."
    • changedInput schema / properties / query / properties / series / items / properties / filters / items / properties / property / description
      Previous value: -"A plain filter's property: a standard property (page_origin, page_path, page_fragment, referrer, data_track, element_tag, element_selector, element_selector_generalized, element_text), attrs.KEY, query.PARAM, trait, or automated (true for automated visits: headless or program-driven browsers and AI agents browsing for a person; equals 'true' or 'false' only, e.g. automated equals false to count people only). Leave out in an any group."New value: +"A plain filter's property: a standard property (page_origin, page_path, page_fragment, referrer, data_track, element_tag, element_selector, element_selector_generalized, element_text), attrs.KEY, query.PARAM, trait, automated (true for automated visits: headless or program-driven browsers and AI agents browsing for a person; equals 'true' or 'false' only, e.g. automated equals false to count people only), or a page view's numbers: scroll_depth (how far down the page the visitor got, whole percent 0-100: 0 never scrolled, 100 the bottom) and time_on_page_seconds (active seconds on the page, 0-1800), null where no value arrived (an older tracker, a lost send), which no comparison matches. Leave out in an any group."
    • changedInput schema / properties / query / properties / series / items / properties / filters / items / properties / value / description
      Previous value: -"A plain filter's value (for matches, the pattern); required except for exists."New value: +"A plain filter's value (for matches, the pattern; for scroll_depth and time_on_page_seconds a whole number such as 75; for greater_than or less_than on attrs.KEY a plain decimal number such as 100 or 34.5); required except for exists."
    • changedInput schema / properties / query / properties / series / items / properties / measure_property / description
      Previous value: -"For sum and average only, and then required: the event detail, attrs.KEY."New value: +"For sum and average only, and then required: the event detail, attrs.KEY, or scroll_depth (average only) or time_on_page_seconds, as the query's measure_property."
  2. First observed

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag this as a non-readonly, non-idempotent write, so the description's job is to add context — and it does: adding a widget consumes one of the dashboard's finite widget slots (checkable via get_project slots_left), changes land below existing widgets unless x/y are given, and run_id determines whether the change is grouped for undo. What it omits is the consequence of exhausting slots and what identifier comes back for the new widget.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and essentially every clause carries operational information (slot consumption, placement, run_id semantics). It is one dense paragraph with stacked parentheticals, though, so a reader has to work harder than necessary to extract the placement and run_id rules.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a write tool with a deeply nested query object and no output schema, the definition covers purpose, prerequisite testing, quota effect, placement, and undo grouping — nearly everything needed to call it correctly. The notable gap is the return value: it says a new run_id is returned but never mentions the created widget's id, which the agent needs for later update_widget or remove_widget calls.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the nested query, x/y/w/h and project fields are already fully documented and the baseline is 3. The description adds a little beyond the schema — the 12-column grid, default placement below other widgets, and the warning never to send an empty-string run_id — but does not enrich the query sub-object further than the schema already does.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource ("Add a chart to a dashboard"), then defines what a widget actually is (a saved insights query rendered as line/bar/number/table over the dashboard range). This is enough to separate it from update_widget and remove_widget without opening their schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit prerequisite ("run the query with run_insights_query first and only add it if it shows what the title says") and a branching rule for run_id: pass one from start_setup_run to make the change undoable, omit it ("never """) to start a new chat run. That is real when-to-use/when-not guidance rather than restated mechanics.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources