socrata-mcp-server
Server Details
Search and query government open-data portals (Socrata SODA API).
- Status
- Healthy
- Uptime
- 100.0% over 41 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/socrata-mcp-server
- GitHub Stars
- 3
- Server Listing
- @cyanheads/socrata-mcp-server
TDQS
Scored across 6 tools
Each tool targets a distinct stage in the Socrata workflow: portal discovery, dataset search, schema inspection, remote SoQL query, and local DataFrame operations. Even the two schema-describing tools (get_dataset and dataframe_describe) are clearly separated by remote vs. local context, with cross-references reinforcing boundaries.
All tools share the socrata_ prefix and use clear action words, but there is a minor inconsistency: four tools use verb_noun ordering (find_datasets, get_dataset, list_portals, query_dataset) while two use noun_verb (dataframe_describe, dataframe_query). Still predictable and readable.
Six tools is well-scoped for a Socrata read/query server: discovery, metadata, query, and local SQL fallback. No redundancy or bloat, and the count fits comfortably within the typical 3-15 range.
The toolset covers the full read-only lifecycle: discover portals, search datasets, fetch schema, run SoQL queries, and spill to DataCanvas for SQL. No obvious dead ends or missing operations for the stated purpose.
Available Tools
6 toolssocrata_dataframe_describeDescribe DataCanvas TablesARead-onlyIdempotentInspect
List registered tables in a DataCanvas session — schema, row count, and column names. Shows what datasets are available for SQL queries via socrata_dataframe_query. Only meaningful when CANVAS_PROVIDER_TYPE=duckdb is set. Use after socrata_query_dataset spills a large result set to canvas.
| Name | Required | Description | Default |
|---|---|---|---|
| canvas_id | No | Canvas ID returned by socrata_query_dataset when a large result spills to canvas. Required in practice when canvas is enabled — canvases cannot be enumerated, so omitting it fails with canvas_id_required instead of listing tables. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | Status message when canvas is not enabled or no tables are registered. Absent when tables are present. |
| tables | No | Tables available for SQL queries. Empty when none registered. |
| canvas_id | No | Canvas ID resolved, when canvas is enabled. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the read-only, safe nature is covered. The description adds behavioral context beyond annotations: the environmental dependency on CANVAS_PROVIDER_TYPE=duckdb and the recommended usage after a spill event, which helps an agent understand when this tool will actually work.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no fluff: the first states the core function, the second clarifies what it shows, and the third gives the environmental condition and usage trigger. Every sentence earns its place and the information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple one-parameter design, the presence of an output schema, and annotations covering safety, the description is complete. It tells the agent what the tool does, when it is meaningful, and after which event to use it, leaving no critical gaps for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage, with a detailed description for canvas_id explaining its pattern, practical requirement, and failure mode. The tool description itself provides no additional parameter semantics, so the baseline score of 3 is appropriate since the schema already carries the parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('List registered tables in a DataCanvas session') with concrete output details (schema, row count, column names). It clearly distinguishes the tool from siblings by referencing its role for socrata_dataframe_query and the spill-triggering relationship with socrata_query_dataset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly gives a condition ('Only meaningful when CANVAS_PROVIDER_TYPE=duckdb is set') and a specific trigger ('Use after socrata_query_dataset spills a large result set to canvas'). It also frames the tool as a precursor to socrata_dataframe_query, which conveys when it is appropriate, though it does not name alternative tools to avoid.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
socrata_dataframe_queryQuery DataCanvas TableARead-onlyIdempotentInspect
Run SELECT-only SQL against a DataCanvas table populated by socrata_query_dataset. Columns SODA types as number (including aggregate aliases like count(*) as n) are staged as DOUBLE, so numeric comparisons work without a cast (year > 2020, amount < 500). Text and timestamp columns stay VARCHAR — compare times with CAST(date AS TIMESTAMP). Only works when CANVAS_PROVIDER_TYPE=duckdb is set. Use socrata_dataframe_describe to see registered tables and their schemas.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | SELECT-only SQL to run against registered canvas tables. DDL, DML, and file-reading functions are rejected. Use table names from socrata_dataframe_describe. | |
| limit | No | Max rows to return (1–10000). Default 1000. | |
| canvas_id | Yes | Canvas ID returned from socrata_query_dataset or socrata_dataframe_describe. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The row limit that was applied when capped. |
| sql | No | SQL that was executed. |
| rows | No | Query result rows. DuckDB may return native JS types (number, boolean, null) for numeric/boolean columns. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows returned in this response when capped. |
| notice | No | Guidance when the SQL returned zero rows. Absent when rows are present. |
| canvas_id | No | Canvas ID queried. |
| row_count | No | Number of rows returned. |
| truncated | No | True when results were capped at the limit — more rows match the query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds valuable behavioral context: SELECT-only enforcement, rejection of DDL/DML/file-reading functions, type staging behavior (numbers as DOUBLE, text/timestamps as VARCHAR), and the need for CAST for timestamp comparisons. This goes beyond the annotations and helps the agent predict execution behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action ('Run SELECT-only SQL'), then adds the most important behavioral caveats (type staging, provider requirement) and a pointer to the sibling tool. Every sentence earns its place; no filler or repetition of schema details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and the annotations cover safety, the description is complete for an agent to select and invoke the tool correctly. It covers prerequisites, constraints, type behavior, and how to discover table names. The only minor gap is not describing the output format, but the output schema handles that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds meaning by explaining the type-staging behavior that affects how parameters like sql should be written (e.g., numeric comparisons work without cast, timestamps need CAST). It also reinforces that table names come from socrata_dataframe_describe, which is useful context beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Run SELECT-only SQL') and a specific resource ('a DataCanvas table populated by socrata_query_dataset'), and it distinguishes itself from siblings by naming socrata_dataframe_describe for schema discovery. It clearly identifies what the tool does and how it differs from related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool (after socrata_query_dataset populates a table) and when not to (only works when CANVAS_PROVIDER_TYPE=duckdb is set). It also points to socrata_dataframe_describe for registered tables and schemas, giving the agent a clear alternative and prerequisite.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
socrata_find_datasetsFind Socrata DatasetsARead-onlyIdempotentInspect
Search for datasets across all Socrata-powered government open-data portals, or scope to one portal with the domain parameter. Returns dataset IDs, names, domains, update timestamps, and column_names — the API field names SoQL takes, not display labels. Use socrata_get_dataset to fetch the typed column schema before writing queries — column_names carry no type information.
| Name | Required | Description | Default |
|---|---|---|---|
| only | No | Filter by asset type. Omit to include all types. Usually "datasets" is what you want. | |
| tags | No | Filter by tags (e.g. ["covid19", "permits"]). | |
| limit | No | Number of results to return (1–100). Default 10. | |
| order | No | Sort order. Defaults to relevance. Use updated_at to surface recently-refreshed datasets. | |
| query | No | Full-text search across dataset names and descriptions. Omit to browse without filtering. | |
| domain | No | Scope search to a single portal by bare hostname (e.g. data.seattle.gov, data.cityofnewyork.us); URL forms like https://data.seattle.gov/ are accepted and reduced to the host. Omit to search all portals. | |
| offset | No | Pagination offset. Default 0. | |
| categories | No | Filter by domain categories (e.g. ["Public Safety", "Transportation"]). |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | Recovery hint when results are empty — echoes filters and suggests how to broaden. Absent on non-empty result pages. |
| results | No | Matching datasets. Empty when no results. |
| totalCount | No | Total matches before pagination. 0 when empty. |
| effectiveQuery | No | Search query applied, for reference. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, which cover the safety profile. The description adds valuable behavior beyond annotations: returned column_names are API field names, not display labels, and they carry no type information. This prevents misuse when constructing SoQL queries.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. It front-loads the main action, then delivers the key output caveat and a pointer to the next tool, while leaving schema details to the schema itself.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a search tool with rich schema coverage and safety annotations, the description covers the essential context: what is searched, how to scope, what is returned, the important nuance about field-name semantics, and the follow-up tool to use for typed schemas. Nothing critical is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers 100% of the 8 parameters with descriptions, defaults, and enums, so the schema does the heavy lifting. The description adds marginal semantic value by reinforcing the domain scoping behavior and the meaning of column_names, but does not substantially extend parameter understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Search'), a specific resource ('datasets across all Socrata-powered government open-data portals'), and explicitly distinguishes scoped vs. global search via the domain parameter. It also differentiates itself from sibling socrata_get_dataset by noting that this tool returns search results, not typed schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when to use this tool ('Search for datasets across all... portals') and explicitly directs the agent to use socrata_get_dataset when typed column schema is needed before writing queries. It does not enumerate exclusions against every sibling tool, but the context and alternative are clear enough for correct routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
socrata_get_datasetGet Dataset SchemaARead-onlyIdempotentInspect
Fetch full metadata and column schema for a Socrata dataset by ID. Returns field names, data types, descriptions, row count, and licensing. Always call this before writing a socrata_query_dataset — the column types determine correct WHERE clause syntax: Number columns accept bare literals (year=2023) while Text columns require single-quoted strings (year='2023').
| Name | Required | Description | Default |
|---|---|---|---|
| domain | No | 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. | |
| dataset_id | Yes | Four-by-four dataset ID matching pattern like kzjm-xkqj. IDs are portal-scoped: take it from socrata_find_datasets together with that result’s domain. |
Output Schema
| Name | Required | Description |
|---|---|---|
| name | No | Dataset display name. |
| tags | No | Associated tags. |
| error | No | Present when the call failed. Absent on success. |
| domain | No | Portal domain hosting this dataset. |
| columns | No | Column schema. Computed region columns (:@computed_region_*) are excluded to reduce noise. |
| license | No | License name when available. |
| category | No | Domain category when available. |
| row_count | No | Approximate row count when available. See row_count_source for provenance. |
| dataset_id | No | Four-by-four dataset ID. |
| description | No | Dataset description when available. |
| data_updated_at | No | ISO 8601 timestamp of last data update when available. |
| row_count_source | No | How row_count was obtained: 'top_level_cached_contents' — reported directly by the portal's views metadata; 'column_cached_contents' — derived as the maximum per-column cached count when the top-level value is absent. Absent when row_count is absent. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the description only needs to add context. It adds the return contents (field names, data types, descriptions, row count, licensing) and explains how the fetched column types inform downstream query syntax. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first front-loads the operation and return list, the second delivers high-value usage guidance. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with fully documented parameters, an output schema, and read-only/idempotent annotations, the description covers what the tool returns, when to call it, and why. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with detailed descriptions for both domain and dataset_id. The description adds little parameter-specific meaning beyond the schema, so it meets the baseline without going further.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Fetch') and resource ('full metadata and column schema for a Socrata dataset by ID') and enumerates what it returns. It also differentiates itself from socrata_query_dataset by explicitly framing itself as the prerequisite for correct query construction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit workflow guidance: 'Always call this before writing a socrata_query_dataset' and explains why column types affect WHERE clause syntax. It does not, however, mention other sibling tools such as socrata_dataframe_describe or conditions where this tool should not be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
socrata_list_portalsList Socrata PortalsARead-onlyIdempotentInspect
List known Socrata-powered government open-data portals with their domain, organization name, and approximate dataset count. The catalog is a curated list of 39 well-known portals; dataset counts are fetched from the Discovery API and cached for ~24 hours. Filtering is client-side substring match on the query parameter. Use this first when you do not know which portal to target, then pass the domain to socrata_find_datasets.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max portals to return (1–200). Default 50. | |
| query | No | Keyword to filter portal names or organization names (case-insensitive substring match). Omit to list all portals. | |
| offset | No | Pagination offset. Default 0. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | Recovery hint when no portals matched the filter. Absent on non-empty pages. |
| portals | No | Matching portals. Empty when no results. |
| totalCount | No | Total portals before pagination. 0 when empty. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only and idempotent behavior, and the description adds valuable context beyond that: the catalog is curated to 39 portals, dataset counts are approximate and cached for ~24 hours, and filtering is client-side. These details help the agent anticipate staleness and performance characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: what the tool returns, behavioral caveats (curated list, caching), and usage routing. Key information is front-loaded in the first sentence, and no redundant or speculative content is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, has no required parameters, has a complete schema, an output schema, and safety annotations. The description fully covers what an agent needs to know to call it correctly, including data freshness and how to proceed afterward.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover 100% of parameters, including limit bounds, query substring behavior, and offset pagination, so the schema carries the semantic load. The description adds only a minor implementation detail ('client-side substring match'), which does not meaningfully exceed the baseline for fully documented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('List known Socrata-powered government open-data portals') and specifies the returned fields: domain, organization name, and approximate dataset count. It also distinguishes itself from siblings by framing this as the entry-point tool before calling socrata_find_datasets.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance: use this tool first when the target portal is unknown, then pass the chosen domain to socrata_find_datasets. This clear when-to-use directive and sibling routing leaves no ambiguity about the tool's place in the workflow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
socrata_query_datasetQuery DatasetARead-onlyIdempotentInspect
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 CANVAS_PROVIDER_TYPE=duckdb and rows fill limit, 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.
| Name | Required | Description | Default |
|---|---|---|---|
| group | No | SoQL GROUP BY clause over API field names (field_name from socrata_get_dataset). Requires an aggregate function in select. | |
| limit | No | 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. | |
| order | No | SoQL ORDER BY clause over API field names or select aliases, e.g. "total_deaths DESC" or "date ASC". | |
| where | No | 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. | |
| domain | No | 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. | |
| having | No | SoQL HAVING clause. Filters on aggregated results, e.g. count > 100. | |
| offset | No | Row offset for pagination. Default 0. | |
| search | No | Full-text search across all text columns ($q). For field-specific filtering, use where instead. | |
| select | No | 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. | |
| canvas_id | No | 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. | |
| dataset_id | Yes | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The row limit that was applied when capped. |
| rows | No | Result rows. Scalar values are strings (SODA 2.1); geo/location columns return nested objects. Use column schema from socrata_get_dataset for type context. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows returned in this response when capped. |
| domain | No | Portal hostname queried, normalized from the domain input. |
| notice | No | 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. |
| canvas_id | No | 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. |
| row_count | No | Rows returned in this response. |
| truncated | No | 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. |
| dataset_id | No | Dataset ID queried. |
| table_name | No | 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. |
| total_count | No | 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. |
| assembled_query | No | SoQL clauses assembled for this request — useful for learning the syntax. |
| canvas_row_count | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and idempotent annotations, the description discloses notable behaviors: rows are returned along with the assembled SoQL string, API field names are required rather than display labels, all SODA 2.1 row values are strings even for numeric columns, and large result sets spill to DataCanvas under certain conditions. This gives the agent important operational knowledge annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence carries operational value and the main purpose is front-loaded. The details about field naming, string coercion, distinct-value enumeration, and spill behavior are dense but not redundant, and no filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with an output schema and readOnly annotations, the description covers the critical ambiguities: domain scoping, API field name usage, quoting by data type, pagination, and post-spill analysis. The presence of an output schema means return-value details do not need to be repeated, and the description is complete enough for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds substantial meaning beyond the schema: it explains the distinction between search and where, provides concrete quoting rules based on data_type, gives select alias examples, specifies a distinct-value pattern, and clarifies how limit interacts with DataCanvas spill behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Execute a SoQL query against any dataset on any Socrata portal.' It also distinguishes the querying role by contrasting quick full-text search with structured select/where/group/having/order control, making it clearly distinct from sibling tools like socrata_get_dataset and socrata_dataframe_query.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: use search for quick lookup, use structured clauses for analytical control, use where for field-specific filtering, and use a specific pattern for distinct values. It also directs spill-over analysis to socrata_dataframe_describe and socrata_dataframe_query. However, it does not explicitly state when this tool should not be used in favor of metadata-oriented siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
- Changed
socrata_dataframe_describe2 fields changed- changed
Output schema / properties / tables / items / properties / columns / descriptionPrevious value: -"Column names and DuckDB types. Numeric SODA columns become queryable with numeric comparisons after spillover."New value: +"Column names and DuckDB types. SODA number columns are staged as DOUBLE, so numeric comparisons (year > 2020) need no cast; compare timestamps with CAST(col AS TIMESTAMP)." - changed
Output schema / properties / tables / items / properties / columns / items / properties / type / descriptionPrevious value: -"DuckDB inferred type (e.g. VARCHAR, DOUBLE, BIGINT)."New value: +"DuckDB column type (e.g. VARCHAR, DOUBLE, BOOLEAN, JSON). SODA number columns are DOUBLE; text and timestamp columns are VARCHAR."
- Changed
socrata_query_dataset5 fields changed- changed
Input schema / properties / limit / descriptionPrevious 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." - changed
Output schema / properties / canvas_id / descriptionPrevious 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." - changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / table_nameAdded 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" +} - changed
Output schema / properties / truncated / descriptionPrevious 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."
4 tool updates
- Changed
socrata_find_datasets4 fields changed- changed
Input schema / properties / domain / descriptionPrevious value: -"Scope search to a single portal (e.g. data.seattle.gov, data.cityofnewyork.us). Omit to search all portals."New value: +"Scope search to a single portal by bare hostname (e.g. data.seattle.gov, data.cityofnewyork.us); URL forms like https://data.seattle.gov/ are accepted and reduced to the host. Omit to search all portals." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `rate_limited`: Discovery API returned 429. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `rate_limited`: Discovery API returned 429. `unknown_domain`: The Discovery catalog does not index the domain (\"Domain not found\"). `invalid_domain`: The domain is not a hostname, even after dropping a URL scheme, path, or query. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "rate_limited" -]New value: +[ + "rate_limited", + "unknown_domain", + "invalid_domain" +] - changed
Output schema / properties / results / items / properties / column_names / descriptionPrevious value: -"Preview column name list (no type info). Call socrata_get_dataset for typed schema."New value: +"API field names — the identifiers SoQL takes in select/where/group/order (e.g. cuisine_description), not display labels. Computed-region system columns are dropped; empty when the catalog lists no field names. No type info — call socrata_get_dataset for the typed schema."
- Changed
socrata_get_dataset4 fields changed- changed
Input schema / properties / dataset_id / descriptionPrevious value: -"Four-by-four dataset ID matching pattern like kzjm-xkqj. Obtain from socrata_find_datasets."New value: +"Four-by-four dataset ID matching pattern like kzjm-xkqj. IDs are portal-scoped: take it from socrata_find_datasets together with that result’s domain." - changed
Input schema / properties / domain / descriptionPrevious value: -"Portal domain (e.g. data.seattle.gov). Defaults to SOCRATA_DEFAULT_DOMAIN env var 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." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `invalid_id`: Dataset ID does not match the four-by-four pattern. `not_found`: Valid ID format but dataset does not exist on this domain. 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`: Valid ID format but 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. `rate_limited`: SODA endpoint returned 429. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "invalid_id", - "not_found" -]New value: +[ + "invalid_id", + "not_found", + "unknown_domain", + "invalid_domain", + "rate_limited" +]
- Changed
socrata_list_portals2 fields changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `rate_limited`: Discovery API returned 429. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode." - removed
Output schema / properties / error / properties / data / properties / reason / examplesRemoved value: -[ - "rate_limited" -]
- Changed
socrata_query_dataset9 fields changed- changed
Input schema / properties / dataset_id / descriptionPrevious 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." - changed
Input schema / properties / domain / descriptionPrevious 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." - changed
Input schema / properties / group / descriptionPrevious 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." - changed
Input schema / properties / order / descriptionPrevious 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\"." - changed
Input schema / properties / select / descriptionPrevious 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." - changed
Input schema / properties / where / descriptionPrevious 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." - changed
Output schema / properties / domain / descriptionPrevious value: -"Portal domain queried."New value: +"Portal hostname queried, normalized from the domain input." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "invalid_id", - "not_found", - "soql_error", - "rate_limited" -]New value: +[ + "invalid_id", + "not_found", + "unknown_domain", + "invalid_domain", + "soql_error", + "rate_limited" +]
4 tool updates
- Changed
socrata_dataframe_describe2 fields changed- added
Input schema / properties / canvas_id / patternAdded value: +"^[A-Za-z0-9_-]{10}$" - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `canvas_id_required`: Canvas is enabled but canvas_id was omitted or blank. `canvas_not_found`: Provided canvas_id does not match any registered canvas. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `canvas_id_required`: Canvas is enabled but canvas_id was omitted. `canvas_not_found`: Provided canvas_id does not match any registered canvas. Other values are possible when a failure originates below the handler."
- Changed
socrata_dataframe_query1 field changed- added
Input schema / properties / canvas_id / patternAdded value: +"^[A-Za-z0-9_-]{10}$"
- Changed
socrata_list_portals2 fields changed- removed
Output schema / properties / portals / items / properties / dataset_count / anyOfRemoved value: -[ - { - "type": "number" - }, - { - "type": "null" - } -] - added
Output schema / properties / portals / items / properties / dataset_count / typeAdded value: +[ + "number", + "null" +]
- Changed
socrata_query_dataset2 fields changed- changed
Input schema / properties / canvas_id / descriptionPrevious 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." - added
Input schema / properties / canvas_id / patternAdded value: +"^[A-Za-z0-9_-]{10}$"
6 tool updates
- Changed
socrata_dataframe_describe6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "tables" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `canvas_id_required`: Canvas is enabled but canvas_id was omitted or blank. `canvas_not_found`: Provided canvas_id does not match any registered canvas. Other values are possible when a failure originates below the handler.", + "examples": [ + "canvas_id_required", + "canvas_not_found" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "tables" -]
- Changed
socrata_dataframe_query6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "rows", + "row_count", + "sql", + "canvas_id" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `canvas_disabled`: CANVAS_PROVIDER_TYPE is not set to duckdb — DataCanvas is unavailable. `canvas_not_found`: canvas_id does not match any registered canvas. `table_not_found`: The SQL referenced a canvas table that does not exist — expired, dropped, or a mistyped name. `sql_rejected`: SQL was not a SELECT statement, referenced a system catalog, or contained disallowed functions. Other values are possible when a failure originates below the handler.", + "examples": [ + "canvas_disabled", + "canvas_not_found", + "table_not_found", + "sql_rejected" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "rows", - "row_count", - "sql", - "canvas_id" -]
- Changed
socrata_find_datasets6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `rate_limited`: Discovery API returned 429. Other values are possible when a failure originates below the handler.", + "examples": [ + "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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "totalCount" -]
- Changed
socrata_get_dataset6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "dataset_id", + "domain", + "name", + "tags", + "columns" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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`: Valid ID format but dataset does not exist on this domain. Other values are possible when a failure originates below the handler.", + "examples": [ + "invalid_id", + "not_found" + ], + "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" +} - removed
Output schema / requiredRemoved value: -[ - "dataset_id", - "domain", - "name", - "tags", - "columns" -]
- Changed
socrata_list_portals6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "portals", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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: `rate_limited`: Discovery API returned 429. Other values are possible when a failure originates below the handler.", + "examples": [ + "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" +} - removed
Output schema / requiredRemoved value: -[ - "portals", - "totalCount" -]
- Changed
socrata_query_dataset6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "rows", + "row_count", + "assembled_query", + "domain", + "dataset_id" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "rows", - "row_count", - "assembled_query", - "domain", - "dataset_id" -]
1 tool update
- Changed
socrata_query_dataset2 fields changed- changed
Output schema / properties / canvas_id / descriptionPrevious 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." - added
Output schema / properties / canvas_row_countAdded 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" +}
2 tool updates
- Changed
socrata_get_dataset2 fields changed- changed
Output schema / properties / row_count / descriptionPrevious value: -"Approximate row count when available."New value: +"Approximate row count when available. See row_count_source for provenance." - added
Output schema / properties / row_count_sourceAdded value: +{ + "description": "How row_count was obtained: 'top_level_cached_contents' — reported directly by the portal's views metadata; 'column_cached_contents' — derived as the maximum per-column cached count when the top-level value is absent. Absent when row_count is absent.", + "enum": [ + "top_level_cached_contents", + "column_cached_contents" + ], + "type": "string" +}
- Changed
socrata_list_portals3 fields changed- added
Output schema / properties / portals / items / properties / dataset_count / anyOfAdded value: +[ + { + "type": "number" + }, + { + "type": "null" + } +] - changed
Output schema / properties / portals / items / properties / dataset_count / descriptionPrevious value: -"Number of datasets on this portal."New value: +"Approximate count of dataset-type assets on this portal from the Discovery API catalog (point-in-time, refreshed ~daily). 0 means the portal exposes no dataset assets to the catalog; null means the live count is temporarily unavailable." - removed
Output schema / properties / portals / items / properties / dataset_count / typeRemoved value: -"number"
2 tool updates
- Changed
socrata_dataframe_describe1 field changed- changed
Input schema / properties / canvas_id / descriptionPrevious value: -"Canvas ID returned from socrata_query_dataset. Omit to list all tables visible in the current session."New value: +"Canvas ID returned by socrata_query_dataset when a large result spills to canvas. Required in practice when canvas is enabled — canvases cannot be enumerated, so omitting it fails with canvas_id_required instead of listing tables."
- Changed
socrata_query_dataset2 fields changed- changed
Output schema / properties / total_count / descriptionPrevious 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." - changed
Output schema / properties / truncated / descriptionPrevious 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."
2 tool updates
- Changed
socrata_dataframe_query3 fields changed- added
Output schema / properties / capAdded value: +{ + "description": "The row limit that was applied when capped.", + "type": "number" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Rows returned in this response when capped.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when results were capped at the limit — more rows match the query.", + "type": "boolean" +}
- Changed
socrata_query_dataset3 fields changed- added
Output schema / properties / capAdded value: +{ + "description": "The row limit that was applied when capped.", + "type": "number" +} - added
Output schema / properties / shownAdded value: +{ + "description": "Rows returned in this response when capped.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when rows filled the limit — more rows match (see total_count). Spills to canvas when enabled.", + "type": "boolean" +}
5 tool updates
- Changed
socrata_dataframe_describe2 fields changed- removed
Output schema / properties / messageRemoved value: -{ - "description": "Status message when canvas is not enabled or no tables are registered. Absent when tables are present.", - "type": "string" -} - added
Output schema / properties / noticeAdded value: +{ + "description": "Status message when canvas is not enabled or no tables are registered. Absent when tables are present.", + "type": "string" +}
- Changed
socrata_dataframe_query1 field changed- added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when the SQL returned zero rows. Absent when rows are present.", + "type": "string" +}
- Changed
socrata_find_datasets7 fields changed- added
Output schema / properties / effectiveQueryAdded value: +{ + "description": "Search query applied, for reference.", + "type": "string" +} - removed
Output schema / properties / messageRemoved value: -{ - "description": "Recovery hint when results are empty — echoes filters and suggests how to broaden. Absent on non-empty result pages.", - "type": "string" -} - added
Output schema / properties / noticeAdded value: +{ + "description": "Recovery hint when results are empty — echoes filters and suggests how to broaden. Absent on non-empty result pages.", + "type": "string" +} - removed
Output schema / properties / queryRemoved value: -{ - "description": "Search query applied, for reference.", - "type": "string" -} - added
Output schema / properties / totalCountAdded value: +{ + "description": "Total matches before pagination. 0 when empty.", + "type": "number" +} - removed
Output schema / properties / total_countRemoved value: -{ - "description": "Total matches before pagination. 0 when empty.", - "type": "number" -} - changed
Output schema / requiredPrevious value: -[ - "results", - "total_count" -]New value: +[ + "results", + "totalCount" +]
- Changed
socrata_list_portals5 fields changed- removed
Output schema / properties / messageRemoved value: -{ - "description": "Recovery hint when no portals matched the filter. Absent on non-empty pages.", - "type": "string" -} - added
Output schema / properties / noticeAdded value: +{ + "description": "Recovery hint when no portals matched the filter. Absent on non-empty pages.", + "type": "string" +} - added
Output schema / properties / totalCountAdded value: +{ + "description": "Total portals before pagination. 0 when empty.", + "type": "number" +} - removed
Output schema / properties / total_countRemoved value: -{ - "description": "Total portals before pagination. 0 when empty.", - "type": "number" -} - changed
Output schema / requiredPrevious value: -[ - "portals", - "total_count" -]New value: +[ + "portals", + "totalCount" +]
- Changed
socrata_query_dataset1 field changed- added
Output schema / properties / noticeAdded value: +{ + "description": "Guidance when the query returned zero rows — suggests narrowing or reviewing the SoQL. Absent on non-empty result sets.", + "type": "string" +}
6 tool updates
- First observed
socrata_dataframe_describe - First observed
socrata_dataframe_query - First observed
socrata_find_datasets - First observed
socrata_get_dataset - First observed
socrata_list_portals - First observed
socrata_query_dataset
Related MCP Connectors
Query and explore Nova Scotia open datasets via the Socrata SODA API.
ArcGIS Hub — open government geospatial data (search + Feature Service query).
Data.gov MCP — wraps Data.gov CKAN API (catalog.data.gov/api/3)
DataSeattle MCP — Seattle open data (data.seattle.gov, Socrata SODA API).
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables querying and searching the Providence Open Data catalog via Socrata SoQL, including dataset search, data querying, and metadata retrieval.3 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables querying Seattle open data from data.seattle.gov via the Socrata SODA API.152 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables searching, querying, and retrieving metadata from Sonoma County Open Data datasets via Socrata SoQL or natural language.159 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables searching and querying Norfolk Open Data datasets through Socrata SoQL, including metadata retrieval.151 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.