ny-data-registry-mcp
Locates and describes ArcGIS open-data services across ArcGIS Hub, ArcGIS Enterprise, ArcGIS Online organizations, and ArcGIS Server endpoints, including harvested dataset metadata, columns, formats, and query handoff details for ArcGIS services.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ny-data-registry-mcpWhich NY open data portals cover Albany County?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ny-data-registry-mcp
An MCP (Model Context Protocol) server that finds open data across every New York data portal in BetaNYC's NY data portal registry: which portal covers a place or topic, how to query it, and, with the harvested index, which datasets and columns exist and in what formats.
It complements the socrata MCP rather than replacing it. This server knows where data is (140 sources across state, county, city, agency, library and nonprofit portals) and hands the agent the right Socrata domain or ArcGIS service. Querying the data stays with socrata and the other BetaNYC MCPs.
Built by BetaNYC. Status: 0.1.0. Package: @betanyc/ny-data-registry-mcp.
What it does
Nine tools, in two groups.
Registry tools (work out of the box, no index needed):
Tool | What it answers |
| Which portals cover this topic or place? Filters: place, tier, platform family, has API, key required, status (default |
| Everything for one county, city, NYC borough or region. Says whether the place has a portal, was checked and has none, or is not in the registry (unchecked, not absent) |
| Endpoint (verbatim from the registry, never guessed), API type, key and env var, example request, and which MCP to hand off to. Flags UNCONFIRMED, undocumented, gated, dead and no-portal rows |
| One live request to a portal URL: status, redirect, response time, and whether that matches the registry |
| Row counts, registry date and origin, unmapped platform strings, index size and last harvest |
Index tools (need the harvested SQLite index):
Tool | What it answers |
| Dataset titles, descriptions, tags and column names across Socrata and ArcGIS portals. Filters: place, portal, platform family, format (csv, geojson, shapefile, kml, api, xlsx …), updated since |
| Fields and types, every distribution (format + URL), license, publisher, extent, and per-field provenance |
| Datasets sharing a join key (BBL, BIN, borough, community district, council district, census tract, SWIS, FIPS, ZIP), from a curated key-column map, not raw name equality |
| Datasets added, changed or removed since a date |
All tool inputs are strict: an unknown parameter is rejected by name, never silently dropped (same rule as nyc-311-mcp).
Related MCP server: Akil MCP
Questions to try
Ask your AI assistant these once the server is connected. Where we ran a question on 2026-11-05, what it found is noted. Portals change, so your results may differ.
Which datasets match my words? (search_datasets)
"Which New York cities publish housing code violation data? Search for 'housing code violations' and 'code enforcement', and list the results by city." Finds New York City (HPD violations, NYCHA violations, tenant complaints, DOB violations), Buffalo (code violations) and Syracuse (code violations, unfit properties, rental registry).
"Do any New York cities publish zoning data? If so, what formats do they publish them in?" Finds New York City, Buffalo, Rochester, Glens Falls and Cortland, plus zoning layers on the Westchester, Albany, Dutchess, Tioga, Wayne, Oswego and Warren county portals.
"Find flood zones, as GeoJSON." Finds the statewide FEMA flood hazard layer, plus Buffalo and Cortland County.
"Find restaurant inspection data." Top hit: NYC's DOHMH restaurant inspection results.
"Where are the farmers markets?" Finds the statewide list on data.ny.gov and Albany County's.
"Find EV charging stations, as a CSV file." Finds two NYC charging datasets and the statewide alternative fuel stations list.
"Housing code violations in Syracuse." / "Bike lanes in Buffalo." / "Street trees in Buffalo." Narrow a search to one place.
"Where are the polling places?" Finds Suffolk and Tompkins counties.
"Crash data updated since 2026-10-01." Use a date to see only datasets that changed recently.
Who has data, and for where? (find_sources, list_sources_for_place)
"Which New York portals have health data?"
"Which state agencies have a real API?" / "Which portals need an API key?"
"What open data does Erie County have?" Erie County was checked and has no portal; the answer says so.
"What can I get for Syracuse?" / "What covers Queens, or the North Country?"
How do I use it? (how_to_query, get_dataset_columns, find_joinable)
"How do I pull data from the NYS Department of Health portal?"
"Does Westchester County publish zoning data, and what columns does it have?"
"What columns does Buffalo's code violations dataset have?"
"What other datasets can I join to NYC's housing violations by BBL?"
Is it current? (whats_new, check_source, registry_info)
"What datasets were added or changed since October 1?"
"Is Albany's data portal still working?"
"How many sources do you track, and when was the list last updated?"
Tips
Try more than one wording. Cities name the same thing differently: "code enforcement" finds datasets that "housing code violations" misses.
New York City crowds the results. NYC's matches tend to fill the top of the list. To see the rest of the state, name a place or ask a second time for results outside New York City.
Add a date to skip old data. "School enrollment" alone returns NYC tables from 2010–2011; add a date, such as "updated since 2025-01-01", to skip them.
An empty result can still have data elsewhere. The index covers Socrata and ArcGIS portals only. A city may publish on a site this server does not search.
Some maps are not official. The Westchester and Tioga county zoning layers say they are not the legal boundaries. Check the town's own map before relying on one.
It finds the data; another tool fetches it. Hand a Socrata dataset to the
socrataMCP. For an ArcGIS layer, open or download it from the portal.
Install
Requires Node 22.16 or later (it uses Node's built-in node:sqlite, so there is nothing native to compile; 22.16 is the first official Node whose SQLite includes FTS5 full-text search).
Add it to your MCP client's config (Claude Desktop, Claude Code, Cursor, VS Code and others use this shape):
"ny-data-registry-mcp": {
"command": "npx",
"args": ["-y", "@betanyc/ny-data-registry-mcp"]
}That's all. The first time it starts, it downloads the dataset index by itself (about 19 MB, unzipped to about 110 MB). This takes a few seconds on a normal connection. The five registry tools work right away. If you ask a dataset question while the download is still running, the tool waits up to 45 seconds and then says "try again in a minute".
From source instead:
git clone https://github.com/BetaNYC/ny-data-registry-mcp && cd ny-data-registry-mcp
npm install # also builds
npm test # offline; no networkand point your client at node /path/to/ny-data-registry-mcp/dist/index.js.
The dataset index
The four index tools (search_datasets, get_dataset_columns, find_joinable, whats_new) read a prebuilt SQLite index. It holds metadata only: titles, descriptions, column names and types, formats and links. No dataset contents.
Where it comes from: the
index-latestrelease, at a fixed URL:https://github.com/BetaNYC/ny-data-registry-mcp/releases/download/index-latest/ny-data-index.sqlite.gz. Dated snapshots are kept asindex-YYYY-MM-DDreleases.Checked before use: the server checks both SHA-256 sums in the release's
SHA256SUMSfile (the.gzand the unzipped.sqlite) and the schema version. A file that fails any check is never installed.Where it goes:
${HOME}/.cache/betanyc/ny-data-registry/ny-data-index.sqlite(change withNY_DATA_INDEX).When: only when the file is missing. An existing index is never replaced on its own.
Get or refresh it by hand:
npx -y -p @betanyc/ny-data-registry-mcp ny-data-registry download # if missing npx -y -p @betanyc/ny-data-registry-mcp ny-data-registry download --force # replace with the newestTurn the download off: set
NY_DATA_INDEX_AUTO_DOWNLOAD=0. Then the dataset tools reply with these steps instead. Or build your own index withny-data-registry harvest(see "Refresh").
Environment variables (all optional)
Variable | Default | Purpose |
|
| Where the index lives |
| on |
|
| the | Download the index from somewhere else (it must have a |
|
| Registry refresh cache and HTTP cache |
| on |
|
| off |
|
| 250 | Per-portal cap on ArcGIS field requests per harvest |
| 1000 | Minimum gap between requests to one host (cannot be set below 1000) |
| none | Sent as |
Data sources
The registry.
BetaNYC/grounding-ai-with-ny-open-dataresources/ny-data-portal-registry.json(140 rows). A copy is bundled indata/. On startup the server makes a conditional request (ETag) for the published copy on GitHub Pages, caches it under${HOME}/.cache/betanyc/, and falls back to the bundled copy on any failure. This server never edits the registry.Human-editable tables in
data/:platform-families.json: maps each of the registry's 101 free-textplatformstrings to one family (socrata,arcgis-hub,arcgis-enterprise,arcgis-server,ckan,geoblacklight,custom-api,none). A string not in the table is reported as unmapped, never guessed; 7 strings are deliberatelynullbecause the registry marks them UNCONFIRMED.ny-places.json: 62 counties, 62 cities, 5 boroughs, 8 regions.key-columns.json: the curated join keys.handoffs.json: which BetaNYC MCP serves which registry row.harvest-config.json: skips (ANHD, Rockland, Columbia GeoBlacklight) and caps.synonyms.json: a short civic synonym list ("property" → parcels, tax lots, BBL).
The harvested index, built from the portals themselves (next section).
The harvest
node dist/cli.js harvest reads every live registry row and harvests the ones a documented catalog API covers:
Platform | Adapter | Columns from |
Socrata | Discovery API ( | the search response itself |
ArcGIS Hub | OGC API - Records ( |
|
ArcGIS Enterprise |
| same second hop |
ArcGIS Online org (agency REST directories such as DEC, Parks, DCP) |
| same second hop |
Everything else (custom APIs, CKAN, GeoBlacklight, standalone ArcGIS Server directories, pages with no API) is described by the registry tools but not harvested in this version.
Guards
Esri's own content is excluded (owner
esri…, orgP3ePLMYs2RVChkJx). For Enterprise portals and ArcGIS Online orgs, items from another org are not counted under that portal; this is what turns Monroe's 108 search hits into its own content. Hub sites are not filtered by org, because a Hub's catalog is curated by its owner and aggregators like the State GIS Clearinghouse deliberately list other agencies' layers.Out-of-state guard: an item whose extent lies wholly outside New York is dropped; a portal whose items are mostly outside New York is refused and purged. Placeholder extents (
[0,0,0,0]) and projected coordinates (State Plane) count as unknown, never as outside.Stable paging: Hub pages are requested sorted by
id. A listing that comes back with fewer unique items than the portal's own total is treated as incomplete, so nothing is marked removed from a shaky listing.Politeness: one descriptive User-Agent with no email address; at least 1 s between requests to a host; robots.txt Disallow and Crawl-delay honored (every Hub site asks for 60 s, so Hub listing is slow on purpose); conditional requests by ETag; one bounded retry on 429; a per-portal cap on layer requests. A bot block is reported, never worked around.
Never called: rows needing a key, ANHD, Rockland County, undocumented endpoints.
The index stores metadata only (titles, descriptions, field names, links). It never downloads data.
Incremental: datasets carry first_seen, last_seen and a content hash. A layer whose modified date has not changed keeps its stored columns and is not re-requested. A dataset is marked removed only after a complete harvest of its portal.
Refresh
Registry: picked up on next server start (conditional GET of the Pages copy).
Index: re-run
node dist/cli.js harvest..github/workflows/harvest.ymlis written to do this nightly in GitHub Actions and publish the SQLite file as a release asset, but it is not enabled (schedule commented out). Index releases are published by hand for now; the first isindex-2026-11-05.
How it was checked
npm test: offline tests from recorded fixtures (test/fixtures/, each says which request produced it), including a stdio smoke test that starts the server and calls all nine tools.node dist/cli.js eval: a fixed set of real questions (eval/questions.json) scored against the real index. Results:eval/runs/.
Latest results (2026-11-05, office-mac), all in eval/runs/:
npm test: 44 / 44 pass.Question set: 27 / 27 in the top 3, 0 invariant violations. The set was written by the same agent that built the tool, so treat 100% as an upper bound; two checks (Q01, Q13) were tightened during the build when a loose check passed on the wrong county's parcels.
Index: 9,569 datasets, 185,352 columns (5,729 with a join key) from 35 of 36 harvestable portals; 110 MB SQLite (about 18 MB gzipped). Full harvest: 924 s and 3,694 requests; an ArcGIS-only re-run: 878 s and 1,403 requests (unchanged layers are not re-requested).
311 (
erm2-nwe9) joins: BBL 426, borough 1,073, community district 510, council district 426 datasets (Scout, name equality only: 331 / 512 / 286).
Limits
Coverage is the registry's. A place not in the registry has not been checked; the tools say so.
Not harvested yet: standalone ArcGIS Server REST directories (NYS DOT, ITS, many counties), GeoBlacklight (Cornell), CKAN (catalog.data.gov), custom APIs.
Row counts are not collected (Socrata Discovery does not return them; ArcGIS would need one more request per layer).
downloadsandupdate_frequencyexist only for Socrata.Columns for ArcGIS are capped at 250 layer requests per portal per run; the rest show
columns_status: not-fetchedand fill in on later runs.Search is keyword search (SQLite FTS5 with a small synonym list), not semantic search.
Join keys are by column name only; values are not compared.
Orange County's portal is unreachable from Node because its server does not send its intermediate TLS certificate. Certificate checks are not disabled.
Syracuse's Hub returned 126 unique items of 136 on one run even with sorted paging; the guard kept the index whole, but a short listing can still miss new items until the next run.
The index is about 110 MB uncompressed, larger than the scoping estimate (low tens of MB), mostly Socrata column metadata and the full-text index.
Terms of use
Read before any adapter was written; details and quotes in docs/terms.md.
Socrata / Tyler: the Discovery API's stated purpose is "automated searching, research, and exploration"; read-only access needs no authentication; an app token is recommended. Per-portal terms pages were not found (not verified).
Esri: ArcGIS Online public content is for personal or noncommercial use under each item's own terms, and owners who share publicly grant end users permission to use and reproduce it. The Master Agreement's "may not scrape, download, or store Data" clause defines Data as Esri's own commercial datasets, which are excluded here. Hub robots.txt asks for a 60 s crawl delay, which is honored.
Related
Scout field mapping:
docs/scout-mapping.mdProposed upstream registry change (
platform_family):docs/upstream/
License
MIT
Available Tools
9 toolscheck_sourceA
Live check of one source's portal URL: one polite request, redirects reported (not followed), HTTP status, response time, and whether that matches the registry's status. Never calls key-required or account-gated sources, and reports a bot block rather than working around it.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | A portal URL; matched to its registry row by host | |
| source_id | No | ||
| registry_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: one polite request, redirects reported rather than followed, bot blocks surfaced rather than circumvented, and a hard limit on which sources it will touch. These are exactly the side-effect and policy details an agent needs before invoking.
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, front-loaded with the core action and then the behavioral constraints, with no filler. Every clause conveys either an output or a limit.
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?
Covers the return values (status, timing, redirects, registry agreement) and the safety posture well, which is what matters for a read-only check with no output schema. The only real gap is the identifier semantics for the three-parameter input.
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?
Only the url parameter is documented in the schema (33% coverage), and the description says nothing about source_id or registry_id. With three optional identifiers and zero required parameters, the agent is left guessing whether url, source_id, or registry_id alone suffices or whether they must be combined.
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 and scope ('Live check of one source's portal URL') plus the exact outputs it produces (redirects, HTTP status, response time, registry match). The word 'live' separates it from the static discovery siblings like find_sources and registry_info without needing to name them.
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 'live check' framing implies the use case (verify a portal is reachable and consistent with the registry), and it gives a concrete exclusion: it never calls key-required or account-gated sources. It stops short of explicitly routing the agent away from siblings such as registry_info for stored status.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_joinableA
Datasets that share a join key with this one, grouped by key: BBL, BIN, borough, community district, council district, census tract, SWIS, FIPS, ZIP. Uses a curated key-column map, not raw column-name equality.
| Name | Required | Description | Default |
|---|---|---|---|
| column | No | Limit to one key (a field name in the dataset, or a key label like 'BBL') | |
| dataset | Yes | dataset_id, Socrata 4x4, ArcGIS item id or URL | |
| limit_per_key | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosure. It does disclose a genuinely important behavioral trait: matching uses a curated key-column map rather than raw column-name equality, so results reflect a normalization layer. However, it never states that this is a read-only operation, says nothing about how large or expensive the scan is, and does not describe error behavior when the dataset_id is invalid.
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, zero filler. The primary purpose comes first, and the list of keys and the curated-map caveat follow as supporting detail. Nothing could be removed without losing information.
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 three-parameter read tool with no annotations and no output schema, the description covers the core semantics and the key taxonomy. What is missing is a sense of what a result entry looks like beyond 'grouped by key' and whether limit_per_key applies per group. That roughly matches the expected baseline, but it is not complete for a dataset-discovery tool.
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 67%; the dataset and column parameters are documented in the schema. The description adds real meaning by enumerating the recognized key labels (BBL, BIN, borough, census tract, FIPS, ZIP, and so on), which clarifies what 'column' will accept. It says nothing about limit_per_key (which the schema also leaves undocumented) or about how a field name differs from a key label in practice.
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-plus-resource construction: it returns datasets that share a join key with a given dataset, and it explicitly says the results are grouped by key. That is far more precise than its name 'find_joinable' alone. It does not name a sibling such as search_datasets or find_sources to contrast with, but the purpose is unmistakable.
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 phrase 'share a join key with this one' implies the use case, which is finding datasets you can join against the supplied dataset. The description gives no explicit when-to-use or when-not guidance, and it does not say to call it instead of, or after, get_dataset_columns or search_datasets. The descriptors in the input schema (dataset_id, Socrata 4x4, ArcGIS item id or URL) support the guidance that already exists implicitly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_sourcesA
Find New York open data portals and sources (state, county, city, agency, library, nonprofit) in BetaNYC's registry by topic, name or place. Returns each source's portal URL, platform family, API type, dataset count, status and last-verified date. Searches portal names and notes, not dataset titles (use search_datasets for datasets). Default status filter is 'live'.
| Name | Required | Description | Default |
|---|---|---|---|
| tier | No | 1 statewide portals, 2 state agencies/authorities, 3 local government, 4 nonprofit/academic | |
| limit | No | Default 10 | |
| place | No | County, city, NYC borough or region, e.g. 'Erie County', 'Buffalo', 'Brooklyn', 'Capital Region' | |
| query | Yes | Free text, e.g. 'health', 'parcels', 'Erie County', 'transit' | |
| status | No | Default 'live'. Use 'any' to include no-portal, dead and UNCONFIRMED rows | |
| has_api | No | Only sources with (true) or without (false) a queryable API | |
| key_required | No | ||
| platform_family | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does a fair job: it lists the return shape (portal URL, platform family, API type, dataset count, status, last-verified date) and flags the non-obvious default of status='live'. It omits authentication requirements, rate limits, pagination behavior and whether 'any' materially changes result volume, which are the remaining gaps.
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, all front-loaded: what it finds, what it returns, what it does not search, and the default filter. No redundant restatement of the tool title and no filler.
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 eight-parameter search tool with no output schema, the description supplies enough to call it correctly: return fields, search scope, the default status filter, and the sibling to use for datasets. Minor incompleteness remains on the two undocumented enum parameters and on limit/pagination semantics.
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 coverage is 75%, so the baseline is 3; the description earns a bump by clarifying the query parameter's actual search scope (portal names and notes rather than dataset titles) and reinforcing the status default. It adds nothing for key_required or platform_family, which are also undocumented in the schema, leaving those enums unexplained.
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 gives a specific verb and resource — finding New York open data portals/sources in BetaNYC's registry — and enumerates the source types covered (state, county, city, agency, library, nonprofit). It explicitly distinguishes itself from search_datasets by noting it searches portal names and notes, not dataset titles.
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?
It clearly states the intended search surface (portal names and notes) and routes the agent to search_datasets when dataset titles are wanted. It also discloses that the default status filter is 'live', which affects results. It does not address the other siblings such as list_sources_for_place, so there is no exclusion guidance for those.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_dataset_columnsB
Column names, field names, types and descriptions for one dataset from the index, plus every distribution (format + URL), license, publisher, extent and per-field provenance (from the portal vs derived here).
| Name | Required | Description | Default |
|---|---|---|---|
| dataset | Yes | dataset_id from search_datasets, a Socrata 4x4, an ArcGIS item id, or the dataset URL |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden; it does add real content by distinguishing portal-sourced provenance from locally derived provenance, which is non-obvious. However, it never states that this is a read-only lookup, how large responses can get for wide datasets, or what happens on an unresolvable identifier.
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?
It is a single sentence with no filler, but it is an unstructured run-on list chained by 'plus' and 'and', which makes the main payload (columns) hard to separate from secondary metadata at a glance.
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?
There is no output schema, so the description must describe returns, and it does so fairly thoroughly across both schema-level and distribution-level metadata plus provenance. Missing are error/failure behavior and any note on response size for wide datasets.
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% and already explains accepted identifier forms (dataset_id, Socrata 4x4, ArcGIS item id, URL). The description adds no additional meaning about the single dataset argument, so the schema does all the work.
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 resource (columns/fields for one dataset) and enumerates the payload: names, types, descriptions, distributions, license, publisher, extent, provenance. It is a noun-phrase inventory rather than a verb-first statement, and it does not name or differentiate itself from sibling tools such as search_datasets or check_source.
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?
There is no when-to-use guidance and no mention of alternatives. The only routing hint ('dataset_id from search_datasets') lives in the schema, not the description, and nothing tells the agent how this differs from check_source or find_sources.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
how_to_queryA
How to get data from one registry source: its endpoint (copied verbatim, never guessed), API type, whether a key is needed and which env var holds it, an example request, and which MCP server to hand off to (the socrata MCP with the right domain, or the matching @betanyc MCP). Flags UNCONFIRMED, undocumented, gated, dead and no-portal rows.
| Name | Required | Description | Default |
|---|---|---|---|
| entity | No | Entity name, e.g. 'NYS Department of Health' | |
| source_id | No | From find_sources / list_sources_for_place results | |
| registry_id | No | ny-gov-web-registry id (only 22 rows carry one) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses that endpoints are copied verbatim and never guessed, names the data-quality flags emitted (UNCONFIRMED, undocumented, gated, dead, no-portal), and specifies the handoff target. It stops short of stating that this is a read-only lookup or whether any auth is needed to call the tool itself.
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 return contents are front-loaded in one dense sentence and the flags are called out in a short trailing fragment. It is information-rich with little waste, though the packed clause list is close to overstuffed.
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?
There is no output schema, and the description compensates by enumerating the returned fields and the flag vocabulary, plus naming the downstream MCP server and domain handling. An agent can decide and act from this, with only auth/read-only status left unstated.
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 entity, source_id provenance, and the registry_id rarity note. The description adds no parameter-level meaning beyond that, so baseline 3 applies.
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 resource and enumerates exactly what the response contains (verbatim endpoint, API type, key requirement, example request, handoff server), which makes it distinguishable from find_sources and check_source. Slightly weaker because the name/opening frame it as 'how to query' rather than 'returns query instructions for one source'.
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?
Usage is only implied via the schema note that source_id comes 'From find_sources / list_sources_for_place results', which suggests a natural follow-up step. There is no explicit when-to-use versus check_source or registry_info, and no stated exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sources_for_placeA
Everything the registry knows for one New York place (county, one of the 62 cities, an NYC borough, or a region): its own portal(s), sources for cities inside it, regional sources, and statewide sources that cover it. Says plainly whether the place has a portal, was checked and has none ('no-portal-exists'), or is not in the registry ('not-in-registry', which means unchecked, not absent).
| Name | Required | Description | Default |
|---|---|---|---|
| place | Yes | e.g. 'Erie County', 'Syracuse', 'Queens', 'NYC', 'North Country' | |
| include_statewide | No | List the statewide sources too (default true) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose meaningful behavior: it defines the three possible outcomes (has a portal, 'no-portal-exists', 'not-in-registry') and crucially explains that 'not-in-registry' means unchecked rather than absent — a distinction an agent would otherwise misinterpret. It does not cover response shape or ordering, but the state semantics are a real addition.
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, front-loaded with the scope statement followed by the outcome semantics. Dense but every clause carries information; the parenthetical place-type list is slightly redundant with the schema examples but not wasteful.
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 has no annotations and no output schema, so the description must explain what comes back — and it does, listing the four categories of sources and the three status outcomes. Only minor gaps remain, such as output structure or whether results are grouped by category.
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 coverage is 100% and the schema examples already cover county, city, borough, and region forms, so the description's mention of those place types largely restates existing schema information. It adds only marginal meaning, such as implying that statewide sources can be excluded via the boolean parameter; baseline 3 applies.
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 resource scope ("Everything the registry knows for one New York place") and enumerates exactly what is returned: the place's own portal(s), sources for cities inside it, regional sources, and statewide sources covering it. This makes the scope distinguishable in practice from a generic search tool, though it never names the closest sibling (find_sources) to draw the contrast explicitly.
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?
Usage is implied by the framing (look up all registry knowledge for a given place), and the place-type enumeration hints at accepted inputs. However, there is no statement of when to prefer this over find_sources or check_source, and no prerequisites or exclusions are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
registry_infoA
Registry row counts by status, tier and platform family; when the registry was generated and where this copy came from (bundled or refreshed from GitHub Pages); unmapped platform strings; and the harvested index's size and last harvest date.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations and zero parameters, the read-only nature is inferable but never stated. The mention of 'bundled or refreshed from GitHub Pages' usefully signals that the local copy may be stale, yet the description doesn't say whether calling triggers a network refresh, how long that might take, or what the return shape looks like.
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?
A single sentence with no filler, and the primary content (row counts) is front-loaded. The semicolon-delimited list is dense and the ordering of secondary items is somewhat arbitrary, but nothing is redundant.
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?
There is no output schema, so the description carries the burden of explaining return values, and it does so field by field. The remaining gap is behavioral rather than definitional: the agent still doesn't know whether a refresh happens on call or what the response structure is.
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 schema has zero parameters, so there is no parameter semantics to explain; baseline 4 applies. The description correctly focuses its words on output contents instead of inventing input details.
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 enumerates concrete contents: row counts by status/tier/platform family, generation timestamp, provenance, unmapped platform strings, and harvest index size/date. That is specific enough to distinguish it from siblings like find_sources or check_source, which look up individual sources. It lacks an explicit verb ('returns'/'reports'), but the resource is unmistakable.
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?
Usage is only implied: an agent can infer this is for checking registry coverage, freshness, or provenance, but there is no explicit when-to-use statement and no named alternative. It also doesn't say whether it should be called before querying sources to validate the data is current.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_datasetsA
Search dataset titles, descriptions, tags and column names across the harvested Socrata and ArcGIS portals in New York (needs the harvested index). Filter by place, portal, platform family, download format (csv, geojson, shapefile, kml, api, xlsx) or last-updated date. Each result gives the portal, link, formats, update date, and for Socrata the domain + 4x4 to hand to the socrata MCP.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| place | No | County, city, borough or region. Statewide portals are always included | |
| query | Yes | e.g. 'rodent', 'tax parcels', 'lead service lines' | |
| format | No | csv, json, geojson, shapefile, kml, api, arcgis, xlsx, geopackage, pdf | |
| portal | No | source_id or part of a portal name | |
| updated_since | No | YYYY-MM-DD | |
| platform_family | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does reasonably well: it discloses the harvested-index dependency, enumerates what each result contains (portal, link, formats, update date), and explains the Socrata-specific domain + 4x4 handoff to another MCP. It stops short of stating result ordering, default limit, or rate/refresh characteristics of the index.
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 dense sentences, front-loaded with what is searched and then what can be filtered on, with zero filler. The prerequisite and the cross-MCP handoff are packed into the same compact text rather than padded out.
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 7-parameter read tool with no annotations and no output schema, the description covers both input intent and return shape well enough to call it correctly. Minor gaps remain around result ordering, the default page size, and what happens if the index is empty or unharvested.
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?
At 71% schema coverage the schema already documents most parameters, and the description largely mirrors them (place, portal, platform family, format, last-updated). Its format enumeration is actually narrower than the schema's list, omitting json, arcgis, geopackage and pdf, so it adds little semantic value beyond the structured fields.
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 and resource — 'Search dataset titles, descriptions, tags and column names' — and bounds the corpus to harvested Socrata and ArcGIS portals in New York. It is clearly distinguishable from siblings like get_dataset_columns or find_sources, though it never names an alternative directly.
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 parenthetical '(needs the harvested index)' is a useful prerequisite an agent must satisfy before calling, and the filter list implies the intended discovery workflow. However there is no explicit when-to-use vs when-to-use-another guidance and no sibling is mentioned by name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whats_newA
Datasets added, changed or removed in the index since a date, and datasets whose portal says they were updated since then. Optional portal filter.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| since | Yes | YYYY-MM-DD | |
| portal | No | source_id or part of a portal name |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It helpfully discloses the dual inclusion logic (index changes vs portal-reported updates) but omits limit/pagination behavior, ordering, return shape, and any permission/rate-limit context.
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 short sentences, front-loaded with the selection criteria, and no unnecessary wording. The optional filter note is efficient.
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 3-parameter query tool with no annotations and no output schema, the description covers the core selection logic but omits the limit parameter and return/pagination details. It is adequate but not complete.
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 coverage is 67%. The description clarifies 'since' as a date and 'portal' as an optional filter, but never mentions the 'limit' parameter, which has no schema description. It adds partial meaning but leaves one parameter undocumented.
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 the resource (datasets) and the temporal scope (added, changed, removed since a date; portal-reported updates), so the purpose is clear. It does not explicitly distinguish itself from search_datasets or other siblings, so it falls short of a 5.
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?
It implies usage for finding recent index or portal changes and notes an optional portal filter, but gives no explicit when-to-use vs alternatives (e.g., search_datasets) or when-not conditions. Guidance is only implied.
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.
9 tool updates
v0.1.0- First observed
check_source - First observed
find_joinable - First observed
find_sources - First observed
get_dataset_columns - First observed
how_to_query - First observed
list_sources_for_place - First observed
registry_info - First observed
search_datasets - First observed
whats_new
TDQS
Scored across 9 tools
Most tools have clearly distinct roles: source discovery, place-level source lookup, query instructions, live checks, registry metadata, dataset search, column inspection, join discovery, and change tracking. The only meaningful overlap is find_sources versus list_sources_for_place when a place is used as a search term, but the descriptions clarify the difference between a general search and a comprehensive place profile.
The set mostly follows a consistent snake_case verb_noun convention: find_sources, list_sources_for_place, check_source, search_datasets, get_dataset_columns, find_joinable. Minor deviations are registry_info and whats_new, which are noun/phrase-style rather than verb_noun, but overall the naming remains predictable.
Nine tools is well-scoped for a registry/discovery server, with each tool covering a distinct part of the workflow: source discovery, place lookup, query guidance, health checks, registry metadata, dataset search, column inspection, joins, and change tracking. No tool feels redundant or missing from a count perspective.
The surface covers the core lifecycle well: finding sources, understanding how to query them, checking liveness, searching harvested datasets, inspecting columns, finding joinable datasets, and tracking changes. Minor gaps remain, such as a dedicated single-source detail tool beyond how_to_query or a direct dataset-detail lookup beyond column inspection, but agents can work around these.
Maintenance
Related MCP Connectors
Agent-ready NYC public records. Hosted, source-backed civic data organized around durable anchors.
Search 77k public-sector open data APIs across 10 countries. Read-only, no API key.
Normalized official data with provenance, aggregations, insights, free samples and agent access.
Normalized official data with provenance, aggregations, insights, free samples and agent access.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables querying NYC Open Data datasets using natural language, with tools to search datasets, run SoQL queries, and retrieve metadata, all without an API key.691 npmMIT

Akil MCPofficial
AlicenseNot gradedqualityCmaintenanceEnables AI agents to query NYC public records through a hosted MCP server, supporting civic workflows such as property research, business evaluation, public money tracking, and influence mapping.14 npmMIT- AlicenseAqualityCmaintenanceEnables agents to discover and access Norwegian open government data by asking questions in natural language, performing filtered searches, running SPARQL queries, and downloading actual dataset files from publishers.6MIT
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to turn natural-language questions into precise paths to authoritative primary data sources, recommending vetted government, international, and research datasets and providing step-by-step navigation instructions for locating and downloading the underlying data.-