Skip to main content
Glama

Publish a dashboard

dashboard_publish

Publish 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

NameRequiredDescriptionDefault
nameYesName 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.
specYesThe dashboard spec document. See this tool's description.
draftNoWrite 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.
handoffNoThe handoff id from dashboard_handoff, when this call finishes one; the page the reader is watching opens what you made
messageNoWhat changed in this version, for the version list

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnly=false, destructive=false, idempotent=false and openWorld=true; the description adds the consequential behavior behind those flags: republishing the same name adds a version rather than overwriting, a new dashboard is PRIVATE and republishing preserves the existing audience, drafts are checked and run but only the owner sees them at the reply's previewPath, and string filters without a list publish with a warning. That is exactly the mutation-side context annotations cannot convey.

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?

The critical facts are front-loaded and sectioned with capitals (SHAPE, PANEL KINDS, SOURCES, FILTERS, AUDIENCE, DRAFTS), which makes a long description scannable. The length is largely justified because the spec parameter is an untyped object (additionalProperties: {}) and the embedded example is the only place its structure is documented, though there is mild redundancy between the prose and the example.

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

Completeness5/5

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

For a tool whose main argument is a free-form JSON document, the description supplies the document shape, the closed list of panel kinds, the canvas-vs-panel distinction, source naming rules, filter dropdown semantics, and pointers to dashboard_reference keys and the orionbi://dashboards/spec.json schema. With no output schema present, it also covers the relevant reply detail (previewPath) so nothing an agent needs to call this correctly is missing.

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

Parameters4/5

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

Schema coverage is 100% and the parameter descriptions are already detailed (name slug/versioning, draft, handoff, message), so the baseline is 3. The description still adds decision-level meaning the schema does not: when to prefer draft=true, and that same-name republishing applies only to the caller's own dashboard. It adds less than the schema already carries, so it stops short of 5.

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 — "Publish a BI dashboard, or add a new version to an existing one" — and immediately scopes what is and isn't accepted ("you do not write HTML, CSS or JavaScript, and none would be accepted"). It explicitly distinguishes itself from siblings by naming dashboard_patch for partial edits and dashboard_get for retrieving an existing spec, so an agent can route correctly without opening another schema.

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 explicit decision rules: "Run dashboard_check first if unsure", "PREFER A DRAFT when the dashboard is shared and its owner asked for a change", and "dashboard_patch changes part of a dashboard without resending the spec". It also states a hard exclusion — widening the audience "cannot be done from a tool call, by design" — which prevents a futile call to dashboard_share for group access.

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