---
summary: "census_query_data returns wildcard results 50 rows at a time with limit/offset paging; ACS sentinels and withheld business values decode to their published meanings; limit, sort_by, empty variables, and the variable count are validated before any Census request."
breaking: true
security: false
---

# 0.4.0 — 2026-09-25

Breaking: inputs the data and discovery tools used to accept, clamp, or pass through are now rejected, and a `census_query_data` wildcard is no longer unbounded — see the first five bullets under Changed.

## Changed

- **`census_query_data` pages its rows** — new `limit` (1–500, default 50) and `offset` (≥0, default 0) inputs; rows come in GEOID order, every row counts (each `pep/charv` record and `"*"` category), and enrichment adds `totalCount` and `truncated` with a notice naming the next `offset`. A wildcard that returned every row now returns at most 50 by default. ([#35](https://github.com/cyanheads/census-mcp-server/issues/35))
- **`limit` is a bounded integer at the schema** on `census_search_variables` (1–100), `census_list_predicate_values`, and `census_compare_geographies` (1–500). 0, negative, fractional, or above-max values fail with `invalid_arguments` instead of being clamped or passed through. ([#40](https://github.com/cyanheads/census-mcp-server/issues/40))
- **`too_many_variables` counts every `get=` column** on both data tools, before any request: at most 49 codes on ACS, 46 on `cbp`, 41 on `pep/charv`, since `NAME` and the added label and record columns share the Census 50-column limit. 50 codes used to be accepted and fail upstream; `census_compare_geographies` had no check. ([#46](https://github.com/cyanheads/census-mcp-server/issues/46))
- **`sort_by` must name a requested code** — `census_compare_geographies` fails with the new `sort_by_not_requested` (ValidationError) before any request, and a sort column with no number on any row gets a notice that the rows are in Census return order, not ranked. ([#38](https://github.com/cyanheads/census-mcp-server/issues/38))
- **`census_compare_geographies` rejects an empty `variables` array** with the same validation error `census_query_data` gives. ([#49](https://github.com/cyanheads/census-mcp-server/issues/49))
- **Codes and predicate keys are case-insensitive** — both data tools uppercase `variables`, `sort_by`, and predicate keys, and key the response by the uppercase code; a blank predicate value is treated as omitted. ([#45](https://github.com/cyanheads/census-mcp-server/issues/45), [#41](https://github.com/cyanheads/census-mcp-server/issues/41))
- **`census_compare_geographies` rate guidance** — the description and `variables`/`sort_by` describes say a count ranks by size and name published percentages (`S1701_C03_001E`, `DP03_0128PE`, `DP04_0047PE`) for rate rankings. ([#39](https://github.com/cyanheads/census-mcp-server/issues/39))

## Fixed

- **ACS sentinels resolve by numeric value to the Census's published meanings**, so `-666666666.0` reads like `-666666666`. A `-555555555` MOE reads as `moe: 0`, not a suppression, and an estimate whose MOE is `-333333333` keeps its figure with `open_ended: true`. `census_compare_geographies` now emits `suppression_reason`. ([#37](https://github.com/cyanheads/census-mcp-server/issues/37))
- **Withheld business values no longer read as zero** — on `cbp`, `ecnbasic`, and `nonemp` each measure's `_F` flag column is requested; a withholding flag (`D`, `S`, a range letter) reports `suppressed: true` with its meaning in a new `flag: { code, meaning }` field, while a quality note (`r`, `s`) keeps the figure. ([#47](https://github.com/cyanheads/census-mcp-server/issues/47))
- **`"*"` predicate rows are labelled** — each per-category row carries `record.<CODE> = { code, label }` from the dimension's label column; `census_compare_geographies` still fails `ambiguous_rows`, now naming the dimension to pin. ([#41](https://github.com/cyanheads/census-mcp-server/issues/41))
- **Unknown variable codes return `variable_not_found`** (NotFound, not retried) naming the code, instead of a retryable `upstream_error`. Labels resolve per code, so one unlisted column such as `B19013_001EA` no longer drops every label. ([#45](https://github.com/cyanheads/census-mcp-server/issues/45))

## Dependencies

- `vitest` `^4.1.11` → `^5.0.1`
- `@types/node` `26.5.1` → `26.6.2`
- `@socketsecurity/bun-security-scanner` `^1.1.2` → `^1.1.3`

530 tests pass across 13 files; `bun run devcheck` clean.
