mcpField
C
cubes

cubes

github.com/revosaiData & databases0118 installsUpdated 5d ago
Repository

About cubes

cubes is a skill for managing semantic-model cube definitions through RevOS, for people maintaining analytical data models. It covers reading and writing definitions, checking compilation and queries, and restoring prior state when a change breaks the model.

Key features

  1. 01Read and maintain cube definitions
  2. 02Inspect compiled model metadata
  3. 03Verify compilation and SQL queries
  4. 04Check dependencies before renaming or deleting
  5. 05Restore definitions after failed writes

Use cases

  1. 01Review a cube's tables, dimensions, and measures
  2. 02Add or change model relationships
  3. 03Check that cube changes are queryable
  4. 04Find references before deleting a cube

MCP support

It accesses the `cubes` resource through RevOS MCP server generic tools to read, create, update, and delete definitions, and query the compiled model.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/revosai/skills --skill cubes

After installing, type/cubesin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
evals.json
references/
create.md
definition.md
delete.md
edit.md

Details

From the project README

Cubes

A cube is one stored definition in the org's semantic model: which warehouse table it reads (sql_table), the dimensions you group and filter by, the measures you aggregate, and the joins to other cubes. Tables, segments, and every semantic-model query are built on top of these.

You reach them through the RevOS MCP server's generic tools on the cubes resource:

CallWhat it does
api_read { "resource": "cubes", "params": { "fields": "id,name,updatedAt" } }list the stored definitions
api_read { "resource": "cubes", "id": "<cube id>" }one stored definition, under definition
api_read { "resource": "cubes", "method": "meta", "params": { "filter": "name == \"crm_deals\"" } }the compiled cube as the org can query it
api_write { "resource": "cubes", "data": { "name", "definition" } }create
api_write { "resource": "cubes", "id": "<cube id>", "data": { "definition" } }update
api_delete { "resource": "cubes", "id": "<cube id>" }delete

The record always goes under data. A body under any other key may be ignored without an error. api_details({ resource: "cubes", operation: "create" }) is the authority on the definition's JSON schema.

The one thing to keep in mind

The server checks a definition's shape, not whether it compiles, and Cube compiles all of the org's cubes together. Unknown dimension, measure and join keys are rejected with a named error, but unknown keys at the top of the definition (sqlTable for sql_table) are silently dropped — which can leave a cube with no source. Always send definition.name too: it's optional on create, but Cube compiles by it. A definition that doesn't compile doesn't fail on save. It fails the whole org's semantic model: every table, segment, and query errors until someone fixes it. Common causes are a join to a cube that doesn't exist, a ${…} reference to a member that isn't there, or a removed dimension that a table column still uses. A wrong column name or bad SQL is quieter: the model compiles, and only queries touching that member fail.

So every write follows the same loop:

  1. Keep the before-state. For an edit, hold the full current definition you just read. For a create, remember the new id.
  2. Write.
  3. Verify at once with meta filtered to the cube's name. An error there means the org's model no longer compiles. Restore immediately: write the saved definition back, or delete the cube you just created. Then tell the user what happened, and don't keep editing on a broken model. The error itself says only "The RevOS API failed with status 500" — the compile error isn't passed through, so don't promise the user a cause; point them to the logs or Cube Playground for it. If meta still shows the old version, wait a few seconds and read again; Cube polls for changes.
  4. Prove the SQL with one small query over the members you added or changed: api_read { "resource": "cubes", "method": "query", "body": { "query": { "dimensions": ["crm_deals.stage"], "measures": ["crm_deals.count"], "limit": 3 } } }. An error here names the bad column or expression. Fix it the same way.

Writes need the Developer (or Admin) role. A 403 means the connected user doesn't have it, so say so rather than retrying.

Before the first write: two checks

What's generated, not stored? meta lists the stored cubes plus what RevOS generates: a cube per table with stored columns or scores (model_stream_…___local, titled [Table] <name>), one per static segment (segment_…, [Segment] <name>), and a view per table (model_…). These also add joins onto stored cubes, so a cube's joins in meta can list joins its stored definition doesn't have. An org with no stored cubes still shows the generated ones; creating a cube adds to them and removes nothing.

Are the cubes managed as code? Some orgs ship cubes from a repo with the RevOS CLI (revos apply). An edit made here is overwritten on their next apply. If the user mentions a repo or the CLI, point them there instead.

Reading

  • What's defined, and how: list with fields: "id,name,updatedAt", then get by id for the full definition. The list's filter is CEL on name (name == "crm_deals", name.startsWith("hubspot_")).
  • What's actually queryable: meta. It differs from the stored list:
    • It is compiled. Members are fully qualified, such as crm_deals.amount, and use camelCase keys.
    • It adds the cubes RevOS generates itself, which you never write:
      • a cube per table that has stored columns or scores, named model_stream_…___local (a table that only reads cubes has none);
      • a cube per static segment, named segment_…;
      • a view per table.

When the user asks how a cube is defined, show the relevant part of the stored definition: the table, the dimensions with their types, the measures, and the joins. Explain it in plain words. Don't dump the JSON. To answer questions about the data, switch to semantic-model.

Who depends on a cube

Before you rename or remove anything, or delete a cube, find its users. Each reference to the old name or member breaks:

  • Other cubes: a joins key equal to this cube's name, or ${name.…} in any join, dimension, or measure SQL. Get each stored definition and search it. Joins are declared on either side.
  • Tables: list them with api_read { "resource": "tables", "params": { "fields": "id,name,streams,objectsColumns" } }. Each table has:
    • streams[].id (a cube name) and streams[].joinPath (dotted cube names);
    • objectsColumns[]: each external: true one has streamId + path pointing at a cube's dimension, or its measure when measure: true. A stream without joinPath is joined as <root>.<id>.
  • Segments: list them, then get each by id. Each has cubes[].joinPath and the members in its filter. A STATIC one also joins its segment_… cube on cubes[0]'s primaryKeyDimension.
  • Dashboard cards: list them with api_read { "resource": "dashboard-cards", "params": { "fields": "id,dashboardId,title,measure,breakdown,filter,joinPaths", "pageSize": 200 } }. Each names members in measure, breakdown and its filter, and cubes in joinPaths. Cards aren't checked when the model changes: a broken one doesn't stop the model compiling, it just shows as unavailable on the dashboard — still worth telling the user.

Report what you found to the user before acting: "crm_deals is used by the Deals table (7 columns), 2 segments and 3 dashboard cards".

Creating, editing, deleting

Each has its own reference. Read the one you need before writing:

Reporting back

After a write, tell the user in two or three sentences:

  • what changed, in their terms ("added Amount as a sum measure on Deals");
  • that meta compiled and a test query ran;
  • any judgment call you made, such as a join's relationship or a dimension's type.

If you had to restore, say so plainly, along with the error that caused it.

Comments

Markdown supported