Publish a dashboard
dashboard_publishPublish a BI dashboard, or add a new version to an existing one. Dashboards are hosted on OrionBI and rendered from the spec you supply — you do not write HTML, CSS or JavaScript, and none would be accepted.
You send a SPEC: a JSON document of queries, filters and canvases. Every number is bound to a query run server-side against a Data Source or Data Set the account can already use, so the dashboard is live and never needs republishing for new data.
CANVASES ARE THE TOP-LEVEL STRUCTURE, and there is no other: a canvas is a full page of panels, the tab bar switches between them, the first opens. An undivided dashboard is ONE canvas holding everything — there is no panels key at the document level.
READ THE REFERENCE BEFORE WRITING ONE: dashboard_reference "kinds" has every panel kind's fields; "formats", "filters", "layout", "theme", "guidance" and "examples" cover widths, heights, phones, number formats, tones, the theme and what makes a dashboard good; "all" is everything. The JSON Schema is the resource orionbi://dashboards/spec.json. dashboard_get returns an existing spec ready to edit; republishing under the same name adds a version and keeps its audience.
SHAPE (schemaVersion 2): { "schemaVersion": 2, "title": "Q3 revenue", "notes": "optional — definitions and caveats, plain text", "queries": { "revenue_by_month": { "source": { "kind": "dataset", "name": "<name, from dataset_list>" }, "sql": "SELECT month, segment, revenue FROM ds_… WHERE month >= $1 AND ($2::text IS NULL OR segment = $2)", "params": [{ "name": "from", "type": "date" }, { "name": "segment", "type": "string" }], "maxRows": 5000 }, "segments": { "source": { "kind": "dataset", "name": "<name, from dataset_list>" }, "sql": "SELECT DISTINCT segment FROM ds_… ORDER BY 1", "params": [], "maxRows": 200 } }, "filters": [ { "id": "from", "type": "date", "label": "Period", "default": "-90d", "options": [{ "value": "-30d", "label": "Last 30 days" }, { "value": "-90d", "label": "Last 90 days" }] }, { "id": "segment", "type": "string", "label": "Segment", "optionsFrom": { "query": "segments", "value": "segment" }, "allLabel": "All segments" } ], "canvases": [ { "id": "overview", "title": "Overview", "panels": [ { "kind": "stat", "id": "p1", "title": "MRR", "query": "revenue_by_month", "value": { "column": "revenue", "agg": "sum" }, "format": "currency", "width": 3 }, { "kind": "line", "id": "p2", "title": "Revenue by month", "query": "revenue_by_month", "x": "month", "y": ["revenue"], "seriesBy": "segment", "width": 9 } ] } ] }
PANEL KINDS: stat, gauge, line, bar, area, table, pivot, scatter, combo, pie, treemap, funnel, waterfall, histogram, heatmap, boxplot, sankey, note, bullet, choropleth, section, group. That list is closed; the fields are in dashboard_reference "kinds". A canvas is NOT a panel kind — it is the container above them.
SOURCES: name the Data Set or Data Source exactly as dataset_list or postgres_list_connections reports it.
FILTERS ARE DROPDOWNS: give every one a list, through "options" or "optionsFrom". A string filter with no list is a free-text box and publishes with a warning unless you say "freeText": true. The "All" entry binds NULL, so write the SQL to read NULL as everything. Details: dashboard_reference "filters".
AUDIENCE: a new dashboard is PRIVATE, and republishing keeps its audience. dashboard_share invites ONE person by email; anything wider is the owner's click in OrionBI and cannot be done from a tool call, by design.
DRAFTS: "draft": true writes the version without making it live — checked and run like a live one, but readers keep the current version and only the owner opens it, at the reply's previewPath. PREFER A DRAFT when the dashboard is shared and its owner asked for a change: they look, then promote it. dashboard_patch changes part of a dashboard without resending the spec.
Run dashboard_check first if unsure: it validates and runs the queries.
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": {
"name": "<name>",
"spec": "<spec>"
},
"name": "dashboard_publish"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name of the dashboard, e.g. 'Q3 revenue'. Publishing again with the same name adds a version — to the user's OWN dashboard of that name, never one shared with them (change one shared with them to edit with dashboard_patch). The spec's own `title` is what the page shows; the name is how the dashboard is addressed and is the source of its URL slug. | |
| spec | Yes | The dashboard spec document. See this tool's description. | |
| draft | No | Write the version without making it live. Readers keep the current version; the owner previews this one at the previewPath in the reply and makes it live from OrionBI or with dashboard_promote_version. Needs a live version to be a draft of. | |
| handoff | No | The handoff id from dashboard_handoff, when this call finishes one; the page the reader is watching opens what you made | |
| message | No | What changed in this version, for the version list |