Skip to main content
Glama

query

Retrieve data from a semantic model by defining measures, dimensions, filters, and time groupings, with support for inline extensions, complex aggregations, and SQL inspection.

Instructions

Query data from a semantic model. Call inspect(reference=".", entity_type="model") first to see available columns and measures.

Args: source_model: One of three forms: - Model name (string) — name of a saved model from models_summary, e.g. "orders". - Inline ModelExtension (dict) — extend an existing model with extra columns/joins/measures for this one query: {"source_name": "orders", "columns": [{"name": "double_amount", "sql": "amount * 2", "type": "DOUBLE"}]}. - Inline SlayerModel (dict) — define a model ad-hoc: {"name": "ad_hoc", "sql_table": "things", "data_source": "test", "columns": [...]}. measures: Aggregated values to return. Each is a formula: {"formula": "*:count"}, {"formula": "revenue:sum / *:count", "name": "aov"} (arithmetic), {"formula": "cumsum(revenue:sum)"} (cumulative sum), {"formula": "change(revenue:sum)"} (period-over-period difference), {"formula": "change_pct(revenue:sum)"} (period-over-period % change, e.g. month-over-month growth), {"formula": "time_shift(revenue:sum, -1)"} (the shifted value itself, one time bucket back), {"formula": "time_shift(revenue:sum, -1, 'year')"} (value from one year earlier, for custom arithmetic), {"formula": "lag(revenue:sum, 1)"} (previous row via window function; shifts by row position, NULL at edges), {"formula": "lead(revenue:sum, 1)"} (next row via window function), {"formula": "last(revenue:sum)"} (most recent), {"formula": "rank(revenue:sum)"} (ranking). A bare name like {"formula": "aov"} resolves to a saved ModelMeasure on the model. change / change_pct / time_shift are calendar-aware and partition-safe: change and change_pct compare each row against the prior time bucket (one step back at the query's own granularity), while time_shift compares at its explicitly requested offset and granularity. All three join on the same non-time dimension values, so per-group series reset cleanly — safe for grouped queries like month-over-month revenue by store. For period-over-period growth, prefer change_pct (or change for the absolute delta); use time_shift only when you need the shifted value itself as a term in your own arithmetic. dimensions: List of dimension names to group by, e.g. ["status", "region"]. filters: Filter conditions as formula strings. Examples: "status == 'completed'", "amount > 100", "status in ('a', 'b')", "status is None", "name like '%acme%'". Filters on measures are automatically routed to HAVING. Supports and/or: "status == 'a' or status == 'b'". Filters can also reference computed measure names or contain inline transforms: "change(revenue:sum) > 0", "last(change(revenue:sum)) < 0". time_dimensions: Time grouping. Format: {"dimension": "created_at", "granularity": "day|week|month|quarter|year", "date_range": ["2024-01-01", "2024-12-31"]}. order: Sorting. Format: {"column": "measure_or_dim_name", "direction": "asc|desc"}. limit: Max rows to return. offset: Number of rows to skip. whole_periods_only: When true, snap date filters to time bucket boundaries based on granularity, exclude the current incomplete time bucket. show_sql: When true, include the generated SQL in the response for debugging. strict: Error instead of warn when a cross-model measure would broadcast or a producer filter would be dropped. Rejected with run-by-name execution — declare it on the stored query instead. dry_run: When true, generate and return the SQL without executing it. explain: When true, run EXPLAIN ANALYZE and return the query plan. format: Output format — "markdown" (default, compact and LLM-friendly), "json" (structured), or "csv" (most compact). Case-insensitive. distinct_dimension_values: Default True (Cube.js-style auto-dedup for dim-only queries — emits GROUP BY ). Set False to emit raw rows: no top-level GROUP BY, just SELECT <dimensions/time_dimensions> with the usual WHERE/ORDER BY/LIMIT. Any measure reference (in measures, filters, or order) raises an error in this mode.

Example: query(source_model="orders", measures=[{"formula": "*:count"}], dimensions=["status"], filters=["status == 'completed'"])

Before calling this tool, run search first, supplying the entities you're thinking of using (and/or the query itself via the query arg, or a free-text question). Read the returned memories and consider any matching example queries before formulating the final query.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo
orderNo
formatNomarkdown
offsetNo
strictNo
dry_runNo
explainNo
filtersNo
measuresNo
show_sqlNo
variablesNo
dimensionsNo
source_modelYes
time_dimensionsNo
whole_periods_onlyNo
distinct_dimension_valuesNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. First observedv0.10.0

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and delivers richly: filters on measures are "automatically routed to HAVING," change/change_pct/time_shift are disclosed as calendar-aware and partition-safe with clean per-group resets, lag/lead are described as window functions with "NULL at edges," strict mode's error/drop behaviors and run-by-name rejection are stated, distinct_dimension_values' auto-dedup GROUP BY behavior and error-on-measure-reference are detailed, and dry_run/explain/show_sql modes are all explained.

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 description is long (~600 words), but the length is justified by 16 parameters and a complex formula grammar. It is well-structured with a front-loaded purpose sentence, per-parameter 'Args' sections, and a worked example. The 'run search first' precondition is buried at the end rather than near the front, which costs it a perfect score.

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

Completeness4/5

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

For a 16-parameter tool with no annotations and zero schema descriptions, the description is remarkably complete: preconditions, parameter semantics, formula grammar, edge cases, error modes, and output format options are all covered, and the output schema covers return values. Minor gaps are the undocumented `variables` parameter and the unaddressed relationship to query_nested.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate — and it nearly does. It explains all three source_model forms with inline dict examples, enumerates measure formula functions with concrete examples, defines filter syntax and HAVING routing, specifies time_dimensions format, and adds meaning to order, whole_periods_only, strict, format, and distinct_dimension_values. Only the `variables` parameter receives no descriptive coverage.

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?

The first sentence, "Query data from a semantic model," states a specific verb plus resource, and the detailed parameter documentation (three source_model forms, measure formulas, filters, time dimensions) makes the operation unambiguous. It is clearly distinguishable from the introspection siblings (inspect, inspect_model, models_summary) and DDL siblings (create_model, edit_model).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit orchestration guidance is given: "Call inspect(reference="<ds>.<model>", entity_type="model") first" and "Before calling this tool, run search first... Read the returned memories and consider any matching example queries." However, it never names alternatives or exclusions — notably, it does not say when to use the sibling query_nested instead, so the when-not dimension is missing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MotleyAI/slayer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server