Skip to content
Web > Charts

Building Charts over MCP

Known issues

Some chart features have known issues in the current release. See Known issues.

This page covers the MCP tools an agent uses to create charts, add layers to them, and check what they drew.

Overview

A chart over MCP is built on a datamodel the agent has already created and run: connecting an agent is covered in the AI section, and building and committing the datamodel in the Datamodels section. The chart tools are:

Tool Does
web_create_chart Creates a bar, horizontal bar, line, scatter, area, pie, or donut chart from a datamodel's table
web_get_chart_templates Lists every chart type and template, with the fields each one maps
web_create_chart_from_template Creates a chart from a template, such as a candlestick or a waterfall
web_add_chart_layer Adds one layer to an existing chart
web_debug op=panelRenderStats Reports what each layer of a chart drew
web_debug op=chartSchemaWarnings Lists a chart's field expressions that name columns its datamodel does not output

Every tool that creates or changes a chart does so in a session, named by __SESSIONID (web_execute op=initDatamodelSchema and op=executeDatamodel call the same parameter __SESSIONID_or_HEADLESSNAME): a user's session ID or a headless session's name. To find it, call web_console with op=sessions: each row is one open session, with its ID in __SESSIONID, its user in __USERNAME, and its layout in Layout; for a headless session, pass the name in its row's __NAME instead. Pass the ID to every call below. A call without it is refused, as in web_debug (op=panelRenderStats): missing required parameter(s): __SESSIONID.

A typical sequence

  1. Create the datamodel and run it so its columns are known: web_execute op=importDatamodel, then op=initDatamodelSchema. The schema it returns lists the output table and its columns.
  2. Create the chart with web_create_chart or web_create_chart_from_template, naming that datamodel and table.
  3. Run the datamodel again with web_execute op=executeDatamodel. A chart created over MCP can stay empty until it does. Render stats do not show this through Rows, which already count the rows; the chart's AXIS rows still read min=0.0 max=100.0.
  4. Check the chart with web_debug op=panelRenderStats: each layer should report the expected Rows and an empty Problem.
  5. Commit the chart and its datamodel with web_execute op=commitSession, then ask the user to save the layout. op=commitPanel commits the chart only.
  6. Confirm that the chart's "Plot" submenu now offers "Edit Layers".

One walkthrough per chart type, each with its MCP call, is in Chart type walkthroughs.

Creating a base chart

web_create_chart creates a one-layer chart in a new window.

Parameter Value
windowName The name of the new window
datamodelId The datamodel to chart
dmTable Its output table
chartType bar, hbar, line, scatter, area, pie, or donut, in any case
xField The category column for a bar or pie chart; the x column for a line, scatter, or area chart
yField The value column
title The chart's title. It also becomes the chart's panel id
logScale x, y, or xy for a logarithmic axis, base 10, on a line, scatter, or area chart; empty for none

chartType also accepts barv, vbar, barh, rapie, and doughnut. A donut or doughnut is drawn as a full pie, without a hole: it sets an inner radius but leaves "Auto Min Value:" on, which hides it. To draw the ring, export the chart with web_console op=exportPanel, set the layer's "autoMinValue" to false, pass the result to web_execute op=updatePanel, and run the datamodel again.

A bar chart is drawn with one color per category, and its hover text is filled in. Its categories are in alphabetical order. To order them as the rows arrive, which the gallery calls "Sub-Title Ordering:" "Original", set the category axis's "isGroupOrdered" to false with op=updatePanel, and sort the rows in the datamodel's query; see Ordering bars by value. A horizontal bar chart draws the first row at the bottom.

The reply names the chart, its type, and its window, followed by its schema warnings:

Chart 'Trades' (2dBarV) created as transient window 'W1' from TradesDm.T. Schema OK (0 warnings). Call web_execute(op=commitSession) then ask the user to Save to persist.

An unknown type is refused with "Unknown chartType 'speedometer'. Use one of: bar, hbar, line, scatter, area, pie, donut.".

The chart's panel id is its title as given, spaces and punctuation included. The gallery allows only a letter or _ followed by letters, digits, and _, and gives a chart a taken id with a number added, such as ChartDemoRisk1. A title already used by a panel in the layout is refused with a message that names web_execute(op=importWindow); give the chart another title.

web_create_chart does not check that the datamodel exists. Given a datamodelId that is not in the session, it creates the chart and reports only "Schema warnings (5)", such as "Syntax error for Options --> Group By: Unknown variable: Symbol", the same warnings as for a datamodel that has not yet run.

Creating a chart from a template

web_get_chart_templates lists the chart types and templates, and web_create_chart_from_template creates a chart from one.

web_get_chart_templates takes an optional family (Cartesian, Radial, or Flow, in any case) and an optional templateKey, and returns one row per type with the columns Key, Label, Family, Kind, Description, Bindings, and DataPrep. Bindings lists each field as label=KEY:KIND, with ? after an optional one, such as Time=T:AXIS for a candlestick. An unknown templateKey is refused with "Unknown chart type key: ...".

web_create_chart_from_template takes:

Parameter Value
windowName The name of the new window
templateKey A Kind Template key from web_get_chart_templates, such as tplCandle
datamodelId, dmTable The datamodel and its output table
bindings Optional. A JSON object mapping each field's key or label to a column, such as {"T":"Day","O":"Open","H":"High","L":"Low","C":"Close"}. Fields left out are filled in from the columns
dmTable2 The second table, for a Sankey's links
title Optional. The chart's title

The reply includes a "ROLE MAP" that shows which column was mapped to each field, marking fields it filled in itself [auto-fitted], and required fields it could not fill "(UNSET - REQUIRED, chart will be incomplete)":

1
2
3
4
5
Tree / Org chart 'Org' (tplTree, 1 layer(s)) created as transient window 'W2' from OrgDm.T.
ROLE MAP (verify these - a wrong auto-fit renders a valid but meaningless chart):
  Row kind (KIND) -> (UNSET - REQUIRED, chart will be incomplete)
  X (left / from) (X1) -> Dy   [auto-fitted]
  ...

Read the role map and pass bindings for any field mapped wrongly. A filled-in mapping can be meaningless, such as a candlestick's "Open" mapped to a day column. A required field left unset does not stop the chart from being created.

For the templates that need data in a particular shape (Waterfall, Boxplot, Stacked Area, Network Graph, Tree / Org, Sankey), the reply adds "DATA SHAPE REQUIRED", with the shape. The template draws the data it is given; see Data each template expects.

The reply includes a "Cosmetic note" about styling, followed by the instruction to commit. To restyle the chart, use web_execute op=setPanelStyle, not the tool the note names.

The template errors include:

  • A Sankey without dmTable2: "... needs TWO output tables ..."
  • A base type's key: refused, naming it a BASE chart type
  • An unknown table: "DataModel '...' has no output table '...'. Known tables: [...]"
  • An unknown field in bindings: refused, listing the valid ones
  • bindings that are not valid JSON: refused

Adding a layer

web_add_chart_layer adds one layer to an existing chart's first plot, from a layer described as JSON.

Parameter Value
panelId The chart
layerJson The layer, with an id and a type: Chart, Radial, Legend, Crosshair, or Annotation

An unknown type is refused with "Unsupported layer 'type' 'Bogus' - must be "Chart", "Radial", "Legend", or "Crosshair"." Annotation is accepted, although the message does not name it. The tool does not refuse a layer with no id, a duplicate id, or an unknown editorType: give every layer a unique id of its own.

A legend or a crosshair added with only an id and a type starts with no layer selected: the legend's "AVAILABLE SERIES" and the crosshair's "SERIES TO SNAP TO" are both cleared. The legend then draws an empty box titled with its id, and the crosshair draws nothing.

Give a legend or a crosshair its layers in zpositions, a list of the layers' zPlotPos values. A chart's first layer has no zPlotPos, and 0 selects it:

{"id": "Legend", "type": "Legend", "zpositions": [0]}
{"id": "Crosshair", "type": "Crosshair", "zpositions": [0]}

The legend then lists that layer's series, and its "AVAILABLE SERIES" shows the layer ticked; the crosshair follows that layer. panelRenderStats reports "NO SERIES" for a legend or crosshair either way. Their layers can also be selected in the chart's editors, as in Adding a legend and Turning on the crosshair.

An annotation is drawn only when it has the chart's datamodel in dm and dmTable; without them it draws nothing, and render stats report "NO DATA: this layer built 0 rows and has no dm binding". Its fields use the keys below, with the label each has in the layer editor. This draws a red line across the plot at 600, labeled "Target 600":

{"id": "Target", "type": "Annotation", "editorType": "2dAnnotationLine", "dm": "Trades", "dmTable": "Trades", "xAxis": "bottom", "yAxis": "left", "xAnchor": "data", "yAnchor": "data", "annY1": "600", "annColor": {"type": "custom", "value": "\"#FF0000\""}, "annLineSize": "3", "annLabel": "\"Target 600\"", "annLabelColor": {"type": "custom", "value": "\"#FFFFFF\""}}
Key Field
annX1, annY1, annX2, annY2 "X:", "Y:", "X2:", "Y2:"
annColor, annBorderColor "Color:", "Border Color:"
annLineSize, annDash "Line/Border Size (px):", "Line Dash:"
annLabel, annLabelColor, annLabelSize "Label:", "Label Color:", "Label Size:"
annImage "Image Source:"

The editorType names the kind: 2dAnnotationLine is "Axis Line". The other kinds' types can be read from an annotation made in the layer editor, with web_console op=exportPanel.

Checking what a chart drew

web_debug op=panelRenderStats returns a chart's render stats: one PANEL row, one AXIS row per axis, and one LAYER row per layer, with the columns Panel, Scope, Id, Type, Binding, Rows, Detail, and Problem. Leave out panelId to get every chart in the session at once.

A chart layer with no Rows or with a Problem drew nothing; legends and crosshairs report "NO SERIES" even when they work. The reverse does not hold: a layer whose shape is left unmapped, such as a bullet chart's "Range 2:" left empty, reports its Rows and an empty Problem while drawing nothing, so check that every layer you expect is mapped. Zero schema warnings and a "Schema OK" reply are not enough on their own: a layer with an unknown editorType passes both, reports its rows with no Problem, and draws as an "Advanced" layer. The Problem texts are listed in Troubleshooting.

web_debug op=chartSchemaWarnings returns {panelId, warnings, warningCount}, with the same warnings as the creating tool's reply.

Letting people edit an agent's chart

A chart, window, or datamodel created over MCP is transient: it exists only in the session until it is committed, and it is not saved with the layout until then. web_execute op=updatePanel makes a chart transient too, including one made in the gallery. Until it is committed:

  • The chart's "Plot" submenu offers only "Remove", so a person cannot open its layer or plot editors.
  • The visualization gallery refuses its datamodel, with "Can not create panels on transient datamodels".

Commit the chart and its datamodel with web_execute op=commitSession, which commits every transient window and datamodel in the session, then ask the user to save the layout. The op=importDatamodel tool description warns that a datamodel imported before op=importWindow can be lost on save; in the sequence on this page, with web_create_chart and op=commitSession, the saved layout keeps the datamodel, and both come back when the layout is reloaded. op=commitPanel, naming the chart, commits the chart only: its datamodel stays transient, although the tool's description says it commits the panel's datamodels.

To set the chart's style, such as showing its title, use web_execute op=setPanelStyle. Its first call for a style namespace in a session, such as the first for any chart, returns that namespace's style keys and changes nothing; later calls in the session apply the change, for every chart. See Showing a chart's title.

Removing an agent's chart

A datamodel that a chart reads cannot be deleted, so delete the chart first:

  1. Delete the chart with web_danger op=deletePanel, with its panelId from web_console op=panels. Its window goes with it.
  2. Delete the datamodel with web_danger op=deleteDatamodel and its dmName.
  3. Confirm that the datamodel is gone: run web_console op=datamodels, which no longer lists it.

Both tools delete transient objects only. After op=commitSession, deleteDatamodel refuses, as in "Cannot delete DataModel 'ChartDemoTotals': it is not transient (only transient DataModels can be deleted; a committed/saved DM must be kept)." Ask the user to close the chart's window and delete the datamodel in the Data Modeler: Dashboard -> Data Modeler..., then right-click the datamodel under "Datamodels" and select "Delete Datamodel".

A datamodel left in the session keeps its id, and op=importDatamodel refuses another with the same id, as in "DataModel 'ChartDemoTotals' already exists - refusing to import."

What this does not support

  • Every base chart type from web_create_chart: it creates bar, horizontal bar, line, scatter, area, pie, and donut charts only. A radial bar or speedometer is refused, as in "Unknown chartType 'speedometer'"; create one in the gallery.

  • A Sankey from one table: web_create_chart_from_template refuses a Sankey without a second table, dmTable2, holding the links.

  • Reshaping data: no tool aggregates or lays out data for a template. The datamodel must produce the shape the reply's "DATA SHAPE REQUIRED" names.