census-mcp-server
An MCP server that allows agents to query U.S. Census Bureau data, including demographic, economic, and housing statistics. It provides tools to browse datasets, search variables, resolve geographies to FIPS codes, and query or rank estimates across various geographic levels.
Endpoint and access
No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.
https://census.caseyjhand.com/mcpWhat its tools do
8 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.
Checks and signals
Each line is separate evidence, not a trust score.
- Passed Endpoint answered the live check ·
- Availability 1 of 1 checks passed in 30 days
What you can do with it
- Browse available Census Bureau datasets and their supported vintage years
- Search Census variables by keyword or look up by variable code
- Resolve place names or addresses to Census FIPS identifiers
- Query Census data for variables at specific geographies
Source and maintenance
- Maintenance checked
Protocol and capabilities
- Server
- census-mcp-server 0.7.2
- MCP protocol negotiated in check
- 2025-11-25
- Tools
- 8 advertised
- Resources
- 1 advertised
- Resource templates
- 1 advertised
- Prompts
- 0 advertised
{
"tools": {
"listChanged": true
},
"logging": {},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"extensions": {
"io.modelcontextprotocol/skills": {
"directoryRead": true
}
}
}Server-provided instructions
Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.
Tools
8 advertised
census_list_datasets — List Census Datasets
Browse available Census Bureau datasets with their supported vintage years. Use as the starting point when the right dataset is unknown — ACS5, ACS1, and their profile, subject, and comparison tables, population estimates, the decennial census files, and the business datasets (County Business Patterns, Economic Census, Nonemployer Statistics) serve different use cases. Pass the dataset_id value to the dataset parameter in other census tools. Each description names the predicates a dataset requires and the geography levels it publishes, both of which vary by dataset.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"filter": {
"type": "string",
"description": "Keyword to filter datasets by name or description. Omit to list all datasets."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"datasets",
"totalCount"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"description": "Machine-readable failure mode."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Guidance when no datasets matched the filter keyword."
},
"datasets": {
"type": "array",
"items": {
"type": "object",
"required": [
"dataset_id",
"name",
"description",
"available_years"
],
"properties": {
"name": {
"type": "string",
"description": "Human-readable dataset name."
},
"dataset_id": {
"type": "string",
"description": "Dataset code to pass to the dataset parameter in other tools (e.g., \"acs/acs5\", \"acs/acs5/profile\")."
},
"description": {
"type": "string",
"description": "Description of the dataset including coverage and use case guidance."
},
"available_years": {
"type": "array",
"items": {
"type": "number"
},
"description": "Vintage years this dataset can be queried for. Passing any other year to census_query_data, census_compare_geographies, or census_search_variables fails with year_not_available rather than returning data — the list is exhaustive, not a sample. It is narrower than what the Census API hosts: pep/charv publishes its 2020-2022 estimates inside the 2023 vintage under the YEAR filter, the cbp and nonemp vintages left out reject the NAME column every query here sends, and the Census API answers the acs/acs1/spp 2008 and 2010 vintages with server errors."
}
},
"description": "A single Census dataset entry.",
"additionalProperties": false
},
"description": "Matching Census datasets."
},
"totalCount": {
"type": "number",
"description": "Total number of matching datasets."
},
"filterApplied": {
"type": "string",
"description": "Filter keyword applied to the dataset list, when provided."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_list_geographies — List Census Geography Levels
List the geography levels available for a given Census dataset and year, along with the parent geographies each level requires. Use before querying to confirm that the target geography level exists — ACS1 omits many sub-state levels, and not all datasets support tracts or block groups. The geography_level values returned here are the valid inputs to the geography_level parameter in census_query_data and census_compare_geographies.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"dataset"
],
"properties": {
"year": {
"type": "number",
"description": "Vintage year. Defaults to the latest available year for the dataset."
},
"dataset": {
"type": "string",
"description": "Dataset code (e.g., \"acs/acs5\", \"acs/acs1\"). Use census_list_datasets to discover valid values. Case is ignored, and a two-part code can be given by its last part alone — \"acs5\" is acs/acs5, \"pl\" is dec/pl. Three-part codes such as acs/acs5/profile must be given in full. The response echoes the resolved code."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"geography_levels",
"dataset",
"year",
"totalLevels"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"year": {
"type": "number",
"description": "Vintage year queried."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"dataset_not_found",
"year_not_available",
"upstream_error"
],
"description": "Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset code is missing or not recognized, even after case and shorthand resolution. `year_not_available`: Dataset exists but the Census API publishes no geography list for the requested year. For a year outside the dataset's available_years, the error names the years it serves. `upstream_error`: The Census API answered the dataset's geography.json with an HTTP error other than a 404, or with HTML or an unparseable body. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"dataset": {
"type": "string",
"description": "Dataset queried."
},
"totalLevels": {
"type": "number",
"description": "Distinct geography levels available for this dataset and year — the count census_query_data and census_compare_geographies give for an unsupported level. Can be lower than the number of geography_levels entries, which repeat a level per parent hierarchy."
},
"geography_levels": {
"type": "array",
"items": {
"type": "object",
"required": [
"geography_level",
"requires_parent",
"required_parent_levels",
"example"
],
"properties": {
"example": {
"type": "string",
"description": "Example FIPS value for this geography level."
},
"geography_level": {
"type": "string",
"description": "Geography level name — the value to pass as geography_level in census_query_data (e.g., \"county\", \"tract\", \"zip code tabulation area\")."
},
"requires_parent": {
"type": "boolean",
"description": "Whether this level names any parent level. A parent is always mandatory for a concrete FIPS target; some levels drop their innermost parents when the target is \"*\", which is why a nationwide county query needs no parent_fips while a single county does."
},
"required_parent_levels": {
"type": "array",
"items": {
"type": "string"
},
"description": "Names of the parent geography levels required when requires_parent is true."
}
},
"description": "A single geography level available for this dataset.",
"additionalProperties": false
},
"description": "Geography levels supported by this dataset and year, one entry per parent hierarchy: a level published under several hierarchies (county under state, and under a metro area) appears once for each."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_search_variables — Search Census Variables
Search Census variables by keyword across variable labels and concept groups, or look one up by its code. Returns variable codes with human-readable labels — use this to go from a concept like "median household income" to the variable code B19013_001E needed for data queries. A query that is one variable or table code, such as B19013_001E or B19013, returns that variable or the table's variables, in code order, ahead of any keyword matches; a code the dataset does not publish gets a notice naming the dataset that does, when one is confirmed. On ACS datasets it returns both estimate (E suffix) and margin-of-error (M suffix) codes so you can request both; the ACS comparison profiles (acs/acs5/cprofile, acs/acs1/cprofile) and the other dataset families publish no margins of error. Also use it to find the predicate codes a dataset filters on, such as NAICS2017 in cbp. Adding a word narrows the results, since every word must match. Use offset to continue the same search beyond limit; nextOffset names the next page.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"query"
],
"properties": {
"year": {
"type": "number",
"description": "Vintage year to search (default: latest available for the dataset)."
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Maximum results per page (default: 20, max: 100). Follow nextOffset to continue the same search."
},
"query": {
"type": "string",
"description": "Keywords to search (e.g., \"median household income\", \"poverty\", \"bachelor's degree\"), or one variable or table code (e.g., \"B19013_001E\", \"B19013\"). Each word must match a whole word of the label or of the concept, ignoring case and punctuation, so \"rate\" does not match \"separated\". A column shared across tables, such as GEO_ID, is matched on its label only, and a margin of error on its estimate's label. When no variable contains every word, the results are the variables containing the most words, and the notice says how many that was. A single token that equals a variable code or a table ID, ignoring case and any quotes or punctuation around it, returns those variables first. A token with no digit or underscore, such as \"state\", is read as a code when no keyword matched; ahead of keyword matches only when typed in the code's own uppercase (\"STATE\")."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Matching variables to skip in the existing rank order (default: 0). Keep query, dataset, year and limit unchanged when following nextOffset."
},
"dataset": {
"type": "string",
"description": "Dataset to search within (default: \"acs/acs5\"). Use census_list_datasets to discover options. Case is ignored, and a two-part code can be given by its last part alone — \"acs5\" is acs/acs5, \"pl\" is dec/pl. Three-part codes such as acs/acs5/profile must be given in full. The response echoes the resolved code, and the default year is that dataset's latest."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"variables",
"effectiveQuery",
"dataset",
"year",
"totalMatches"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"cap": {
"type": "number",
"description": "The limit that was applied."
},
"year": {
"type": "number",
"description": "Vintage year that was searched."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"dataset_not_found",
"year_not_available",
"variables_unavailable",
"upstream_error"
],
"description": "Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset code is not recognized, even after case and shorthand resolution. `year_not_available`: The dataset does not serve the requested vintage year. `variables_unavailable`: Variable metadata could not be fetched or parsed from the Census API. `upstream_error`: The Census API answered the dataset's variables.json with an HTTP error, after any retries a transient status earns. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"shown": {
"type": "number",
"description": "Number of variables returned after the limit."
},
"notice": {
"type": "string",
"description": "Guidance for no matches, partial-term matches, continuation, the final page or an offset past the end. For a code the dataset does not publish, names the confirmed sibling dataset or census_get_variable for an attribute column; for a table cut inside its code tier, names the last code shown and the next offset."
},
"dataset": {
"type": "string",
"description": "Dataset that was searched."
},
"truncated": {
"type": "boolean",
"description": "True when more matching variables remain after the current page."
},
"variables": {
"type": "array",
"items": {
"type": "object",
"required": [
"variable_code",
"label",
"predicate_type"
],
"properties": {
"label": {
"type": "string",
"description": "Human-readable variable label from the Census data dictionary."
},
"concept": {
"type": "string",
"description": "Concept of the table the variable belongs to (e.g., \"Median Household Income in the Past 12 Months\"). Absent for a column shared across tables, such as GEO_ID, whose concept joins every table it appears in, and for a column the dataset publishes no concept for, such as STATE."
},
"moe_code": {
"type": "string",
"description": "Corresponding margin-of-error variable code when this is an estimate variable. Request both estimate and MOE in census_query_data for complete data. ACS datasets only, apart from the comparison profiles (acs/acs5/cprofile, acs/acs1/cprofile) — there and on other families an E-final code has no margin-of-error sibling, so the field is absent."
},
"estimate_code": {
"type": "string",
"description": "Corresponding estimate variable code when this is a margin-of-error variable. ACS datasets only, apart from the comparison profiles — no other dataset publishes margins of error."
},
"variable_code": {
"type": "string",
"description": "Variable code to pass to census_query_data (e.g., \"B19013_001E\")."
},
"predicate_type": {
"type": "string",
"description": "Data type of the variable (e.g., \"int\", \"string\", \"float\")."
}
},
"description": "A single matching Census variable entry.",
"additionalProperties": false
},
"description": "Matching variables, best first: the variable whose code equals the query, or every variable of the table whose ID equals it, in code order; then a variable whose label's last !!-separated segment or whose whole concept equals the query, then the query as a phrase in both label and concept, in the label only, in the concept only, then every word present but not as a phrase; ties go to fewer !! segments in the label, then a shorter concept, then the code, which puts an E estimate before its M margin of error. On ACS datasets, codes ending in E are estimates and M are their margins of error, except on the comparison profiles, which publish no M codes; on other datasets the suffix carries no such meaning."
},
"nextOffset": {
"type": "number",
"description": "Offset for the next page; absent when no matches remain after this page."
},
"totalMatches": {
"type": "number",
"description": "Variables matched before the limit was applied: those matching the query as a code, plus those containing every query word — or, when none does and no code matched, the variables that contain the most words."
},
"effectiveQuery": {
"type": "string",
"description": "Query as the server parsed it."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_get_variable — Get Census Variable Metadata
Fetch full metadata for one or more Census variable codes — label, concept group, predicate type, the table's universe, and margin-of-error sibling references. Use to confirm a variable code before building a query, or to look up what a known code means. On ACS datasets it returns estimate_code and moe_code sibling references so you can request both without a separate search, and a margin-of-error code carries attribute_of (its estimate) and attribute_type MARGIN_OF_ERROR; the ACS comparison profiles (acs/acs5/cprofile, acs/acs1/cprofile) and the other dataset families publish no margins of error and carry none of these fields. It also resolves the annotation and flag columns the data tools accept, such as B19013_001EA or EMP_F, naming the column each one belongs to, and predicate codes such as NAICS2017 or SEX, confirming a filter dimension exists in a dataset before a query uses it — for the values a dimension accepts rather than the dimension itself, call census_list_predicate_values.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"variables"
],
"properties": {
"year": {
"type": "number",
"description": "Vintage year (default: latest available for the dataset)."
},
"dataset": {
"type": "string",
"description": "Dataset the variables belong to (default: \"acs/acs5\"). Use census_list_datasets to discover valid values. Case is ignored, and a two-part code can be given by its last part alone — \"acs5\" is acs/acs5, \"pl\" is dec/pl. Three-part codes such as acs/acs5/profile must be given in full. The response echoes the resolved code."
},
"variables": {
"type": "array",
"items": {
"type": "string"
},
"description": "One or more variable codes to look up (e.g., [\"B19013_001E\", \"B19013_001M\"]). Codes are trimmed and matched regardless of case, and the response echoes the dataset's own spelling — uppercase everywhere except the comparison profiles' significance columns (e.g., CP03_2024to2019_062SS)."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"variables",
"dataset",
"year"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"year": {
"type": "number",
"description": "Vintage year queried."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"variable_not_found",
"dataset_not_found",
"year_not_available",
"variables_unavailable",
"upstream_error"
],
"description": "Machine-readable failure mode. Declared by this tool: `variable_not_found`: One or more variable codes were not found in the dataset and year. `dataset_not_found`: Dataset code is not recognized, even after case and shorthand resolution. `year_not_available`: The dataset does not serve the requested vintage year. `variables_unavailable`: The dataset's variables.json came back as HTML or unparseable, or an attribute column's own entry could not be fetched or parsed. `upstream_error`: The Census API answered the dataset's variables.json with an HTTP error, after any retries a transient status earns. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Present when the dataset's universe lookup failed: names the codes returned without universe for that reason, and says to retry."
},
"dataset": {
"type": "string",
"description": "Dataset queried."
},
"variables": {
"type": "array",
"items": {
"type": "object",
"required": [
"variable_code",
"label",
"predicate_type"
],
"properties": {
"label": {
"type": "string",
"description": "Human-readable label from the Census data dictionary."
},
"concept": {
"type": "string",
"description": "Concept of the table the variable belongs to. Absent for a column shared across tables, such as GEO_ID, whose concept joins every table it appears in, and for a column the dataset publishes no concept for, such as STATE."
},
"moe_code": {
"type": "string",
"description": "Margin-of-error sibling code when this is an estimate variable. Include both in census_query_data for complete data. ACS datasets only, apart from the comparison profiles (acs/acs5/cprofile, acs/acs1/cprofile) — there and on other families an E-final code has no margin-of-error sibling, so the field is absent."
},
"universe": {
"type": "string",
"description": "Universe of the variable's table (e.g., \"Households\", \"Population 25 years and over\"). Absent when the table publishes none — the ACS subject, profile, and selected population profile tables, dec/dp, the business datasets, pep/charv, and every ACS and dec/pl vintage before 2020 publish none — and for a column that belongs to no single table. Also absent when the universe lookup failed, which the notice names along with the affected codes; retrying can return it."
},
"attribute_of": {
"type": "string",
"description": "For an annotation, flag, or margin-of-error column, the column it belongs to, as the Census publishes it (e.g., \"B19013_001E\" for B19013_001EA or B19013_001M). Absent on ordinary variables."
},
"estimate_code": {
"type": "string",
"description": "Estimate sibling variable code when this is a margin-of-error variable. ACS datasets only, apart from the comparison profiles — no other dataset publishes margins of error."
},
"variable_code": {
"type": "string",
"description": "Census variable code (e.g., \"B19013_001E\")."
},
"attribute_type": {
"type": "string",
"description": "For an annotation, flag, or margin-of-error column, its kind in upper-snake case (e.g., \"ANNOTATION\", \"FLAG\", \"MARGIN_OF_ERROR\"), whatever spelling the vintage publishes — older vintages write \"Annotation\" or \"Margin of Error\". Absent on ordinary variables."
},
"predicate_type": {
"type": "string",
"description": "Data type (e.g., \"int\", \"string\", \"float\")."
}
},
"description": "Full metadata for a single Census variable.",
"additionalProperties": false
},
"description": "Variable metadata in the same order as the input array."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_list_predicate_values — List Census Predicate Values
List the codes a Census filter dimension accepts, so a predicates map can be written without guessing. Answers the question left open when census_query_data or census_compare_geographies reports that a dimension was left unset. Which route a dimension takes depends on the vintage: NAICS and POPGROUP always publish a value list in the dataset dictionary, and on the current vintages EMPSZES, LFO, RCPSZES, TAXSTAT, and TYPOP publish none and are enumerated here against the live data endpoint instead, which needs the server's Census API key. A dictionary value list is a classification shared across Census products rather than a list of what one dataset serves, and roughly half of its codes typically return no rows anywhere — those are checked against the dataset's own published rows and dropped, a check that also reads the data endpoint and so needs the key; without a working key the dictionary list comes back unchecked, and the response source field says whether that check ran. The dictionary lists run to thousands of codes and are best narrowed with query. Pass the returned code as the dimension's value in predicates.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"predicate",
"dataset"
],
"properties": {
"year": {
"type": "number",
"description": "Vintage year (default: latest available for the dataset)."
},
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Maximum codes per page (default: 50, max: 500). totalCount counts matches before offset and limit; nextOffset continues the list."
},
"query": {
"type": "string",
"description": "Keyword to narrow the list, matched case-insensitively against each code and label (e.g., \"software\" against NAICS2017, \"exempt\" against TAXSTAT). Omit to list from the start. NAICS and POPGROUP run to thousands of codes, so a keyword is the practical way to use them."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Matching codes to skip in code order (default: 0). Follow nextOffset with the same predicate, dataset, year, query, geography_level and within_naics."
},
"dataset": {
"type": "string",
"description": "Dataset the dimension belongs to (e.g., \"cbp\", \"nonemp\", \"ecnbasic\", \"dec/ddhca\", \"dec/ddhcb\", \"pep/charv\", \"acs/acs1/spp\"). Use census_list_datasets to discover valid values. Case is ignored, and a two-part code can be given by its last part alone — \"ddhca\" is dec/ddhca, \"charv\" is pep/charv. Three-part codes such as acs/acs1/spp must be given in full. The response echoes the resolved code. Dimension codes are vintage-specific, so the dataset and year must match the query the values are for."
},
"predicate": {
"type": "string",
"description": "Filter dimension code to enumerate (e.g., \"EMPSZES\", \"LFO\", \"POPGROUP\", \"NAICS2017\"). Trimmed and uppercased, and the response echoes that spelling. The response notice of census_query_data names the dimensions a dataset declares, and census_search_variables finds them by keyword."
},
"within_naics": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^\\d{2,8}(-\\d{2})?$",
"description": "A NAICS code: 2 to 8 digits, or a hyphenated sector range such as \"31-33\"."
}
],
"description": "Industry code to scope the enumeration by, for dimensions the Census publishes per industry. On ecnbasic, TAXSTAT and TYPOP return only the all-establishments row until a NAICS sector is named — pass a sector code such as \"62\" (Health Care) or \"42\" (Wholesale Trade) and the result is complete for that industry alone. Ignored for dimensions with a published value list. Get sector codes by calling this tool on the dataset's own NAICS dimension. Blank is treated as omitted."
},
"geography_level": {
"type": "string",
"description": "Geography level for live enumeration (default: \"us\"). Codes can differ by level. Only levels whose dataset/year geography metadata permits a wildcard without concrete parents are supported, such as \"county\" on cbp. Dictionary lists remain dataset-wide and do not validate publication at this level."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"values",
"predicate",
"predicate_label",
"dataset",
"year",
"totalCount",
"truncated",
"source"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"year": {
"type": "number",
"description": "Vintage year queried."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"geography_not_supported",
"parent_required",
"dataset_not_found",
"missing_api_key",
"year_not_available",
"predicate_not_supported",
"not_a_filter_dimension",
"no_values",
"upstream_error",
"variables_unavailable"
],
"description": "Machine-readable failure mode. Declared by this tool: `geography_not_supported`: An explicit live geography level is not listed by this dataset and year. `parent_required`: An explicit live geography level needs concrete parents even with a wildcard target. `dataset_not_found`: Dataset code is missing or not recognized, even after case and shorthand resolution. `missing_api_key`: A dimension with no published value list is enumerated against the data endpoint, and CENSUS_API_KEY is not configured or the key is invalid. `year_not_available`: The dataset does not serve the requested vintage year. `predicate_not_supported`: The predicate code is not a variable in this dataset and year. `not_a_filter_dimension`: The code is not one of the dimensions the dataset filters on, so it takes no value list. `no_values`: The dimension returned no codes for the scope requested. `upstream_error`: Census API returned an error, was unreachable, explicit geography metadata was unavailable, or upstream work exceeded the shared 50-second call budget or the enumeration local 40-second ceiling across retries. `variables_unavailable`: The dataset's variables.json came back as HTML or unparseable, so the predicate cannot be checked against it. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Guidance when the list was truncated, when query matched no published code, when codes from the dataset dictionary could not be checked against its published rows, or when the codes returned are complete only for a named industry rather than for the dimension as a whole."
},
"source": {
"type": "string",
"description": "Where the codes came from. \"live_query\" is a wildcard group-by against the data endpoint, which returns only codes the dataset publishes. \"dataset_dictionary_verified\" is the dataset's published value map with the codes it serves no rows for removed. Plain \"dataset_dictionary\" is that map unchecked — every code in it is declared by the dataset, but some of them return nothing at any geography, and the notice says why the check did not run."
},
"values": {
"type": "array",
"items": {
"type": "object",
"required": [
"code",
"label"
],
"properties": {
"code": {
"type": "string",
"description": "The value to send for this dimension in a predicates map (e.g., \"210\" for EMPSZES)."
},
"label": {
"type": "string",
"description": "What the code means (e.g., \"Establishments with less than 5 employees\"). Falls back to the code when the dataset publishes no label for it."
}
},
"description": "One accepted code for the dimension, with its label.",
"additionalProperties": false
},
"description": "Codes the dimension accepts, sorted by code."
},
"dataset": {
"type": "string",
"description": "Dataset queried."
},
"predicate": {
"type": "string",
"description": "Filter dimension enumerated."
},
"truncated": {
"type": "boolean",
"description": "True when matching codes remain after the current page."
},
"nextOffset": {
"type": "number",
"description": "Offset for the next page; absent when no matching codes remain after this page."
},
"totalCount": {
"type": "number",
"description": "Codes matched before the limit was applied."
},
"geography_level": {
"type": "string",
"description": "Effective live enumeration level. Absent for a dictionary list, which does not validate geography-specific publication."
},
"predicate_label": {
"type": "string",
"description": "Label of the dimension itself (e.g., \"Employment size of establishments code\")."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_resolve_geography — Resolve Census Geography
Resolve a place name, ZIP code, or street address to Census FIPS identifiers. Converts names like "King County, WA", "Seattle, WA", or "Seattle-Tacoma-Bellevue, WA", and ZIPs like "98109", to the codes required by census_query_data and census_compare_geographies. Use before querying when you have a place name rather than raw FIPS codes — state_fips maps to parent_fips and fips_summary maps to geography_fips in downstream tools, and geography_type is itself the geography_level to query at.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "Place name (e.g., \"King County, WA\", \"Seattle, WA\", \"California\"), 5-digit ZIP code (e.g., \"98109\", resolved to its ZIP Code Tabulation Area), or street address (e.g., \"1600 Pennsylvania Ave NW, Washington, DC 20500\"). Include the state after a comma — its abbreviation or full name, as in \"Chatham County, Georgia\" — to disambiguate places with common names. It narrows a statistical area as well, matching any state the area spans, so \"Kansas City, MO\" and \"Kansas City, KS\" both reach the MO-KS metro area. Matching ignores case, reads \"Saint\" and \"St.\" as the same word, and accepts unaccented spellings (\"Dona Ana County, NM\"). For a statistical area a leading city is enough (\"Denver, CO\" for the Denver-Aurora-Centennial metro area), and an older full name resolves through its leading city (\"Denver-Aurora-Lakewood, CO\"). A New York City borough with a New York suffix resolves to the county it is coextensive with when geography_type is \"county\" or omitted — \"Brooklyn, NY\" is Kings County, \"Manhattan, NY\" New York County, \"Staten Island, NY\" Richmond County. At any other level it is no_match, and at place, economic place, state, tract, or consolidated city the hint names the county."
},
"county_fips": {
"type": "string",
"pattern": "^\\d{1,3}$",
"description": "County FIPS code to resolve within — 1 to 3 digits, zero-padded here to the 3 the Census stores. A tract name is unique only inside its county, so a bare tract name matching two counties comes back as ambiguous_name until this is set: take the countyFips of the candidate you want from that error and re-call. Only county and tract sit within a county, so this restricts resolution to those two levels — pairing it with any other geography_type, or with a street address, is a county_scope_unsupported error rather than a scope quietly dropped. census_query_data takes the same code as its own county_fips but pads nothing, so hand it the 3-digit county_fips returned here, not the shorter value."
},
"geography_type": {
"enum": [
"state",
"county",
"place",
"tract",
"metropolitan statistical area/micropolitan statistical area",
"combined statistical area",
"consolidated city",
"zip code tabulation area",
"economic place"
],
"type": "string",
"description": "Geography level to resolve to, named exactly as census_query_data's geography_level and census_list_geographies name it. Auto-detection covers only state, county, place, tract, and zip code tabulation area: zip code tabulation area for a 5-digit ZIP or ZIP+4 — the ACS's ZIP-shaped area, not cbp's \"zip code\" level, which takes the ZIP itself with no resolution — state for a two-letter abbreviation or a spelled-out state name, county when the name contains the word \"County\" or \"Parish\", county then place for the word \"Borough\" (an Alaska borough is a county, a PA or NJ borough a place), tract for the word \"Tract\", otherwise place (incorporated places and census-designated places together) with a fallback to county, where a census-designated place answers only when no incorporated place or county has the exact name — \"Arlington, VA\" is Arlington County, and set \"place\" to reach the Arlington CDP. The other four are never auto-detected and must be set explicitly, because their names overlap city names — \"metropolitan statistical area/micropolitan statistical area\" covers both metro and micro areas and yields a 5-digit code, \"combined statistical area\" yields a 3-digit code, \"consolidated city\" covers the eight merged city-county governments (Nashville-Davidson, Louisville/Jefferson County, Indianapolis, Athens-Clarke County, Augusta-Richmond County, Butte-Silver Bow, Milford CT, Greeley County KS), and \"economic place\" yields the 8-digit code ecnbasic 2022 publishes a place under: the 3-digit county it lies in (000 when it spans counties) followed by its 5-digit place code. Economic places are the incorporated places, census-designated places, and county subdivisions the 2022 Economic Census tabulates, plus each county's remainder (\"Balance of Adams County, WA\"). Setting it explicitly also overrides auto-detection — \"New York\" auto-detects as the state, so New York City needs \"place\"."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"name",
"geography_type",
"fips_summary"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"name": {
"type": "string",
"description": "Canonical name of the resolved geography."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"no_match",
"ambiguous_name",
"county_scope_unsupported",
"resolution_unavailable"
],
"description": "Machine-readable failure mode. Declared by this tool: `no_match`: Place name not recognized at any geography level tried for it. `ambiguous_name`: Name matched more than one geography. `county_scope_unsupported`: county_fips was combined with a street address, or with a geography_type — set or auto-detected — that does not sit within a county. `resolution_unavailable`: Geography resolution endpoint was unreachable. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Present when the name was a New York City borough (\"Brooklyn\", \"The Bronx\", \"Queens borough\") resolved to the county it is coextensive with."
},
"place_fips": {
"type": "string",
"description": "5-digit place FIPS code when the resolved geography is a place — incorporated or census-designated. For an economic place, the place part of its 8-digit code, which is also the place code the 2017 and 2012 ecnbasic vintages take. For a street address, the incorporated place the address sits in (query it at the place level with state_fips as parent_fips); absent when the address is outside every incorporated place, and a census-designated place is never reported for an address."
},
"state_fips": {
"type": "string",
"description": "2-digit state FIPS code. Use as parent_fips in census_query_data for sub-state queries. Absent for a metropolitan/micropolitan or combined statistical area, which can span several states and needs no parent_fips, and for a zip code tabulation area, whose source layer carries no state."
},
"tract_fips": {
"type": "string",
"description": "6-digit census tract FIPS code when the resolved geography is a tract — from a street address, or from a tract name."
},
"county_fips": {
"type": "string",
"description": "3-digit county FIPS code when the resolved geography is a county or sub-county level."
},
"fips_summary": {
"type": "string",
"description": "Pre-formatted FIPS value ready to use as geography_fips in census_query_data (e.g., \"033\" for King County with state_fips \"53\" as parent_fips, \"42660\" for the Seattle-Tacoma-Bellevue metro area with no parent at all, \"03363000\" for Seattle as an ecnbasic 2022 economic place)."
},
"geography_type": {
"type": "string",
"description": "Resolved geography level. Pass this straight through as geography_level in census_query_data and census_compare_geographies."
},
"block_group_fips": {
"type": "string",
"description": "1-digit block group within tract_fips, for a street address only. Query it as geography_level \"block group\" with this as geography_fips, alongside parent_fips, county_fips, and tract_fips. geography_type and fips_summary stay at the tract."
},
"census_designated_place": {
"type": "boolean",
"const": true,
"description": "Present (true) when the resolved place or economic place is a census-designated place (CDP): an unincorporated community the Census delineates for statistics, with no municipal government. Its code is queried like an incorporated place's. Absent for an incorporated place and every other level."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_query_data — Query Census Data
Query a Census dataset for one or more variables at one geography, a list of geographies at the same level, or every geography at a level. Accepts FIPS codes for the target geography — use census_resolve_geography to convert place names to FIPS when needed. On ACS datasets, labeled estimates and margin-of-error values are returned together (the comparison profiles publish no margins), and the negative sentinel values the Census writes for an estimate or margin of error it cannot publish are decoded into the meanings the Census gives them rather than passed through as raw numbers. A value cbp, ecnbasic, or nonemp withheld is stored as 0 beside a flag, and is reported as withheld, with the meaning of its flag, rather than as a zero. Pass geography_fips as "*" for every geography at the level within the parent, or as a comma-separated list of codes ("06,53") for several: rows come back in GEOID order, up to limit per call (default 50, max 500), with totalCount giving how many matched and offset reaching the rest — the order is not a ranking, so use census_compare_geographies to rank. The notice names any listed code that no row came back for. On the business datasets (cbp, ecnbasic, nonemp), pep/charv, dec/ddhca, dec/ddhcb, and acs/acs1/spp, use predicates to filter by industry, size class, or population group — a query that omits one is answered with a default the Census API picks, which is an all-categories total on some dimensions and a single category on others. Each row names the defaults that were applied in applied_filters, and census_list_predicate_values enumerates the codes a dimension accepts. Some dec/ddhca and dec/ddhcb tables split the population groups between them, publishing each group at a geography in only one table of the family, so where a result can be missing a group, a geography, or a value, the notice names the sibling tables to look in. One geography can also come back on more than one row: pep/charv publishes an April estimates base alongside its July estimate, and each row carries a record field saying which it is.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"variables",
"geography_level",
"geography_fips"
],
"properties": {
"year": {
"type": "number",
"description": "Vintage year (default: latest available for the dataset)."
},
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Most rows to return (default: 50, max: 500). Rows come in GEOID order, whether geography_fips is \"*\" or a comma-separated list, a geography's records or categories in code order, and each one counts, so a geography returned as several records (pep/charv April and July) or as one row per category of a \"*\" predicate takes one row each. totalCount says how many rows matched."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Rows to skip before returning up to limit (default: 0). Pages run in GEOID order, so offset 50 with limit 50 returns rows 51–100, and the notice names the offset of the next page. An offset at or past totalCount returns no rows."
},
"dataset": {
"type": "string",
"description": "Dataset to query (default: \"acs/acs5\"). Use census_list_datasets to discover valid values. Case is ignored, and a two-part code can be given by its last part alone — \"acs5\" is acs/acs5, \"pl\" is dec/pl. Three-part codes such as acs/acs5/profile must be given in full. The response echoes the resolved code."
},
"variables": {
"type": "array",
"items": {
"type": "string"
},
"description": "Variable codes to retrieve (e.g., [\"B19013_001E\", \"B19013_001M\"]). Codes are matched regardless of case and sent in the dataset's own spelling, which keys the response: \"b19013_001e\" reads as B19013_001E, and \"cp03_2024to2019_062ss\" as the comparison profiles' mixed-case significance column CP03_2024to2019_062SS. A code the dataset does not list is sent uppercased. At most 49 per call: the Census API accepts 50 columns per request and every query also sends NAME. On datasets where a label column is added for each filter dimension left unset, or record columns are added (cbp, ecnbasic, nonemp, pep/charv, dec/ddhca, dec/ddhcb, acs/acs1/spp), the maximum is lower, and too_many_variables states the exact number for the query. Use census_search_variables to find codes. On ACS datasets only, apart from the comparison profiles (acs/acs5/cprofile, acs/acs1/cprofile), which publish none, each estimate has a margin-of-error counterpart at the same code with the E suffix swapped for M — request both to get the margin alongside the estimate. Other dataset families (pep, dec, cbp, ecnbasic, nonemp) publish no margins of error, and an E-final code there is an ordinary code with no M sibling. A code can also name a text column rather than a measure — GEO_ID, on every dataset, is the nationally unique geography identifier and comes back under value with estimate null, which is the code to request when a stable join key is what is wanted."
},
"predicates": {
"type": "object",
"description": "Filter values keyed by variable code, sent as extra query parameters — e.g. {\"NAICS2017\": \"5112\"} to count only software publishers in cbp. The business datasets (cbp, ecnbasic, nonemp), pep/charv, dec/ddhca, dec/ddhcb, and acs/acs1/spp declare filter dimensions such as industry (NAICS2017/NAICS2022), legal form (LFO), size class (EMPSZES/RCPSZES), tax status (TAXSTAT), operation type (TYPOP), sex (SEX), age (AGE), and population group (POPGROUP). Leaving one unset is not an error: the Census API substitutes its own default, which is the all-categories total on cbp NAICS2017 but a single population group on dec/ddhca and dec/ddhcb POPGROUP and a single sector on ecnbasic NAICS2022 — so an unfiltered value can read like a total without being one. Every unset dimension is named in the response notice and its applied default is echoed per row in applied_filters. Keys are matched case-insensitively, and a blank value is treated as omitted. A value of \"*\" returns one row per category of that dimension for each geography, each row labelled with its category in record (e.g. {\"NAICS2017\": \"*\"} gives King County one row per industry) — a breakdown that can run to over a thousand rows. Code names vary by dataset and vintage — cbp 2023 uses NAICS2017 while nonemp 2023 uses NAICS2022 — so read them from the notice or from census_search_variables. Call census_list_predicate_values for the codes a dimension accepts; NAICS values are standard North American Industry Classification System codes at any depth (51 information, 5112 software publishers).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"tract_fips": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^\\d{6}$",
"description": "Exactly 6 digits — never padded here, and never \"*\"."
}
],
"description": "Census tract code scoping the query to one tract (e.g., \"007101\" for Census Tract 71.01), for the levels that sit within a tract — block group on acs/acs5, block group and block on dec/pl. census_resolve_geography returns it as tract_fips, and for a street address also returns the block_group_fips to pass as geography_fips. A tract code is unique only within its county, so it needs parent_fips and a concrete county_fips (not \"*\"). It is exactly 6 digits and is not padded, since \"7101\" and \"71\" do not name one tract. A level that does not sit within a tract rejects it. Blank is treated as omitted."
},
"county_fips": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^(\\*|\\d{1,3})$",
"description": "1 to 3 digits, zero-padded here to the 3 the Census stores, or \"*\"."
}
],
"description": "County FIPS code when querying tracts or block groups within a specific county (e.g., \"033\" for King County within WA). Required for tract and block-group queries scoped to a county — use alongside parent_fips (state). census_resolve_geography returns this as county_fips. Pass \"*\" to span every county in the state, which is the only way a block-group query reaches a whole state; \"*\" works on the levels whose hierarchy lets it stand in for the county, such as tract and block group, and never under a tract_fips. Blank is treated as omitted."
},
"parent_fips": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^(\\*|\\d{1,2})$",
"description": "1 to 2 digits, zero-padded here to the 2 the Census stores, or \"*\"."
}
],
"description": "State FIPS code when querying sub-state levels (e.g., \"53\" for Washington). Required for county, tract, and block-group queries. census_resolve_geography returns this as state_fips. Pass \"*\" to span every state on the levels whose hierarchy lets \"*\" stand in for the state, such as county and place; tract, block group, and county subdivision need one state. Blank is treated as omitted."
},
"geography_fips": {
"type": "string",
"description": "FIPS code for the target geography (e.g., \"033\" for a county, \"*\" for every geography at the level within the parent, returned up to limit rows per call and paged with offset). Use census_resolve_geography to obtain this value — it is returned as fips_summary. The Census API matches this literally and its width follows geography_level, so it is passed through unpadded: a county is 3 digits (\"051\", not \"51\") and a tract is 6. parent_fips and county_fips are zero-padded for you; this one is not. Several codes at the same level can be joined with commas — \"06,53\" for two states, or \"033,061\" with parent_fips \"53\" for two counties — each at the level's width, none of them \"*\", and with the parents a single code needs. Spaces around a code are ignored and a repeated code returns one row. Rows come back in GEOID order, not list order, paged by limit and offset with totalCount, and the notice names each code no row came back for. On dec/ddhca and dec/ddhcb tables that split the population groups between them, a code whose group is published in a sibling table there has no row, and the notice names the tables to look in."
},
"geography_level": {
"type": "string",
"description": "Level of the target geography (e.g., \"county\", \"tract\", \"state\", \"zip code tabulation area\"). Use census_list_geographies to see valid values for the dataset."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"rows",
"totalRows",
"totalCount",
"truncated",
"dataset",
"year"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"required": [
"geography_name",
"geography_fips",
"geography_geoid",
"variables"
],
"properties": {
"record": {
"type": "object",
"properties": {},
"description": "Which record this row is, when one geography comes back on more than one row — keyed by the column that separates them, each value carrying a code and a label (e.g. {\"MONTH\": {\"code\": \"7\", \"label\": \"July\"}}). pep/charv publishes an April estimates base and a July estimate, so one geography comes back on two rows whose numbers differ; this field is what says which is which. A dimension set to \"*\" in predicates lands here too, one row per category (e.g. {\"NAICS2017\": {\"code\": \"11\", \"label\": \"Agriculture, forestry, fishing and hunting\"}}), with the code as its label when the dimension publishes no label column. Pass the code back in predicates (e.g. {\"MONTH\": \"7\"}) to return that record alone. Absent on the datasets that return one row per geography.",
"additionalProperties": {}
},
"variables": {
"type": "object",
"properties": {},
"description": "Map of variable code to value entry. Each key is a variable code from the variables input, in the dataset's spelling — uppercase except the comparison profiles' significance columns (CP03_2024to2019_062SS); each value has: estimate (number|null), moe (number|null, optional), label (string), suppressed (boolean), suppression_reason (string, optional), open_ended (true, optional), flag ({code, meaning}, optional), value (string, optional). An estimate of null means one of three things and the other fields say which: suppressed true is a number the Census withheld, a value field is a cell holding text rather than a number (GEO_ID returns \"0500000US53033\"; the older ACS profile vintages write not-applicable as \"(X)\" in a column that is a number elsewhere), and neither is a cell with nothing in it. suppression_reason carries the meaning the Census publishes for the sentinel or flag. On ACS, a margin of error the Census treats as zero (a controlled estimate) is moe 0, not a suppression. open_ended true marks an ACS median that falls in the lowest or highest interval of an open-ended distribution, so the estimate is that interval's boundary (250001 for \"250,000+\", 9999 for \"10,000-\") rather than the median itself — it appears only when the matching M code was requested, since that margin of error is the only signal, and it does not say which end. flag is the symbol a business dataset (cbp, ecnbasic, nonemp) published beside the value: a withholding flag (D, S, an employment or sales range letter) comes with suppressed true, and so does a noise or data-quality band (G/H/J, 0-9) beside a 0, which is the range a range column such as EMP_N or RCPTOT_IMP publishes in place of a number; a quality note (r revised, s high relative standard error) keeps the estimate.",
"additionalProperties": {}
},
"geography_fips": {
"type": "string",
"description": "FIPS code for this geography at the queried level only, without its parents (e.g., \"033\" for King County). Pass back as the geography_fips parameter in census_query_data — alongside the same parent_fips/county_fips — for follow-up queries."
},
"geography_name": {
"type": "string",
"description": "Human-readable geography name (e.g., \"King County, Washington\")."
},
"applied_filters": {
"type": "object",
"properties": {},
"description": "Filter dimensions the query left unset, mapped to the label of the default the Census API applied (e.g. {\"POPGROUP\": \"European alone\"}). Present only on datasets that declare filter dimensions. The label is what tells an all-categories total apart from one ordinary category — dec/ddhca and dec/ddhcb default POPGROUP to a single population group, so a value carrying \"European alone\" is that group's count and not the geography's population. Set the dimension in predicates to choose it yourself.",
"additionalProperties": {}
},
"geography_geoid": {
"type": "string",
"description": "Full GEOID — the queried level concatenated with its parent levels (e.g., \"53033\" for King County, \"53033000101\" for a tract). Nationally unique, unlike geography_fips. Pass these to the geographies filter in census_compare_geographies to compare geographies across different states."
}
},
"description": "Data for one geography — name, FIPS, and variable values.",
"additionalProperties": false
},
"description": "One row per geography, or per record or category where a geography has several. When geography_fips is \"*\", the rows from offset up to limit of every geography at the level within the parent, in GEOID order; when it is a comma-separated list, the rows of the listed geographies the Census returned, in the same order and paging."
},
"year": {
"type": "number",
"description": "Vintage year queried."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"dataset_not_found",
"missing_api_key",
"year_not_available",
"variable_not_found",
"variables_unavailable",
"geography_not_supported",
"parent_required",
"parent_not_accepted",
"no_data",
"too_many_variables",
"predicate_not_supported",
"upstream_error"
],
"description": "Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset code is not recognized, even after case and shorthand resolution. `missing_api_key`: CENSUS_API_KEY is not configured or the key is invalid. `year_not_available`: The dataset does not serve the requested vintage year. `variable_not_found`: The Census API rejected a variable code as unknown for the requested dataset and year. It names only the first unknown code in a request. `variables_unavailable`: The variable metadata endpoint returned an unparseable response for this dataset and year. `geography_not_supported`: The requested geography level does not exist in this dataset and year. `parent_required`: The geography level requires a parent FIPS code but parent_fips was not provided, a tract/block-group level requires county_fips but it was omitted, a single block group requires tract_fips, tract_fips was set without a concrete county_fips, or parent_fips or county_fips is \"*\" where the level's hierarchy does not let \"*\" stand in for that parent. For a level the dataset lists under several hierarchies, no hierarchy accepts the call and the error describes the one closest to accepting it, which can need a \"*\" geography_fips or a parent this tool has no input for. When that hierarchy also does not take a parent the call supplied, the error names that parent to drop as well. `parent_not_accepted`: parent_fips, county_fips, or tract_fips names a parent the geography level does not sit within — for a level listed under several hierarchies, one that dropping the parent reaches. `no_data`: The query returned no rows. `too_many_variables`: The variable codes plus NAME and the label and record columns added for the dataset exceed the 50 columns the Census API accepts per request. `predicate_not_supported`: A key in predicates is not a variable in this dataset and year. `upstream_error`: Census API returned an error, was unreachable, or exceeded the shared 50-second upstream budget or the data request's 40-second ceiling within it. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Warning that the dataset declares filter dimensions the query left unset, naming each one alongside the label of the default the Census API applied to it. That default is an all-categories total on some dimensions and one ordinary category on others, so the label is what says which. Also carries the warning that a geography came back on more than one row, naming the column that separates the records and the values it took; the codes of a comma-separated geography_fips that no row came back for, with applicable ACS publication coverage guidance and variable rediscovery when switching datasets; the range of rows returned when offset or limit left some out, with the offset of the next page; the sibling tables a missing group, geography, or value may sit in, on dec/ddhca and dec/ddhcb tables that split the population groups between them; and any variable codes whose flags could not be checked because the request had no room left under the Census 50-column limit — a withheld value there reads as 0."
},
"dataset": {
"type": "string",
"description": "Dataset queried."
},
"totalRows": {
"type": "number",
"description": "Number of rows returned."
},
"truncated": {
"type": "boolean",
"description": "True when more matched rows remain after this page."
},
"nextOffset": {
"type": "number",
"description": "Offset for the next page, present only when more matched rows remain. Keep the other query inputs unchanged."
},
"totalCount": {
"type": "number",
"description": "Number of rows the query matched, before offset and limit were applied."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}census_compare_geographies — Compare Census Geographies
Compare one or more variables across multiple geographies at the same level — all counties in a state, all states nationally, or a named set of specific geographies — ranked on the value of one of them. Covers queries like "compare median income across WA counties" or "which states have the most people below the poverty line." A count ranks geographies by size, not by rate, so to rank a rate, rank a published percentage: S1701_C03_001E (percent below the poverty level, dataset acs/acs5/subject), DP03_0128PE (the same percentage, acs/acs5/profile), or DP04_0047PE (percent of occupied housing units that are renter-occupied, acs/acs5/profile). Profile and subject tables reach tracts but not block groups. Omit within to compare all geographies nationally at the level. Suppressed values are decoded to human-readable labels rather than passed through as raw negative sentinels. On the business datasets (cbp, ecnbasic, nonemp), pep/charv, dec/ddhca, dec/ddhcb, and acs/acs1/spp, use predicates to rank within one industry, size class, or population group — a comparison that omits one ranks on a default the Census API picks, which is an all-categories total on some dimensions and a single category on others. Each row names the defaults that were applied in applied_filters, and census_list_predicate_values enumerates the codes a dimension accepts. Some dec/ddhca and dec/ddhcb tables split the population groups between them, publishing each group at a geography in only one table of the family, so a ranking on one of them leaves out the geographies whose group sits in a sibling table — the notice names those tables. A dataset that publishes several records per geography cannot be ranked until one is pinned: pep/charv publishes an April estimates base and a July estimate, so a comparison that pins neither fails with ambiguous_rows rather than giving every geography two ranks — pass predicates {"MONTH": "7"} for the July estimate.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"variables",
"geography_level"
],
"properties": {
"year": {
"type": "number",
"description": "Vintage year (default: latest available for the dataset)."
},
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Maximum geographies per page (default: 50, max: 500). totalCount counts the matched set before paging; nextOffset reaches the next page."
},
"offset": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0,
"description": "Rows to skip in the sorted matched set (default: 0), not a rank. Equal numeric estimates share competition ranks and are ordered by GEOID. An offset at or past totalCount returns no rows."
},
"within": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^(\\*|\\d{1,2})$",
"description": "1 to 2 digits, zero-padded here to the 2 the Census stores, or \"*\"."
}
],
"description": "State FIPS to constrain results (e.g., \"53\" to compare counties or tracts within WA only). Omit to compare all geographies at the level nationally. Use census_resolve_geography to get state_fips. Pass \"*\" to span every state on the levels whose hierarchy lets \"*\" stand in for the state, such as county and place; tract, block group, and county subdivision need one state. Blank is treated as omitted."
},
"dataset": {
"type": "string",
"description": "Dataset to query (default: \"acs/acs5\"). Use census_list_datasets for valid values. Case is ignored, and a two-part code can be given by its last part alone — \"acs5\" is acs/acs5, \"pl\" is dec/pl. Three-part codes such as acs/acs5/profile must be given in full. The response echoes the resolved code."
},
"sort_by": {
"type": "string",
"description": "Variable code to rank on (default: the first code in variables), matched regardless of case like the variables. Must be one of the requested codes, or the call fails with sort_by_not_requested. Geographies rank on that code's own value, so a count ranks by size and only a published percentage such as S1701_C03_001E or DP03_0128PE ranks by rate."
},
"sort_dir": {
"enum": [
"asc",
"desc"
],
"type": "string",
"description": "Sort direction (default: \"desc\" — highest value first)."
},
"variables": {
"type": "array",
"items": {
"type": "string"
},
"description": "Variable codes to compare (e.g., [\"B19013_001E\", \"B19013_001M\"]); the ranking is on one of them, set by sort_by. Codes are matched regardless of case and sent in the dataset's own spelling, which keys each row — uppercase everywhere except the comparison profiles' significance columns (CP03_2024to2019_062SS). A code the dataset does not list is sent uppercased. At most 49 per call: the Census API accepts 50 columns per request and every query also sends NAME. On datasets where a label column is added for each filter dimension left unset, or record columns are added (cbp, ecnbasic, nonemp, pep/charv, dec/ddhca, dec/ddhcb, acs/acs1/spp), the maximum is lower, and too_many_variables states the exact number for the comparison. On ACS datasets, add the margin-of-error counterpart of a code (same code, E suffix swapped for M) for reliability context. The ACS comparison profiles (acs/acs5/cprofile, acs/acs1/cprofile) and the other dataset families (pep, dec, cbp, ecnbasic, nonemp) publish no margins of error."
},
"predicates": {
"type": "object",
"description": "Filter values keyed by variable code, applied to every geography in the comparison — e.g. {\"NAICS2017\": \"5112\"} to rank counties by their software-publisher establishment count in cbp. The business datasets (cbp, ecnbasic, nonemp), pep/charv, dec/ddhca, dec/ddhcb, and acs/acs1/spp declare filter dimensions such as industry (NAICS2017/NAICS2022), legal form (LFO), size class (EMPSZES/RCPSZES), tax status (TAXSTAT), operation type (TYPOP), sex (SEX), age (AGE), and population group (POPGROUP). Leaving one unset is not an error: the Census API substitutes its own default, which is the all-categories total on cbp NAICS2017 but a single population group on dec/ddhca and dec/ddhcb POPGROUP and a single sector on ecnbasic NAICS2022 — so a ranking can read like an overall one without being it. Every unset dimension is named in the response notice and its applied default is echoed per row in applied_filters. Keys are matched case-insensitively, and a blank value is treated as omitted. A value of \"*\" returns every geography once per category of that dimension, which a ranking cannot hold, so it fails with ambiguous_rows naming the dimension to pin — use census_query_data for a per-category breakdown. Code names vary by dataset and vintage — cbp 2023 uses NAICS2017 while nonemp 2023 uses NAICS2022 — so read them from the notice or from census_search_variables. Call census_list_predicate_values for the codes a dimension accepts; NAICS values are standard North American Industry Classification System codes at any depth (51 information, 5112 software publishers).",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"geographies": {
"type": "array",
"items": {
"type": "string"
},
"description": "Optional list of specific geographies to include; only these are returned. Prefer full GEOIDs — the level concatenated with its parents, e.g. \"53033\" for King County WA and \"06037\" for Los Angeles County CA — which are nationally unique and so work across states. Bare level codes (\"033\") are also accepted but match that code in every state unless within scopes them to one. A GEOID is easiest taken from the geography_geoid field of a census_query_data or census_compare_geographies row; from census_resolve_geography, concatenate state_fips, then county_fips when it is present, then fips_summary. Entries that match nothing, and bare codes that match more than one state, are named in the response notice."
},
"within_county": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^(\\*|\\d{1,3})$",
"description": "1 to 3 digits, zero-padded here to the 3 the Census stores, or \"*\"."
}
],
"description": "County FIPS to constrain tract or block-group comparisons to a single county within the state specified by within (e.g., \"033\" for King County). Required when geography_level is \"tract\" or \"block group\" and you want county-scoped results. census_resolve_geography returns this as county_fips. Pass \"*\" to span every county in the state, which is the only way a block-group comparison reaches a whole state; \"*\" works on the levels whose hierarchy lets it stand in for the county, such as tract and block group. Blank is treated as omitted."
},
"geography_level": {
"type": "string",
"description": "The level to compare across (e.g., \"state\", \"county\", \"tract\"). Use census_list_geographies to see valid values for the dataset."
}
},
"additionalProperties": false
}{
"type": "object",
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"rows",
"totalCount",
"truncated",
"sortVariable",
"dataset",
"year"
]
},
{
"required": [
"error"
]
}
],
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"rows": {
"type": "array",
"items": {
"type": "object",
"required": [
"geography_name",
"geography_fips",
"geography_geoid",
"variables",
"rank"
],
"properties": {
"rank": {
"type": "number",
"description": "Competition rank in the matched set before paging (1 = highest when sort_dir is desc). Equal numeric estimates share a rank, with gaps after ties: 1, 2, 2, 4. Nonnumeric rows follow every number with sequential ordinals; an entirely nonnumeric comparison retains Census return order."
},
"record": {
"type": "object",
"properties": {},
"description": "Which record the ranking is over, for a dataset that publishes more than one per geography — keyed by the column that separates them, each value carrying a code and a label (e.g. {\"MONTH\": {\"code\": \"7\", \"label\": \"July\"}}). Present on every row whenever the dataset publishes such a column, whether predicates pinned it or another predicate narrowed the result to one record per geography. A comparison that would put each geography on several rows fails with ambiguous_rows instead of ranking it, so a ranking that returned at all is a ranking of the single record named here. Absent on the datasets that publish one record per geography.",
"additionalProperties": {}
},
"variables": {
"type": "object",
"properties": {},
"description": "Map of variable code to value entry. Each key is a variable code from the variables input, in the dataset's spelling — uppercase except the comparison profiles' significance columns (CP03_2024to2019_062SS); each value has: estimate (number|null), moe (number|null, optional), label (string), suppressed (boolean), suppression_reason (string, optional), open_ended (true, optional), flag ({code, meaning}, optional), value (string, optional). An estimate of null means one of three things and the other fields say which: suppressed true is a number the Census withheld, a value field is a cell holding text rather than a number (GEO_ID returns \"0500000US53033\"; the older ACS profile vintages write not-applicable as \"(X)\" in a column that is a number elsewhere), and neither is a cell with nothing in it. suppression_reason carries the meaning the Census publishes for the sentinel or flag, and a suppressed value ranks after every number in either sort direction. On ACS, a margin of error the Census treats as zero (a controlled estimate) is moe 0. open_ended true marks an ACS median that falls in the lowest or highest interval of an open-ended distribution, so the estimate is that interval's boundary (250001 for \"250,000+\") — it ranks by that figure, so geographies sharing it are tied, and it appears only when the matching M code was requested. flag is the symbol a business dataset (cbp, ecnbasic, nonemp) published beside the value: a withholding flag comes with suppressed true, and so does a noise or data-quality band beside a 0, which is the range a range column such as EMP_N or RCPTOT_IMP publishes in place of a number; a quality note keeps the estimate. Text has no ordering, so sorting on a column of it leaves every row tied and ranked in the order the Census returned them, and the notice says so.",
"additionalProperties": {}
},
"scope_rank": {
"type": "number",
"description": "Rank among all fetched geographies before the geographies filter, using the same competition rule as rank. Present only with a nonempty geographies filter; scopeCount gives the size of that fetched set."
},
"geography_fips": {
"type": "string",
"description": "FIPS code for this geography at the compared level only, without its parents (e.g., \"033\" for King County). Pass back as the geography_fips parameter in census_query_data — alongside within as parent_fips — for follow-up variable queries."
},
"geography_name": {
"type": "string",
"description": "Human-readable geography name."
},
"applied_filters": {
"type": "object",
"properties": {},
"description": "Filter dimensions the comparison left unset, mapped to the label of the default the Census API applied (e.g. {\"POPGROUP\": \"European alone\"}). Present only on datasets that declare filter dimensions. The label is what tells an all-categories total apart from one ordinary category, so a ranking whose rows carry \"European alone\" ranks that group rather than total population. Set the dimension in predicates to choose it yourself.",
"additionalProperties": {}
},
"geography_geoid": {
"type": "string",
"description": "Full GEOID — the compared level concatenated with its parent levels (e.g., \"53033\" for King County, \"53033000101\" for a tract). Nationally unique, unlike geography_fips, so this is the value to pass back in the geographies filter."
}
},
"description": "One ranked geography row with variable values.",
"additionalProperties": false
},
"description": "Geographies sorted by the requested variable. Suppressed values are labeled."
},
"year": {
"type": "number",
"description": "Vintage year queried."
},
"error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"description": "JSON-RPC error code for this failure."
},
"data": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"examples": [
"dataset_not_found",
"missing_api_key",
"geography_not_supported",
"parent_required",
"parent_not_accepted",
"year_not_available",
"variable_not_found",
"too_many_variables",
"variables_unavailable",
"predicate_not_supported",
"sort_by_not_requested",
"ambiguous_rows",
"no_data",
"upstream_error"
],
"description": "Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset code is not recognized, even after case and shorthand resolution. `missing_api_key`: CENSUS_API_KEY is not configured or the key is invalid. `geography_not_supported`: The requested geography level does not exist in this dataset and year. `parent_required`: The geography level requires a parent FIPS but within, or within_county, was not provided, or within or within_county is \"*\" where the level's hierarchy does not let \"*\" stand in for that parent. For a level the dataset lists under several hierarchies, no hierarchy accepts the call and the error describes the one closest to accepting it, which can need a parent this tool has no input for. When that hierarchy also does not take a parent the call supplied, the error names that parent to drop as well. `parent_not_accepted`: within or within_county names a parent the geography level does not sit within — for a level listed under several hierarchies, one that dropping the parent reaches. `year_not_available`: The dataset does not serve the requested vintage year. `variable_not_found`: The Census API rejected a variable code as unknown for this dataset and year. It names only the first unknown code in a request. `too_many_variables`: The variable codes plus NAME and the label and record columns added for the dataset exceed the 50 columns the Census API accepts per request. `variables_unavailable`: The variable metadata endpoint returned an unparseable response for this dataset and year. `predicate_not_supported`: A key in predicates is not a variable in this dataset and year. `sort_by_not_requested`: sort_by names a code that is not among the requested variables, so no column exists to rank on. `ambiguous_rows`: The dataset publishes several records per geography and the comparison pinned none of them, so every geography would occupy several ranks with different values. `no_data`: No geographies were returned for the query, or no row matched any entry in the geographies list. `upstream_error`: Census API returned an error, was unreachable, or exceeded the shared 50-second upstream budget or the data request's 40-second ceiling within it. Other values are possible when a failure originates below the handler."
},
"recovery": {
"type": "object",
"required": [
"hint"
],
"properties": {
"hint": {
"type": "string"
}
},
"description": "Actionable next step for the caller.",
"additionalProperties": {}
},
"retryable": {
"type": "boolean",
"description": "Whether retrying may succeed."
}
},
"additionalProperties": {}
},
"message": {
"type": "string",
"description": "Human-readable description of what went wrong."
}
},
"description": "Present when the call failed. Absent on success.",
"additionalProperties": {}
},
"notice": {
"type": "string",
"description": "Guidance when results were truncated, when the sort column holds no number on any row (so the rows are in the order the Census returned them rather than ranked), when geographies entries matched no row, when a bare level code matched more than one state, or when the dataset declares filter dimensions the comparison left unset — how to narrow scope, raise the limit, correct the FIPS codes, or add the predicates that pin what the ranking covers. Unmatched geographies include applicable ACS publication coverage guidance and variable rediscovery when switching datasets. For an unset dimension it also quotes the label of the default the Census API applied, which is what says whether the ranking is on a total or on one category. On dec/ddhca and dec/ddhcb tables that split the population groups between them, it names the sibling tables a geography left out of the ranking may sit in. Also names any variable codes whose flags could not be checked because the request had no room left under the Census 50-column limit — a withheld value there reads as 0 and ranks as one."
},
"dataset": {
"type": "string",
"description": "Dataset queried."
},
"truncated": {
"type": "boolean",
"description": "True only when more matched rows remain after this page."
},
"nextOffset": {
"type": "number",
"description": "Row offset for the next page, present only when truncated is true. An offset counts rows rather than competition ranks."
},
"scopeCount": {
"type": "number",
"description": "Number of fetched geographies before the nonempty geographies filter; the denominator for scope_rank. Absent without that filter."
},
"totalCount": {
"type": "number",
"description": "Total geographies matched after the geographies filter, before offset and limit."
},
"sortVariable": {
"type": "string",
"description": "Variable code the rows are ranked on, in the dataset's spelling, as it keys each row's variables."
}
},
"additionalProperties": false
}{
"readOnlyHint": true,
"openWorldHint": false
}Prompts
0 advertised
Resources
1 advertised
census-guide
Census Bureau data through the census_* tools: choose the dataset and vintage a question needs, find variable codes for lay concepts (rent burden, poverty rate), reach geographies census_resolve_geography cannot name (New England towns, tribal areas), and read ACS margins of error before ranking places, comparing a tract with its county, or comparing years. Use before answering from census_query_data or census_compare_geographies numbers.
skill://census-guide/SKILL.mdio.modelcontextprotocol/skills
skill://{+path}90-day uptime
A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.
- 2026-11-07: 1 of 1 checks answered
30-day availability
Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.
- Successful checks
- 1 of 1 (100%)
- Average latency
- 896 ms
- 95th percentile latency
- 896 ms
Maintenance history
Public check and source-refresh events. Editorial and ownership records remain private.
- · probe · passed · 896 ms · metadata changed · 8 tool(s), 1 resource(s), 1 resource template(s), 0 prompt(s)
Connect from your client
Each snippet registers the same endpoint; pick the client you use.
Claude Code
claude mcp add --transport http census-mcp-server-caseyjhand https://census.caseyjhand.com/mcpCodex
codex mcp add census-mcp-server-caseyjhand --url https://census.caseyjhand.com/mcpCursor
{
"mcpServers": {
"census-mcp-server-caseyjhand": {
"url": "https://census.caseyjhand.com/mcp"
}
}
}Cline
{
"mcpServers": {
"census-mcp-server-caseyjhand": {
"type": "streamableHttp",
"url": "https://census.caseyjhand.com/mcp",
"disabled": false
}
}
}VS Code
{
"servers": {
"census-mcp-server-caseyjhand": {
"type": "http",
"url": "https://census.caseyjhand.com/mcp"
}
}
}Gemini CLI
gemini mcp add --transport http census-mcp-server-caseyjhand https://census.caseyjhand.com/mcpClaude Desktop
https://census.caseyjhand.com/mcpWindsurf
{
"mcpServers": {
"census-mcp-server-caseyjhand": {
"serverUrl": "https://census.caseyjhand.com/mcp"
}
}
}Let your agent find its tools
Find servers like census-mcp-server from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.