census-mcp-server

v0.1.10 pre-1.0

Query U.S. Census Bureau data, variables, and geography via MCP. STDIO or Streamable HTTP.

census.caseyjhand.com/mcp
claude mcp add --transport http census-mcp-server https://census.caseyjhand.com/mcp
codex mcp add census-mcp-server --url https://census.caseyjhand.com/mcp
{
  "mcpServers": {
    "census-mcp-server": {
      "url": "https://census.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http census-mcp-server https://census.caseyjhand.com/mcp
{
  "mcpServers": {
    "census-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://census.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "census-mcp-server": {
      "type": "http",
      "url": "https://census.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://census.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

census_list_datasets

Browse available Census Bureau datasets with their supported vintage years. Use as the starting point when the right dataset is unknown — ACS5, ACS1, population estimates, and decennial census serve different use cases. Pass the dataset_id value to the dataset parameter in other census tools.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_list_datasets",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "filter": {
      "description": "Keyword to filter datasets by name or description. Omit to list all datasets.",
      "type": "string"
    }
  },
  "additionalProperties": false
}
view source ↗

census_list_geographies

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_list_geographies",
    "arguments": {
      "dataset": "<dataset>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "dataset": {
      "type": "string",
      "description": "Dataset code (e.g., \"acs/acs5\", \"acs/acs1\"). Use census_list_datasets to discover valid values."
    },
    "year": {
      "description": "Vintage year. Defaults to the latest available year for the dataset.",
      "type": "number"
    }
  },
  "required": [
    "dataset"
  ],
  "additionalProperties": false
}
view source ↗

census_search_variables

Search Census variables by keyword across variable labels and concept groups. 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. Returns both estimate (E suffix) and margin-of-error (M suffix) codes so you can request both. When total_matches exceeds the limit, narrow the query to see more specific results.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_search_variables",
    "arguments": {
      "query": "<query>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Keyword to search (e.g., \"median household income\", \"poverty\", \"bachelor's degree\"). Multi-word queries search for all terms."
    },
    "dataset": {
      "description": "Dataset to search within (default: \"acs/acs5\"). Use census_list_datasets to discover options.",
      "type": "string"
    },
    "year": {
      "description": "Vintage year to search (default: latest available for the dataset).",
      "type": "number"
    },
    "limit": {
      "description": "Maximum results to return (default: 20, max: 100). Increase if total_matches greatly exceeds the limit.",
      "type": "number"
    }
  },
  "required": [
    "query"
  ],
  "additionalProperties": false
}
view source ↗

census_get_variable

Fetch full metadata for one or more Census variable codes — label, concept group, predicate type, 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. Returns estimate_code and moe_code sibling references where applicable so you can request both without a separate search.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_get_variable",
    "arguments": {
      "variables": "<variables>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "variables": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "One or more variable codes to look up (e.g., [\"B19013_001E\", \"B19013_001M\"]). Variable codes are case-sensitive."
    },
    "dataset": {
      "description": "Dataset the variables belong to (default: \"acs/acs5\"). Use census_list_datasets to discover valid values.",
      "type": "string"
    },
    "year": {
      "description": "Vintage year (default: latest available for the dataset).",
      "type": "number"
    }
  },
  "required": [
    "variables"
  ],
  "additionalProperties": false
}
view source ↗

census_resolve_geography

Resolve a place name or street address to Census FIPS identifiers (state, county, tract codes). Converts names like "King County, WA" or "Seattle, WA" to the FIPS 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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_resolve_geography",
    "arguments": {
      "name": "<name>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Place name (e.g., \"King County, WA\", \"Seattle, WA\", \"California\") or street address (e.g., \"1600 Pennsylvania Ave NW, Washington, DC 20500\"). Include the state abbreviation to disambiguate places with common names."
    },
    "geography_type": {
      "description": "Expected geography type to resolve to. Optional — auto-detected from the name when omitted (county if \"County\"/\"Borough\"/\"Parish\" appears, state for two-letter abbreviations).",
      "type": "string",
      "enum": [
        "state",
        "county",
        "place",
        "tract"
      ]
    }
  },
  "required": [
    "name"
  ],
  "additionalProperties": false
}
view source ↗

census_query_data

Query a Census dataset for one or more variables at a specific geography. Accepts FIPS codes for the target geography — use census_resolve_geography to convert place names to FIPS when needed. Labeled estimates and margin-of-error values are returned together. Suppression codes (geography too small, data not collected) are decoded into human-readable reasons rather than passed through as raw negative numbers. Pass geography_fips as "*" to return all geographies at the level within the parent.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_query_data",
    "arguments": {
      "variables": "<variables>",
      "geography_level": "<geography_level>",
      "geography_fips": "<geography_fips>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "variables": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Variable codes to retrieve (e.g., [\"B19013_001E\", \"B19013_001M\"]). Max 50 per request. Use census_search_variables to find codes. Include the MOE counterpart (swap E → M suffix) to get margin-of-error alongside each estimate."
    },
    "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."
    },
    "geography_fips": {
      "type": "string",
      "description": "FIPS code for the target geography (e.g., \"033\" for a county, \"*\" for all geographies at the level within the parent). Use census_resolve_geography to obtain this value — it is returned as fips_summary."
    },
    "parent_fips": {
      "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.",
      "type": "string"
    },
    "county_fips": {
      "description": "County FIPS code (3 digits) 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.",
      "type": "string"
    },
    "dataset": {
      "description": "Dataset to query (default: \"acs/acs5\"). Use census_list_datasets to discover valid values.",
      "type": "string"
    },
    "year": {
      "description": "Vintage year (default: latest available for the dataset).",
      "type": "number"
    }
  },
  "required": [
    "variables",
    "geography_level",
    "geography_fips"
  ],
  "additionalProperties": false
}
view source ↗

census_compare_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. Results are sorted and ranked. Covers queries like "rank states by poverty rate", "compare median income across WA counties", or "which census tracts in King County have the highest renter rate." 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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "census_compare_geographies",
    "arguments": {
      "variables": "<variables>",
      "geography_level": "<geography_level>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "variables": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Variable codes to compare (e.g., [\"B17001_002E\", \"B17001_001E\"]). Include MOE counterparts (M suffix) for reliability context."
    },
    "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."
    },
    "within": {
      "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.",
      "type": "string"
    },
    "within_county": {
      "description": "County FIPS (3 digits) 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.",
      "type": "string"
    },
    "geographies": {
      "description": "Optional list of specific geography FIPS codes to include. When provided, only these geographies are returned. Omit to return all geographies within the level. Use census_resolve_geography for each place name to get its FIPS.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "dataset": {
      "description": "Dataset to query (default: \"acs/acs5\"). Use census_list_datasets for valid values.",
      "type": "string"
    },
    "year": {
      "description": "Vintage year (default: latest available for the dataset).",
      "type": "number"
    },
    "sort_by": {
      "description": "Variable code to sort by (default: first variable in the list). Must be one of the requested variable codes.",
      "type": "string"
    },
    "sort_dir": {
      "description": "Sort direction (default: \"desc\" — highest value first).",
      "type": "string",
      "enum": [
        "asc",
        "desc"
      ]
    },
    "limit": {
      "description": "Maximum geographies to return (default: 50, max: 500). When results are truncated, total_count indicates how many matched.",
      "type": "number"
    }
  },
  "required": [
    "variables",
    "geography_level"
  ],
  "additionalProperties": false
}
view source ↗