Skip to main content
Glama

Query a connected table

query_table
Read-onlyIdempotent

A bounded, structured query over one table's current version. NO SQL: send columns, filters, order_by, aggregates, group_by and limit as JSON. Example: {"table_id": "0f2f...", "columns": ["observed_at", "air_temp_f"], "filters": [{"column": "air_temp_f", "operator": "gte", "value": 80}], "order_by": [{"column": "observed_at", "direction": "desc"}], "limit": 50}. Ceilings: 64 columns, 8 filters, 2 sort keys, 4 aggregates, 4 group keys, 10000 rows a page (25 when limit is omitted), 8 MiB of JSON. Every page answers with next_cursor; send it back as cursor (same columns, filters and order_by) for the next page until it is null, and you have read the whole table on one immutable version. Operators, all ANDed: eq, neq, in (an array of at most 20 values), gt, gte, lt, lte, is_null and is_not_null (no value), between (exactly two non-null bounds, inclusive at both ends), and contains, starts_with and ends_with (one non-empty string, case-sensitive, text columns only). Dates and timestamps compare as ISO strings, so a month is one between or a gte plus an lt. GROUPED AGGREGATES: send group_by beside aggregates for one row per distinct combination, keyed by the group column names and the aggregate aliases. Example: {"table_id": "0f2f...", "columns": ["station"], "group_by": ["station"], "aggregates": [{"function": "avg", "column": "air_temp_f", "as": "avg_temp"}], "order_by": [{"column": "avg_temp", "direction": "desc"}], "limit": 10}. An aggregate answers under its as, or under {function}{column or "all"}{position} without one. group_by needs at least one aggregate, no two result columns may share a name and names are compared without case (group_by ["city"] refuses an alias of "CITY", and two aggregates cannot share one alias), and order_by may only name a group column or an alias. limit counts GROUPS, execution.truncated means the limit was reached so there may be more groups, and a grouped answer has no next page: next_cursor is null and offset and cursor stay refused beside aggregates. Without group_by an aggregate query returns one row for the whole table and cannot be ordered. Requires an mr_use_ workspace key (Authorization: Bearer) or an OAuth connection. The first query over a dataset connects it to the workspace; connect_dataset makes that explicit but is not required. Returns rows plus table.version_id and table.content_digest; cite those. For the whole table in one request, download the Parquet instead.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
offsetNo
columnsYes
filtersNo
group_byNo
order_byNo
table_idYes
aggregatesNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / filters / items / properties / operator / enum
      Previous value: -[
      -  "eq",
      -  "neq",
      -  "in",
      -  "gt",
      -  "gte",
      -  "lt",
      -  "lte",
      -  "is_null",
      -  "is_not_null"
      -]New value: +[
      +  "eq",
      +  "neq",
      +  "in",
      +  "gt",
      +  "gte",
      +  "lt",
      +  "lte",
      +  "is_null",
      +  "is_not_null",
      +  "between",
      +  "contains",
      +  "starts_with",
      +  "ends_with"
      +]
    • addedInput schema / properties / group_by
      Added value: +{
      +  "default": [],
      +  "items": {
      +    "maxLength": 128,
      +    "minLength": 1,
      +    "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
      +    "type": "string"
      +  },
      +  "maxItems": 4,
      +  "type": "array"
      +}
  2. Changed3 schema fields changed
    • addedInput schema / properties / cursor
      Added value: +{
      +  "maxLength": 512,
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedInput schema / properties / limit / maximum
      Previous value: -100New value: +10000
    • addedInput schema / properties / offset
      Added value: +{
      +  "maximum": 100000000,
      +  "minimum": 0,
      +  "type": "integer"
      +}
  3. First observed

TDQS

A4.9/5.0
Behavior5/5

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

Annotations declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is already known. The description adds substantial behavioral context beyond annotations: pagination via next_cursor, immutable version semantics, ceilings on columns/filters/sort keys/aggregates/group keys/rows, grouped aggregate behavior, the meaning of execution.truncated, and the requirement for an mr_use_ workspace key or OAuth connection. It also discloses that the first query connects the dataset to the workspace, which is a side effect not implied by the read-only annotation. No contradiction with annotations.

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 dense but well-organized, with the core purpose front-loaded and examples embedded for clarity. Every sentence adds information, and the structure flows from basic query shape to operators to grouped aggregates to auth and alternatives. It is long, but the tool is complex with 9 parameters and many constraints; the length is justified. It loses one point because the density makes it harder to parse quickly, and some details (like the exact JSON example) could be trimmed without losing essential meaning.

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 with 9 parameters, no output schema, and no schema description coverage, the description is remarkably complete. It covers the query shape, all operators, pagination, grouping, aggregation, naming constraints, auth requirements, side effects, and the alternative for whole-table downloads. It even tells the agent to cite table.version_id and table.content_digest in responses. There is no output schema, so the description's explanation of return values (rows plus version_id and content_digest, next_cursor, execution.truncated) is essential and present.

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 carries the full burden of explaining parameters. It explains table_id, columns, filters (with all operators and their value requirements), order_by, limit, cursor, group_by, and aggregates (with aliases and naming rules). It provides two concrete JSON examples that illustrate how the parameters compose. It also explains edge cases like limit counting groups, offset and cursor being refused beside aggregates, and the behavior of aggregate queries without group_by. This far exceeds what the schema alone provides.

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 description opens with a precise verb and resource: 'A bounded, structured query over one table's current version.' It immediately distinguishes itself from siblings like query_run, sample_rows, and get_table by stating it is a structured, non-SQL query over a single table's current version. The title 'Query a connected table' is reinforced with concrete detail about what the tool does and does not do (NO SQL).

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?

The description explicitly states when to use this tool versus alternatives: 'For the whole table in one request, download the Parquet instead.' It also mentions connect_dataset as an explicit alternative for connecting a dataset, and clarifies that the first query over a dataset connects it to the workspace. The description gives clear context on when to use this tool (bounded structured queries) and when not to (whole-table downloads).

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