How Cards Read and Show
Change a card's column headers, number and date formats, hidden columns, widths, total row, data labels, legend, axes, chart variant and highlights, and a dashboard's title, through Semaphor MCP.
An agent can finish a card the way a person does in the editor: name its columns, format its numbers and dates, hide a column, add a total row, put the values on the bars, move the legend, title an axis, stack the bars, or highlight the rows that need attention. It reads each setting in the outline and changes it with the same words, through semaphor_propose_change and semaphor_apply_change like every other change (see Making Changes).
{
"dashboardId": "d_8f2k",
"changes": [
{
"op": "card.update",
"cardId": "c_suppliers",
"columns": {
"Net Purchase Value": { "label": "Purchase value", "format": { "type": "currency", "currency": "USD", "maximumFractionDigits": 0 } },
"Net Tons": { "hidden": true }
}
}
]
}The proposal reads it back in plain words, with a value in the new format:
Renames the column "Net Purchase Value" to "Purchase value" in "Purchases by supplier", shows Purchase value as $12,480, and hides Net Tons for everyone (it still sorts and filters).
Read the Settings
semaphor_get_dashboard_details with fields: ["outline"] gives each editable card its settings, in the shape a change takes:
{
"cardId": "c_suppliers",
"title": "Purchases by supplier",
"type": "table",
"editable": true,
"columns": {
"Supplier": { "field": "supplier_id", "role": "dimension", "label": "Supplier", "inherits": ["label", "format"] },
"Net Purchase Value": { "field": "net_purchase_value", "role": "measure", "label": "Net Purchase Value", "width": 180,
"format": { "type": "currency", "currency": "USD" }, "inherits": ["label"] }
},
"totals": { "row": true },
"highlights": [
{ "ruleId": "h_1", "column": "Net Purchase Value", "apply": "row", "enabled": true,
"when": { "operator": "<", "value": 1000 }, "color": "red" }
],
"editorOnly": ["Column display (Supplier)"]
}| Field | What it holds |
|---|---|
columns | Each column by the name its header shows: label, format (the card's own), hidden, width, and inherits, what it takes from the model. A column that inherits its format shows the model's format, which comes with the query's results. field and role say which column it is. |
orientation, stack, donut | A chart's variant (see Chart Variants) |
totals, dataLabels, legend, axes | The card's own settings, when it has them |
highlights | Each highlight rule, with the ruleId that removes it |
editorOnly | Settings the card has that a change doesn't state, in the editor's words. A change keeps them exactly as they are. |
Send a card's settings back as you read them and nothing changes, so an agent can copy them, change only what the user asked, and send them back.
Columns
columns on card.add or card.update names each column by its name in the outline. Send only the settings that change.
| Setting | Values |
|---|---|
label | The header. null returns it to the model's label. |
format | A number, currency, percent, duration or date format, in the shape the outline shows. Send a whole format with its type, or only the fields to change, which are merged onto the format the column shows. null returns the column to the model's format. |
hidden | true hides the column for everyone who views the card; it still sorts and filters. false shows it again. Tables and detail tables. |
width | Pixels, as the table draws it, from 50 to 500. null returns it to automatic. Tables and detail tables. |
{ "Revenue": { "format": { "type": "number", "compact": true } } }
{ "Margin": { "format": { "type": "percent", "percentValueMode": "fraction", "maximumFractionDigits": 1 } } }
{ "Order month": { "format": { "type": "temporal_bucket", "presentation": { "mode": "preset", "preset": "long" } } } }
{ "Ordered at": { "format": { "type": "date", "preset": "short" } } }
{ "Revenue": { "format": { "maximumFractionDigits": 0 } } }- A date grouped by month, quarter or year takes a
temporal_bucketformat: a preset (short,long,numeric,iso, and the week, quarter and fiscal presets at their grains) or apatternno finer than the grain. - A date shown as it is, in a detail table, a SQL table or a Matrix level, takes a
dateformat with apresetor apattern. - Each format is checked against the card that draws it, so the sentence's sample is what the viewer sees. A column whose card shows its values as they come (a chart's categories, text on a table) takes no format, and the refusal says where one applies.
- A SQL table's columns are named by the query's result columns. The proposal runs the card once to read them.
Card Settings
| Setting | Values | Cards |
|---|---|---|
totals | { "row": true } adds a total row; false removes it | Tables |
dataLabels | { "show": true } shows the values on the chart; add format for a number format of their own, or null to follow the measure | Bar, line, area and pie charts |
legend | { "show": true, "position": "bottom" }; position is top, bottom, left or right | Bar, line, area and pie charts |
axes | { "x": {...}, "y": {...} }, each { "title", "min", "max" }; null removes a title or returns a bound to automatic | Bar, line and area charts |
{
"op": "card.update",
"cardId": "c_rev_region",
"dataLabels": { "show": true },
"legend": { "show": true, "position": "bottom" },
"axes": { "y": { "title": "Revenue", "min": 0 } }
}x and y are the axes as they appear on screen: on a horizontal bar chart, y lists the categories and x shows the values. A range goes on the axis that shows values.
Chart Variants
A card's type is one of the eight card types, and its variant is a property of it:
| Variant | type and properties |
|---|---|
| Horizontal bar | bar with "orientation": "horizontal" |
| Stacked bar | bar with "stack": "stacked" (horizontal too, with both) |
| Stacked line, stacked area | line or area with "stack": "stacked" |
| Doughnut | pie with "donut": true |
{
"op": "card.update",
"cardId": "c_rev_region",
"stack": "stacked",
"query": { "dimensions": ["region", "category"] }
}A variant change keeps the card's legend, data labels, axes and colors. A bar chart turned horizontal keeps each axis's title and range with its role, so the value axis keeps "Revenue" and its range. Changing to another chart family, such as a bar chart to a table, works like the editor's type picker.
Highlights
highlight.add colors the cells or rows of a table, detail table or KPI where a condition holds, shades a column on a color scale, or adds data bars:
{ "op": "highlight.add", "cardId": "c_orders", "column": "Margin", "when": { "operator": "<", "value": 0.1 }, "color": "red", "apply": "row" }{ "op": "highlight.add", "cardId": "c_orders", "column": "Margin", "scale": { "low": "red", "high": "green" } }
{ "op": "highlight.add", "cardId": "c_orders", "column": "Revenue", "bars": { "color": "blue" } }| Field | Values |
|---|---|
column | A column's name in the outline |
when and color | { "operator": "=", "!=", ">", ">=", "<" or "<=", "value" }, { "operator": "between", "values": [low, high] }, { "operator": "contains", "value" }, { "operator": "is_null" }, { "top": n } or { "bottom": n }, with the color for the cell or row where it holds |
scale | { "low", "high", "mid" }: colors from the column's lowest value to its highest |
bars | { "color" }: a bar in each cell, in proportion to its value |
apply | cell (the default) or row, for a condition |
Colors are red, amber, green, blue and gray, the editor's own, or a hex color such as #1d4ed8. A KPI's highlight colors its value when a condition holds.
The proposal's change entry gives the new rule's ruleId, and so does the outline afterwards. highlight.remove takes it and keeps the card's other rules:
{ "op": "highlight.remove", "cardId": "c_orders", "ruleId": "h_1" }The Dashboard's Title and Description
{ "op": "dashboard.update", "title": "Weekly sales review" }description sets the dashboard's description; null removes it. The outline shows both.
Confirm
A proposal's confirm says whether the user needs to see it before it's applied:
not_needed: the proposal only changes how cards read and show (labels, formats, hidden columns, widths, data labels, legend, axes, variants and highlights) or the dashboard's title and description. An agent can apply it as soon as it's proposed.needed: anything else, such as a query, a type, a card added or removed, a filter, or a total row (which runs its own query). It's alsoneededwhen a change would remove something viewers saved, such as a column their bookmarks use; theviewer_settings_affectedwarning says what. Show the summary to the user first.
The apply checks again, and refuses with confirm_changed if the proposal now needs the user's confirmation.
When a Setting Is Refused
A refused setting changes nothing in the proposal and says what to do. Each refusal names the card and column as the user sees them, lists what the card or setting takes in allowed, and often carries a suggestedChange you can send as written.
| Code | When |
|---|---|
setting_not_for_card | The card doesn't take that setting, such as axes on a pie chart |
column_not_found, column_ambiguous | No column, or two, have that name; allowed lists the card's column names |
columns_unavailable | A SQL table's query couldn't be run to read its columns |
format_invalid | A format that isn't valid, or that the column's card doesn't draw |
date_finer_than_grain | A date format finer than the column's grouping; allowed lists that grain's presets |
color_unknown | A color that isn't one of the five names or a hex color |
highlight_not_found | No highlight on the card has that ruleId |
value_invalid | A width outside the column's range, an axis that ends before it starts, an empty title, or two labels for one column |