mcpField
C
cube-run-query

cube-run-query

github.com/cube-jsData & databases440 installsUpdated 5w ago
Repository

About cube-run-query

cube-run-query is a skill for querying Cube data through available MCP tools or the Cube CLI. It guides users to discover model members, run queries, and interpret results with security context and query details.

Key features

  1. 01Query through Cube MCP tools or CLI
  2. 02Discover queryable model members
  3. 03Run filtered and time-based queries
  4. 04Page through results over 100 rows
  5. 05Verify changes on development branches

Use cases

  1. 01Answering metric questions from Cube data
  2. 02Checking results after a model change
  3. 03Running Cube queries in scripts or CI jobs

MCP support

When Cube MCP tools are available, the skill uses `cube:searchDataModel`, `cube:runQuery`, and `cube:chat`. It also describes the CLI path when MCP tools are unavailable.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/cube-js/cube-agent-skills --skill cube-run-query

After installing, type/cube-run-queryin Claude Code to confirm it loaded.

Details

From the project README

Run a query against Cube

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, use them. They come from this plugin's cube server or the Cube connector — look for cube:searchDataModel, cube:runQuery and cube:chat. They need no install or login step, and every call runs as the signed-in user, so row-level security applies exactly as in the UI.

  • A specific number: cube:searchDataModel to find the view and the exact member names, then cube:runQuery with Cube SQL — SELECT status, MEASURE(count) FROM orders_view GROUP BY 1. Never guess a member name.
  • An open-ended question ("why did signups drop in March"): cube:chat, which runs Cube's own agent over the governed model and existing reports. Give the user the cubeChatUrl it returns so they can continue in Cube.
  • Another deployment: cube:listDeployments, then pass its deploymentId.
  • A dev branch: pass the same branchName to cube:searchDataModel and cube:runQuery, so the members you find are the ones the query sees.
  • More than 100 rows: page cube:runQuery with offset until hasMore is false.

Use the CLI path below when the MCP tools are not connected, or in a script or CI job. Interpreting results applies to both paths.

CLI path

Querying steps outside the CLI. cube api is bound to Cube's console API and cannot reach a deployment's query endpoint, so querying is two CLI calls to get a URL and a token, then a direct request to the deployment.

Preflight
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

jq and curl are also required here, unlike every other skill in this plugin. Check for them and say so if they are missing.

Get the endpoint and a token
DEPLOYMENT=<id>
URL=$(cube deployments get "$DEPLOYMENT" --json | jq -r .deploymentUrl)
TOKEN=$(cube deployments token "$DEPLOYMENT")

cube deployments token prints the Cube API token on its own; add --json if you want the wrapping object. The token carries the calling user's security context, so row-level security applies exactly as it would in the UI — a query here returns what that user is allowed to see, not everything.

Know what you can query first

Do not guess member names. Ask the compiled model:

cube meta --selectors '[{"type":"cube","deploymentId":'"$DEPLOYMENT"',"environment":"production"}]'

Members are Cube.member or View.member. A dimension that exists on a cube but is not exposed in a view is not queryable through that view — cube meta is what tells you which is which.

Run it
curl -s "$URL/cubejs-api/v1/load" \
  -H "Authorization: $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"query":{
        "measures":["Orders.count","Orders.totalRevenue"],
        "dimensions":["Orders.status"],
        "timeDimensions":[{"dimension":"Orders.createdAt","granularity":"month","dateRange":"Last 6 months"}],
        "limit":100
      }}' | jq

Query shape, in the order you usually need it:

  • measures — the numbers. Always fully qualified.
  • dimensions — what to break down by.
  • timeDimensions — dimension plus granularity (day/week/month/…) and dateRange, which accepts natural ranges like "Last 30 days" or an explicit ["2026-01-01","2026-06-30"].
  • filters — [{"member":"Orders.status","operator":"equals","values":["paid"]}].
  • order, limit.

The response carries data plus annotation, which holds the human titles and formats for each member. Use annotation when presenting results — it is where a measure's display name and unit live.

Interpreting results

  • Report the number, then how it was derived. Which measure, which range, which filters. A number without its query is not checkable.
  • An empty data array is a result, not an error. Say the query succeeded and returned no rows; do not retry with a different query and present that instead without saying you changed it.
  • Never fill in a value you did not receive. If the query failed, report the error.

Verifying a model change

The common case after cube-build-model: query the new measure on the dev branch before merging. Over MCP, pass the dev branchName to cube:searchDataModel and cube:runQuery. With the CLI, $URL/cubejs-api/v1/load always answers from production; a dev branch has its own endpoint under the same deployment URL, used with the same token:

cube deployments build-status "$DEPLOYMENT" --branch <dev-branch> --wait
curl -s "$URL/dev-mode/<dev-branch>/cubejs-api/v1/load" -H "Authorization: $TOKEN" ...

Point cube meta at the branch the same way, with "environment":"<dev-branch>".

When something fails

SymptomCause
deploymentUrl is nullThe deployment has never finished a build; check cube deployments build-status
401 from the load endpointToken expired — they are short-lived, just mint another
Member not foundWrong name or not exposed in that view — re-check cube meta, do not guess a variant
{"error":"Continue wait"}The query is still running — send the same request again until data comes back. Tell the user if it keeps going past a minute or two

Comments

Markdown supported