Writes state. Reports and dashboards are what people see, so a mistake here is visible to more than the person who made it.
Choose the path
Cube MCP tools are written cube:<tool> below: the cube server this plugin
bundles. Through the Cube connector, the same tools carry the connector's name.
If the Cube MCP tools are available (this plugin's
cube server or the Cube connector), use them for workbooks, reports, dashboards and folders:
- Verify the query with
cube:runQueryfirst — seecube-run-query. cube:createWorkbook— returnsworkbookIdand aurl. Skip it when the user named a workbook to build into.cube:createReportwith thatworkbookId, one per chart. Reports take Cube SQL (sqlQuery) and achartCategory. OmitworkbookIdonly for a standalone exploration, which is what the Sheets and Excel add-ons list.cube:readWorkbook, thencube:updateDashboardto lay the reports out.cube:publishDashboard— returns the liveurl. Give it to the user.
Change an existing report in place with cube:readReport and cube:updateReport
rather than recreating it. cube:manageFolders lists and creates folders.
Scheduled notifications, duplicating a workbook, and connecting a report to an external spreadsheet are CLI-only. Use the CLI path below for those, and for everything when the MCP tools are not connected. The order of operations and conventions apply to both paths.
Preflight (CLI)
command -v cube >/dev/null || echo "Cube CLI not installed: curl -fsSL https://raw.githubusercontent.com/cube-js/cube/master/install-cli.sh | sh"
cube whoami || echo "Not authenticated. Interactive: cube login. Headless: set CUBE_API_URL + CUBE_API_KEY."
cube context list
Order of operations
Content hangs off a workbook, so build outward from one:
- Verify the query first. Run it with
cube-run-queryand confirm the numbers are right. Saving a wrong query is how a bad number gets an audience. - Create or pick a workbook.
- Add reports to it.
- Publish it as a dashboard if people need to consume it.
- Schedule it if it should arrive on a cadence.
Workbooks
cube workbooks create <deployment> --name "Revenue review"
cube workbooks update <deployment> <workbook> --name "Revenue review Q3"
cube workbooks duplicate <deployment> <workbook>
cube workbooks dashboard <deployment> <workbook> --data '<dashboard-input>'
cube workbooks publish <deployment> <workbook> # makes the dashboard
cube workbooks delete <deployment> <workbook>
Duplicating an existing workbook is usually a better starting point than creating an empty one — it inherits layout and conventions the team already uses.
Reports
cube reports create <deployment> --workbook <workbook> --name "Revenue by month" --json-query '<query>'
cube reports update <deployment> <report> --json-query '<query>'
cube reports refresh <deployment> <report>
cube reports delete <deployment> <report>
--json-query takes the same query shape cube-run-query sends to the load
endpoint — measures, dimensions, timeDimensions, filters. Take the query you
already verified rather than retyping it; retyping is where a filter goes
missing.
Complex bodies go through -d/--data, which accepts inline JSON, @file.json
or - for stdin. Dedicated flags override values in --data.
cube reports connect-workbook is for placing a report in an external
spreadsheet, not attaching it to a Cube workbook. For that workflow use:
cube reports connect-workbook <deployment> <report> --external-workbook-id <id> --result-location <range>
Folders
cube folders create <deployment> --name "Finance"
cube folders update <deployment> <folder> --name "Finance & RevOps"
cube workspace move <deployment> --type WORKBOOK|REPORT|FOLDER --id <id> --folder <folder> # omit --folder for the root
cube folders delete <deployment> <folder>
Scheduled notifications
cube notifications create <deployment> --data '{"scheduleType":"WEEKLY","dashboardPublicId":"<id>","dayOfWeek":1,"hour":9,"timezone":"Europe/London"}'
cube notifications recipients add <deployment> <notification> --data '{"recipients":[{"type":"USER","userId":<id>}]}'
cube notifications recipients list <deployment> <notification>
cube notifications update <deployment> <notification> --data '<UpdateNotificationInput JSON>'
scheduleType is HOURLY, DAILY, WEEKLY, MONTHLY or CUSTOM (with
customCron), dayOfWeek runs 0–6 from Sunday, and hour is 0–23 in
timezone. A recipient's type is USER, EMBED_USER or SLACK. For
the full body, cube spec notification --json prints the schemas.
Before changing or deleting a schedule, list its recipients and say who is currently receiving it. People notice when a report stops arriving, and they rarely connect it to a change someone made.
Conventions
- Name things the way the user said them. Do not tidy "MRR" into "Monthly Recurring Revenue" unless asked.
- Report the id of everything you create, and the URL if the output carries one. The user's next step is opening it.
- Creating is cheap and deleting is not. When a request is ambiguous between "change the existing one" and "make a new one", make a new one and say so.
When something fails
| Symptom | Cause |
|---|---|
| Report saves but shows no data | The query is wrong, not the report — verify with cube-run-query |
Member not found |
Stale member name; the model changed. Re-check with cube-explore-model |
| Publish does nothing visible | The workbook had no reports yet — add them first |
| 403 | The account can read the workspace but not write to it |