Skip to main content
Glama
This connector has been deprecated

Replaced by io.github.no-fait/infinite-audience

Discovery Crosstab

discovery_crosstab

Generate a cross-tabulation pivot table across two demographic dimensions. Returns rows, columns, bounded cells, total_count for the full population, displayed_count for visible cells, and truncated when row/column limits omit categories. Accepts EXACTLY ONE of: filters (flat array), filter_groups, segment_id, audience_id, or segment_ids+set_logic to define the audience population (more than one is rejected with AMBIGUOUS_INPUT). Grouped logic, saved audience exclusions, and record limits are preserved. Requires 'discovery' scope.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "row_field": "<row_field>",
      "col_field": "<col_field>"
    },
    "name": "discovery_crosstab"
  }
}

Input Schema

NameRequiredDescriptionDefault
filtersNoFlat filter array to define the audience population
max_colsNoMaximum number of column values to return (default 10)
max_rowsNoMaximum number of row values to return (default 20)
col_fieldYesDifferent field with groupable=true from get_field_catalog for pivot columns
col_labelNoHuman-readable label for the column dimension
row_fieldYesField with groupable=true from get_field_catalog for pivot rows
row_labelNoHuman-readable label for the row dimension
set_logicNoHow to combine segment_ids
segment_idNoSaved segment ID
audience_idNoSaved audience ID
segment_idsNoMultiple segment IDs to compose
filter_groupsNoCompound filter groups

Output Schema

NameRequiredDescriptionDefault
rowsYes
cellsYes
columnsYes
guidanceNoInterpretation or recovery guidance for this result
col_fieldYes
col_labelYes
row_fieldYes
row_labelYes
truncatedYes
count_unitNo
page_countNoNumber of objects on this page, not the organization total
count_stateNoUnknown means no count; available does not guarantee freshness. Recount for a current value.
total_countYes
next_actionsNoSuggested next calls using returned IDs and available scopes. Not executed and not user consent.
displayed_countYes
population_inputNoPopulation input used for the preview; IDs refer to their current saved definitions

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed12 schema fields changed
    • changedInput schema / properties / col_field / description
      Previous value: -"Field name for pivot columns"New value: +"Different field with groupable=true from get_field_catalog for pivot columns"
    • changedInput schema / properties / filter_groups / items / additionalProperties
      Previous value: -{}New value: +false
    • addedInput schema / properties / filter_groups / items / properties
      Added value: +{
      +  "combinator": {
      +    "description": "Join to the preceding included group; ignored for the first group. AND binds before OR. Exclusion groups always subtract.",
      +    "enum": [
      +      "AND",
      +      "OR"
      +    ],
      +    "type": "string"
      +  },
      +  "filters": {
      +    "description": "All conditions in this group must match",
      +    "items": {
      +      "additionalProperties": false,
      +      "properties": {
      +        "field": {
      +          "description": "field_name from get_field_catalog; ZIP5 also accepts zip, zip_code or postal_code. Use published operators and enum_values",
      +          "minLength": 1,
      +          "type": "string"
      +        },
      +        "op": {
      +          "enum": [
      +            "=",
      +            "!=",
      +            "<",
      +            "<=",
      +            ">",
      +            ">=",
      +            "IN",
      +            "NOT IN",
      +            "BETWEEN",
      +            "LIKE",
      +            "ARRAY_CONTAINS",
      +            "ARRAY_CONTAINS_ANY",
      +            "IS NULL",
      +            "IS NOT NULL"
      +          ],
      +          "type": "string"
      +        },
      +        "text_comparison": {
      +          "description": "STRING =, !=, IN, NOT IN, LIKE and ARRAY<STRING> ARRAY_CONTAINS, ARRAY_CONTAINS_ANY. Default exact. case_insensitive applies Unicode case folding to stored text and the supplied value; use when capitalization is incidental.",
      +          "enum": [
      +            "exact",
      +            "case_insensitive"
      +          ],
      +          "type": "string"
      +        },
      +        "trim_whitespace": {
      +          "description": "Supported STRING or ARRAY<STRING> comparisons only. Trim leading/trailing whitespace on both sides; default false.",
      +          "type": "boolean"
      +        },
      +        "value": {
      +          "anyOf": [
      +            {
      +              "type": "string"
      +            },
      +            {
      +              "type": "number"
      +            },
      +            {
      +              "type": "boolean"
      +            },
      +            {
      +              "items": {
      +                "anyOf": [
      +                  {
      +                    "type": "string"
      +                  },
      +                  {
      +                    "type": "number"
      +                  },
      +                  {
      +                    "type": "boolean"
      +                  }
      +                ]
      +              },
      +              "type": "array"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ],
      +          "description": "Scalar for comparisons; array for IN/NOT IN; ARRAY_CONTAINS_ANY matches any listed value; [lower, upper] inclusive for BETWEEN; LIKE uses % for any sequence and _ for one character; omit for IS NULL/IS NOT NULL. Use enum_values codes, not display labels"
      +        }
      +      },
      +      "required": [
      +        "field",
      +        "op"
      +      ],
      +      "type": "object"
      +    },
      +    "minItems": 1,
      +    "type": "array"
      +  },
      +  "id": {
      +    "description": "Caller-chosen group ID, for example geography; prefix _exclude:: to subtract this group",
      +    "minLength": 1,
      +    "type": "string"
      +  }
      +}
    • removedInput schema / properties / filter_groups / items / propertyNames
      Removed value: -{
      -  "type": "string"
      -}
    • addedInput schema / properties / filter_groups / items / required
      Added value: +[
      +  "id",
      +  "combinator",
      +  "filters"
      +]
    • changedInput schema / properties / filters / items / additionalProperties
      Previous value: -{}New value: +false
    • addedInput schema / properties / filters / items / properties
      Added value: +{
      +  "field": {
      +    "description": "field_name from get_field_catalog; ZIP5 also accepts zip, zip_code or postal_code. Use published operators and enum_values",
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "op": {
      +    "enum": [
      +      "=",
      +      "!=",
      +      "<",
      +      "<=",
      +      ">",
      +      ">=",
      +      "IN",
      +      "NOT IN",
      +      "BETWEEN",
      +      "LIKE",
      +      "ARRAY_CONTAINS",
      +      "ARRAY_CONTAINS_ANY",
      +      "IS NULL",
      +      "IS NOT NULL"
      +    ],
      +    "type": "string"
      +  },
      +  "text_comparison": {
      +    "description": "STRING =, !=, IN, NOT IN, LIKE and ARRAY<STRING> ARRAY_CONTAINS, ARRAY_CONTAINS_ANY. Default exact. case_insensitive applies Unicode case folding to stored text and the supplied value; use when capitalization is incidental.",
      +    "enum": [
      +      "exact",
      +      "case_insensitive"
      +    ],
      +    "type": "string"
      +  },
      +  "trim_whitespace": {
      +    "description": "Supported STRING or ARRAY<STRING> comparisons only. Trim leading/trailing whitespace on both sides; default false.",
      +    "type": "boolean"
      +  },
      +  "value": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "number"
      +      },
      +      {
      +        "type": "boolean"
      +      },
      +      {
      +        "items": {
      +          "anyOf": [
      +            {
      +              "type": "string"
      +            },
      +            {
      +              "type": "number"
      +            },
      +            {
      +              "type": "boolean"
      +            }
      +          ]
      +        },
      +        "type": "array"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "description": "Scalar for comparisons; array for IN/NOT IN; ARRAY_CONTAINS_ANY matches any listed value; [lower, upper] inclusive for BETWEEN; LIKE uses % for any sequence and _ for one character; omit for IS NULL/IS NOT NULL. Use enum_values codes, not display labels"
      +  }
      +}
    • removedInput schema / properties / filters / items / propertyNames
      Removed value: -{
      -  "type": "string"
      -}
    • addedInput schema / properties / filters / items / required
      Added value: +[
      +  "field",
      +  "op"
      +]
    • changedInput schema / properties / max_cols / maximum
      Previous value: -50New value: +20
    • changedInput schema / properties / row_field / description
      Previous value: -"Field name for pivot rows (e.g. \"state\", \"age_band\", \"gender\")"New value: +"Field with groupable=true from get_field_catalog for pivot rows"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": {},
      +  "properties": {
      +    "cells": {
      +      "additionalProperties": {
      +        "additionalProperties": {
      +          "type": "number"
      +        },
      +        "propertyNames": {
      +          "type": "string"
      +        },
      +        "type": "object"
      +      },
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    },
      +    "col_field": {
      +      "type": "string"
      +    },
      +    "col_label": {
      +      "type": "string"
      +    },
      +    "columns": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "count_state": {
      +      "description": "Unknown means no count; available does not guarantee freshness. Recount for a current value.",
      +      "enum": [
      +        "unknown",
      +        "available"
      +      ],
      +      "type": "string"
      +    },
      +    "count_unit": {
      +      "const": "records",
      +      "type": "string"
      +    },
      +    "displayed_count": {
      +      "type": "number"
      +    },
      +    "guidance": {
      +      "description": "Interpretation or recovery guidance for this result",
      +      "type": "string"
      +    },
      +    "next_actions": {
      +      "description": "Suggested next calls using returned IDs and available scopes. Not executed and not user consent.",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "arguments": {
      +            "additionalProperties": {},
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "reason": {
      +            "type": "string"
      +          },
      +          "tool": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "tool",
      +          "arguments",
      +          "reason"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "page_count": {
      +      "description": "Number of objects on this page, not the organization total",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "population_input": {
      +      "additionalProperties": {},
      +      "description": "Population input used for the preview; IDs refer to their current saved definitions",
      +      "propertyNames": {
      +        "type": "string"
      +      },
      +      "type": "object"
      +    },
      +    "row_field": {
      +      "type": "string"
      +    },
      +    "row_label": {
      +      "type": "string"
      +    },
      +    "rows": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "total_count": {
      +      "type": "number"
      +    },
      +    "truncated": {
      +      "type": "boolean"
      +    }
      +  },
      +  "required": [
      +    "row_field",
      +    "col_field",
      +    "row_label",
      +    "col_label",
      +    "rows",
      +    "columns",
      +    "cells",
      +    "total_count",
      +    "displayed_count",
      +    "truncated"
      +  ],
      +  "type": "object"
      +}
  2. First observed

TDQS

A3.8/5.0
Behavior4/5

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

Beyond the annotations, the description discloses the return shape (rows, columns, bounded cells, total_count, displayed_count, truncated) and explains that row/column limits cause truncation rather than silent omission. It also notes that grouped logic, saved audience exclusions, and record limits are preserved and that conflicting audience inputs are rejected with AMBIGUOUS_INPUT — concrete failure-mode context the annotations do not carry.

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 definition is dense but front-loaded: purpose first, then return shape and truncation, then the audience-input exclusivity rule and the scope requirement. No sentence is filler, though the middle clause listing five parameter names is terse enough to require a second read.

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?

With 12 parameters, a rich output schema, and five competing audience-input modes, the description covers the highest-risk areas: input exclusivity, truncation semantics, and scope requirements. Field-selection details (groupable=true from get_field_catalog) are delegated to the schema, which is appropriate, so nothing critical is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline would be 3, but the description adds real meaning the schema cannot express: it enforces mutual exclusivity across five audience-definition parameter paths and names the error returned when more than one is supplied. This is a oneOf constraint absent from the JSON schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence gives a specific verb and resource: 'Generate a cross-tabulation pivot table across two demographic dimensions', which is clearly distinct from sibling tools like discovery_count or discovery_overlap. It doesn't explicitly name those alternatives, but the operation is unambiguous.

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

Usage Guidelines3/5

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

The description states a hard input-selection rule (EXACTLY ONE of filters, filter_groups, segment_id, audience_id, or segment_ids+set_logic) and the required 'discovery' scope, which is useful operational guidance. However, it never says when to prefer a crosstab over discovery_count, discovery_lookup, or discovery_overlap, so tool selection versus siblings is left implicit.

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