Skip to main content
Glama

socrata-mcp-server

Query Dataset

socrata_query_dataset
Read-onlyIdempotent

Execute a SoQL query against any dataset on any Socrata portal. Use the search parameter for quick full-text lookup, or combine select/where/group/having/order for full analytical control. Returns rows plus the assembled SoQL string so you can learn the pattern. Columns are referenced by API field name (field_name from socrata_get_dataset, e.g. cuisine_description), never the display label. All SODA 2.1 row values are strings even for numeric columns — check data_type from socrata_get_dataset to determine correct WHERE quoting: Number columns use bare literals (year=2023), Text columns use single-quoted strings (year='2023'). To enumerate distinct values, use select="col, count(*) as n" with group="col" and order="n DESC". When the server has a canvas and more rows match past a full page, up to 50,000 matching rows spill to a DataCanvas table whatever the limit: list its columns with socrata_dataframe_describe, then run SQL with socrata_dataframe_query. Pass stage false to return the page alone, without staging.

Input Schema

NameRequiredDescriptionDefault
groupNoSoQL GROUP BY clause over API field names (field_name from socrata_get_dataset). Requires an aggregate function in select.
limitNoMax rows to return (1–50,000). One call returns at most 5,000 rows: a larger limit is served as 5,000, with a notice naming the offset that continues when more rows match. Default 100. Use with offset for pagination. When the server has a canvas and more rows match past a full page, up to 50,000 matching rows are staged on it whatever the limit — pass a small limit (e.g. 10) to stage a large match without a large inline page, or stage false to return the page without staging.
orderNoSoQL ORDER BY clause over API field names or select aliases, e.g. "total_deaths DESC" or "date ASC".
stageNoStage the matching rows on a canvas when more rows match past this page and the server has a canvas. Default true. Pass false to return the page alone, skipping the staging request; canvas_id and table_name then go unused.
whereNoSoQL WHERE clause over API field names (field_name from socrata_get_dataset). Check column data_type there first — Number columns: year=2023, Text columns: year='2023'; an unquoted text value is read as a column name. Operators: =, !=, >, <, LIKE, IN(...), BETWEEN, IS NULL, starts_with(), contains(), AND, OR, NOT.
domainNoPortal the dataset lives on, as a bare hostname (e.g. data.cityofnewyork.us); URL forms like https://data.cityofnewyork.us/ are accepted and reduced to the host. Pass the domain from the same socrata_find_datasets result as dataset_id. Defaults to SOCRATA_DEFAULT_DOMAIN or data.seattle.gov, which is wrong for another portal’s ID.
havingNoSoQL HAVING clause. Filters on aggregated results, e.g. count > 100.
offsetNoRow offset for pagination. Default 0.
searchNoFull-text search across all text columns ($q). For field-specific filtering, use where instead.
selectNoSoQL SELECT clause — API field names (field_name from socrata_get_dataset, not display labels), aliases, aggregates: "state, sum(deaths) as total_deaths". Omit for all columns.
canvas_idNoOptional 10-char DataCanvas token from a prior socrata_query_dataset or socrata_dataframe_describe call. Omit on first call to mint a fresh canvas. Large result sets spill here automatically unless stage is false.
dataset_idYesFour-by-four dataset ID (e.g. kzjm-xkqj). IDs are portal-scoped: take it from socrata_find_datasets together with that result’s domain.
table_nameNoName for the canvas table a spill stages: letters, digits, and underscores, starting with a letter or underscore, 63 characters at most; lowercased, and not a SQL keyword such as select or order. Defaults to a name derived from dataset_id (ijzp_q8t2_rows). A spill under a name the canvas already holds replaces that table, so give each extract its own name, with the same canvas_id, to keep several on one canvas.

Output Schema

NameRequiredDescriptionDefault
capNoThe row limit that was applied when capped.
rowsNoResult rows. Scalar values are strings (SODA 2.1); geo/location columns return nested objects. Use column schema from socrata_get_dataset for type context.
errorNoPresent when the call failed. Absent on success.
shownNoRows returned in this response when capped.
domainNoPortal hostname queried, normalized from the domain input.
noticeNoGuidance when the query returned zero rows (review the SoQL or broaden the filter; past offset 0, whether the offset passed the end of the match), or when more rows match past this page: how to page, naming the requested and served limit when a limit above the 5,000-row per-call cap was served as 5,000; the staged table to query when the result spilled, and the earlier table of that name it replaced; or why nothing was staged, naming a canvas_id or table_name that stage false left unused. Absent otherwise.
canvas_idNoDataCanvas token when results spilled. Pass to socrata_dataframe_query to run SQL over the staged rows in table_name — a bounded copy of the matching set (up to 50,000 rows, reported in canvas_row_count), not the full set when total_count exceeds that cap. Page with offset to reach rows beyond it.
row_countNoRows returned in this response.
truncatedNoTrue when more rows match past this page: total_count exceeds offset + row_count, or rows filled the limit and no count was made. Spills to canvas when enabled and stage is not false; table_name names the staged table.
dataset_idNoDataset ID queried.
table_nameNoCanvas table holding the staged rows; present when canvas_id is. Use it as the FROM target in socrata_dataframe_query SQL; list its columns with socrata_dataframe_describe.
total_countNoRows the query matches, in the same unit as rows: groups for a grouped query, distinct values for a distinct select. Counted when rows fill limit or a page past offset 0 comes back empty; present when the match holds more rows than this response. Absent otherwise, and when the count failed or ran past its 15-second bound.
assembled_queryNoSoQL clauses assembled for this request — useful for learning the syntax.
canvas_row_countNoRows staged onto the DataCanvas — a bounded copy of the matching result set (capped at 50,000). Fewer than total_count when the match exceeds the cap. Present only when canvas_id is.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed8 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Optional 10-char DataCanvas token from a prior socrata_query_dataset or socrata_dataframe_describe call. Omit on first call to mint a fresh canvas. Large result sets spill here automatically."New value: +"Optional 10-char DataCanvas token from a prior socrata_query_dataset or socrata_dataframe_describe call. Omit on first call to mint a fresh canvas. Large result sets spill here automatically unless stage is false."
    • addedInput schema / properties / dataset_id / pattern
      Added value: +"^[A-Za-z0-9]{4}-[A-Za-z0-9]{4}$"
    • changedInput schema / properties / limit / description
      Previous value: -"Max rows to return (1–50,000). One call returns at most 5,000 rows: a larger limit is served as 5,000, with a notice naming the offset that continues when more rows match. Default 100. Use with offset for pagination. When the server has a canvas and more rows match past a full page, up to 50,000 matching rows are staged on it whatever the limit — pass a small limit (e.g. 10) to stage a large match without a large inline page."New value: +"Max rows to return (1–50,000). One call returns at most 5,000 rows: a larger limit is served as 5,000, with a notice naming the offset that continues when more rows match. Default 100. Use with offset for pagination. When the server has a canvas and more rows match past a full page, up to 50,000 matching rows are staged on it whatever the limit — pass a small limit (e.g. 10) to stage a large match without a large inline page, or stage false to return the page without staging."
    • addedInput schema / properties / stage
      Added value: +{
      +  "default": true,
      +  "description": "Stage the matching rows on a canvas when more rows match past this page and the server has a canvas. Default true. Pass false to return the page alone, skipping the staging request; canvas_id and table_name then go unused.",
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `query_rejected`: The gateway refused query clauses but a bare row request succeeded. `not_tabular`: SODA returned the non-tabular asset access error. `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. `retry_deadline_exceeded`: The portal did not answer the query within the 50-second time limit the call shares across its requests, retries included. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `query_rejected`: The gateway refused query clauses but a bare row request succeeded. `not_tabular`: The asset has no queryable rows: SODA refused row access to a non-tabular asset (HTTP 403), or answered with no fields, as maps, charts, calendars, and visualizations do. data.asset_type and data.parent_dataset_ids then name the asset type and the tables it is built on, when the catalog lists them. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. `retry_deadline_exceeded`: The portal did not answer the query within the 50-second time limit the call shares across its requests, retries included. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "query_rejected",
      -  "not_tabular",
      -  "invalid_id",
      -  "not_found",
      -  "unknown_domain",
      -  "invalid_domain",
      -  "soql_error",
      -  "rate_limited",
      -  "retry_deadline_exceeded"
      -]New value: +[
      +  "query_rejected",
      +  "not_tabular",
      +  "not_found",
      +  "unknown_domain",
      +  "invalid_domain",
      +  "soql_error",
      +  "rate_limited",
      +  "retry_deadline_exceeded"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when the query returned zero rows (review the SoQL or broaden the filter; past offset 0, whether the offset passed the end of the match), or when more rows match past this page: how to page, naming the requested and served limit when a limit above the 5,000-row per-call cap was served as 5,000; the staged table to query when the result spilled, and the earlier table of that name it replaced; or why nothing was staged. Absent otherwise."New value: +"Guidance when the query returned zero rows (review the SoQL or broaden the filter; past offset 0, whether the offset passed the end of the match), or when more rows match past this page: how to page, naming the requested and served limit when a limit above the 5,000-row per-call cap was served as 5,000; the staged table to query when the result spilled, and the earlier table of that name it replaced; or why nothing was staged, naming a canvas_id or table_name that stage false left unused. Absent otherwise."
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when more rows match past this page: total_count exceeds offset + row_count, or rows filled the limit and no count was made. Spills to canvas when enabled; table_name names the staged table."New value: +"True when more rows match past this page: total_count exceeds offset + row_count, or rows filled the limit and no count was made. Spills to canvas when enabled and stage is not false; table_name names the staged table."
  2. Changed10 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Optional 10-char DataCanvas token from a prior socrata_query_dataset or socrata_dataframe_describe call. Omit on first call when CANVAS_PROVIDER_TYPE=duckdb to mint a fresh canvas. Large result sets spill here automatically."New value: +"Optional 10-char DataCanvas token from a prior socrata_query_dataset or socrata_dataframe_describe call. Omit on first call to mint a fresh canvas. Large result sets spill here automatically."
    • changedInput schema / properties / limit / description
      Previous value: -"Max rows to return (1–5000). Default 100. Use with offset for pagination. When the canvas is enabled and the page fills limit, up to 50,000 matching rows are staged on it whatever the limit — pass a small limit (e.g. 10) to stage a large match without a large inline page."New value: +"Max rows to return (1–50,000). One call returns at most 5,000 rows: a larger limit is served as 5,000, with a notice naming the offset that continues when more rows match. Default 100. Use with offset for pagination. When the server has a canvas and more rows match past a full page, up to 50,000 matching rows are staged on it whatever the limit — pass a small limit (e.g. 10) to stage a large match without a large inline page."
    • changedInput schema / properties / limit / maximum
      Previous value: -5000New value: +50000
    • addedInput schema / properties / table_name
      Added value: +{
      +  "description": "Name for the canvas table a spill stages: letters, digits, and underscores, starting with a letter or underscore, 63 characters at most; lowercased, and not a SQL keyword such as select or order. Defaults to a name derived from dataset_id (ijzp_q8t2_rows). A spill under a name the canvas already holds replaces that table, so give each extract its own name, with the same canvas_id, to keep several on one canvas.",
      +  "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,62}$",
      +  "type": "string"
      +}
    • changedOutput schema / properties / canvas_id / description
      Previous value: -"DataCanvas token when results spilled (requires CANVAS_PROVIDER_TYPE=duckdb). Pass to socrata_dataframe_query to run SQL over the staged rows in table_name — a bounded copy of the matching set (up to 50,000 rows, reported in canvas_row_count), not the full set when total_count exceeds that cap. Page with offset to reach rows beyond it."New value: +"DataCanvas token when results spilled. Pass to socrata_dataframe_query to run SQL over the staged rows in table_name — a bounded copy of the matching set (up to 50,000 rows, reported in canvas_row_count), not the full set when total_count exceeds that cap. Page with offset to reach rows beyond it."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `query_rejected`: The gateway refused query clauses but a bare row request succeeded. `not_tabular`: SODA returned the non-tabular asset access error. `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `query_rejected`: The gateway refused query clauses but a bare row request succeeded. `not_tabular`: SODA returned the non-tabular asset access error. `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. `retry_deadline_exceeded`: The portal did not answer the query within the 50-second time limit the call shares across its requests, retries included. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "query_rejected",
      -  "not_tabular",
      -  "invalid_id",
      -  "not_found",
      -  "unknown_domain",
      -  "invalid_domain",
      -  "soql_error",
      -  "rate_limited"
      -]New value: +[
      +  "query_rejected",
      +  "not_tabular",
      +  "invalid_id",
      +  "not_found",
      +  "unknown_domain",
      +  "invalid_domain",
      +  "soql_error",
      +  "rate_limited",
      +  "retry_deadline_exceeded"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when the query returned zero rows (review the SoQL or broaden the filter), or when rows filled the limit (how to page, and the staged table to query when the result spilled). Absent otherwise."New value: +"Guidance when the query returned zero rows (review the SoQL or broaden the filter; past offset 0, whether the offset passed the end of the match), or when more rows match past this page: how to page, naming the requested and served limit when a limit above the 5,000-row per-call cap was served as 5,000; the staged table to query when the result spilled, and the earlier table of that name it replaced; or why nothing was staged. Absent otherwise."
    • changedOutput schema / properties / total_count / description
      Previous value: -"Total matching source rows when a plain row query is truncated (row_count < total_count). Absent when the full result fits and for grouped/aggregate queries (group set), where a source-row count would not describe the returned groups."New value: +"Rows the query matches, in the same unit as rows: groups for a grouped query, distinct values for a distinct select. Counted when rows fill limit or a page past offset 0 comes back empty; present when the match holds more rows than this response. Absent otherwise, and when the count failed or ran past its 15-second bound."
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when rows filled the limit — more rows may match (see total_count when present). Spills to canvas when enabled; table_name names the staged table."New value: +"True when more rows match past this page: total_count exceeds offset + row_count, or rows filled the limit and no count was made. Spills to canvas when enabled; table_name names the staged table."
  3. Changed2 schema fields changed
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `query_rejected`: The gateway refused query clauses but a bare row request succeeded. `not_tabular`: SODA returned the non-tabular asset access error. `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "invalid_id",
      -  "not_found",
      -  "unknown_domain",
      -  "invalid_domain",
      -  "soql_error",
      -  "rate_limited"
      -]New value: +[
      +  "query_rejected",
      +  "not_tabular",
      +  "invalid_id",
      +  "not_found",
      +  "unknown_domain",
      +  "invalid_domain",
      +  "soql_error",
      +  "rate_limited"
      +]
  4. Changed5 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"Max rows to return (1–5000). Default 100. Use with offset for pagination."New value: +"Max rows to return (1–5000). Default 100. Use with offset for pagination. When the canvas is enabled and the page fills limit, up to 50,000 matching rows are staged on it whatever the limit — pass a small limit (e.g. 10) to stage a large match without a large inline page."
    • changedOutput schema / properties / canvas_id / description
      Previous value: -"DataCanvas token when results spilled (requires CANVAS_PROVIDER_TYPE=duckdb). Pass to socrata_dataframe_query to run SQL over the staged rows — a bounded copy of the matching set (up to 50,000 rows, reported in canvas_row_count), not the full set when total_count exceeds that cap. Page with offset to reach rows beyond it."New value: +"DataCanvas token when results spilled (requires CANVAS_PROVIDER_TYPE=duckdb). Pass to socrata_dataframe_query to run SQL over the staged rows in table_name — a bounded copy of the matching set (up to 50,000 rows, reported in canvas_row_count), not the full set when total_count exceeds that cap. Page with offset to reach rows beyond it."
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when the query returned zero rows — suggests narrowing or reviewing the SoQL. Absent on non-empty result sets."New value: +"Guidance when the query returned zero rows (review the SoQL or broaden the filter), or when rows filled the limit (how to page, and the staged table to query when the result spilled). Absent otherwise."
    • addedOutput schema / properties / table_name
      Added value: +{
      +  "description": "Canvas table holding the staged rows; present when canvas_id is. Use it as the FROM target in socrata_dataframe_query SQL; list its columns with socrata_dataframe_describe.",
      +  "type": "string"
      +}
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when rows filled the limit — more rows may match (see total_count when present). Spills to canvas when enabled."New value: +"True when rows filled the limit — more rows may match (see total_count when present). Spills to canvas when enabled; table_name names the staged table."
  5. Changed9 schema fields changed
    • changedInput schema / properties / dataset_id / description
      Previous value: -"Four-by-four dataset ID (e.g. kzjm-xkqj). Obtain from socrata_find_datasets."New value: +"Four-by-four dataset ID (e.g. kzjm-xkqj). IDs are portal-scoped: take it from socrata_find_datasets together with that result’s domain."
    • changedInput schema / properties / domain / description
      Previous value: -"Portal domain (e.g. data.seattle.gov). Defaults to SOCRATA_DEFAULT_DOMAIN or data.seattle.gov."New value: +"Portal the dataset lives on, as a bare hostname (e.g. data.cityofnewyork.us); URL forms like https://data.cityofnewyork.us/ are accepted and reduced to the host. Pass the domain from the same socrata_find_datasets result as dataset_id. Defaults to SOCRATA_DEFAULT_DOMAIN or data.seattle.gov, which is wrong for another portal’s ID."
    • changedInput schema / properties / group / description
      Previous value: -"SoQL GROUP BY clause. Requires an aggregate function in select."New value: +"SoQL GROUP BY clause over API field names (field_name from socrata_get_dataset). Requires an aggregate function in select."
    • changedInput schema / properties / order / description
      Previous value: -"SoQL ORDER BY clause, e.g. \"total_deaths DESC\" or \"date ASC\"."New value: +"SoQL ORDER BY clause over API field names or select aliases, e.g. \"total_deaths DESC\" or \"date ASC\"."
    • changedInput schema / properties / select / description
      Previous value: -"SoQL SELECT clause — column names, aliases, aggregates: \"state, sum(deaths) as total_deaths\". Omit for all columns."New value: +"SoQL SELECT clause — API field names (field_name from socrata_get_dataset, not display labels), aliases, aggregates: \"state, sum(deaths) as total_deaths\". Omit for all columns."
    • changedInput schema / properties / where / description
      Previous value: -"SoQL WHERE clause. Check column dataType from socrata_get_dataset first — Number columns: year=2023, Text columns: year='2023'. Operators: =, !=, >, <, LIKE, IN(...), BETWEEN, IS NULL, starts_with(), contains(), AND, OR, NOT."New value: +"SoQL WHERE clause over API field names (field_name from socrata_get_dataset). Check column data_type there first — Number columns: year=2023, Text columns: year='2023'; an unquoted text value is read as a column name. Operators: =, !=, >, <, LIKE, IN(...), BETWEEN, IS NULL, starts_with(), contains(), AND, OR, NOT."
    • changedOutput schema / properties / domain / description
      Previous value: -"Portal domain queried."New value: +"Portal hostname queried, normalized from the domain input."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: Dataset does not exist on this domain. `soql_error`: SoQL syntax error or unknown column name. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: The dataset does not exist on the domain queried — including a gateway HTTP 403 for an ID the portal does not serve. `unknown_domain`: The domain does not serve the Socrata API to this server: its hostname does not resolve (DNS ENOTFOUND), its API answered HTTP 404 without a Socrata error body, it redirected the request to another host that did not answer with Socrata data, or a gateway refused a dataset the Discovery catalog lists there. `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. `soql_error`: SoQL syntax error, unknown column, or literal/column type mismatch. data.socrataCode carries the upstream code and data.column the offending token when upstream names one. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "invalid_id",
      -  "not_found",
      -  "soql_error",
      -  "rate_limited"
      -]New value: +[
      +  "invalid_id",
      +  "not_found",
      +  "unknown_domain",
      +  "invalid_domain",
      +  "soql_error",
      +  "rate_limited"
      +]
  6. Changed2 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Optional 10-char DataCanvas token from a prior call. Omit on first call when CANVAS_PROVIDER_TYPE=duckdb to mint a fresh canvas. Large result sets spill here automatically."New value: +"Optional 10-char DataCanvas token from a prior socrata_query_dataset or socrata_dataframe_describe call. Omit on first call when CANVAS_PROVIDER_TYPE=duckdb to mint a fresh canvas. Large result sets spill here automatically."
    • addedInput schema / properties / canvas_id / pattern
      Added value: +"^[A-Za-z0-9_-]{10}$"
  7. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "rows",
      +      "row_count",
      +      "assembled_query",
      +      "domain",
      +      "dataset_id"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: Dataset does not exist on this domain. `soql_error`: SoQL syntax error or unknown column name. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "invalid_id",
      +            "not_found",
      +            "soql_error",
      +            "rate_limited"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "rows",
      -  "row_count",
      -  "assembled_query",
      -  "domain",
      -  "dataset_id"
      -]
  8. Changed2 schema fields changed
    • changedOutput schema / properties / canvas_id / description
      Previous value: -"DataCanvas token when results spilled (requires CANVAS_PROVIDER_TYPE=duckdb). Pass to socrata_dataframe_query for SQL over the full result set."New value: +"DataCanvas token when results spilled (requires CANVAS_PROVIDER_TYPE=duckdb). Pass to socrata_dataframe_query to run SQL over the staged rows — a bounded copy of the matching set (up to 50,000 rows, reported in canvas_row_count), not the full set when total_count exceeds that cap. Page with offset to reach rows beyond it."
    • addedOutput schema / properties / canvas_row_count
      Added value: +{
      +  "description": "Rows staged onto the DataCanvas — a bounded copy of the matching result set (capped at 50,000). Fewer than total_count when the match exceeds the cap. Present only when canvas_id is.",
      +  "type": "number"
      +}
  9. Changed2 schema fields changed
    • changedOutput schema / properties / total_count / description
      Previous value: -"Total matching rows when result is truncated (row_count < total_count). Absent when the full result fits."New value: +"Total matching source rows when a plain row query is truncated (row_count < total_count). Absent when the full result fits and for grouped/aggregate queries (group set), where a source-row count would not describe the returned groups."
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when rows filled the limit — more rows match (see total_count). Spills to canvas when enabled."New value: +"True when rows filled the limit — more rows may match (see total_count when present). Spills to canvas when enabled."
  10. Changed3 schema fields changed
    • addedOutput schema / properties / cap
      Added value: +{
      +  "description": "The row limit that was applied when capped.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / shown
      Added value: +{
      +  "description": "Rows returned in this response when capped.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / truncated
      Added value: +{
      +  "description": "True when rows filled the limit — more rows match (see total_count). Spills to canvas when enabled.",
      +  "type": "boolean"
      +}
  11. Changed1 schema field changed
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Guidance when the query returned zero rows — suggests narrowing or reviewing the SoQL. Absent on non-empty result sets.",
      +  "type": "string"
      +}
  12. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the readOnly/idempotent/openWorld annotations, the description discloses non-obvious behavior: results return the assembled SoQL string, all SODA 2.1 values are strings regardless of column type, a full page is 5,000 rows while up to 50,000 matching rows spill to the canvas, and a spill under an existing table name replaces it. That is exactly the operational context annotations cannot convey.

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?

Dense but well ordered — core purpose, then query-shape advice, then type/quoting caveats, then the canvas spill escalation, then the stage opt-out. The closing 'Pass stage false to return the page alone, without staging' duplicates the stage parameter's schema description and could be trimmed.

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 13-parameter tool with an output schema and annotations already covering safety, the description fills the remaining gaps an agent needs: correct quoting per data_type, domain scoping risks (default portal is wrong for another portal's ID), the 5,000-row page vs 50,000-row spill behavior, and the downstream canvas tools.

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 is 3, but the description adds genuine meaning: columns must be API field names not display labels, and WHERE quoting depends on data_type from socrata_get_dataset (bare literals for Number, single-quoted for Text). It slightly restates the stage/limit behavior already in the schema, which keeps it from a 5.

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?

Opens with a specific verb+resource: 'Execute a SoQL query against any dataset on any Socrata portal.' It immediately carves out the division of labor versus siblings (socrata_find_datasets for discovery, socrata_get_dataset for field names, socrata_dataframe_* for follow-up), so an agent can place it in the toolchain without opening the schema.

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?

Gives explicit routing rules: 'Use the search parameter for quick full-text lookup, or combine select/where/group/having/order for full analytical control,' and a concrete alternate path ('To enumerate distinct values, use select="col, count(*) as n" with group="col"...'). It also names when to leave the tool (spill rows → socrata_dataframe_describe then socrata_dataframe_query) and how to opt out ('Pass stage false').

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.