Skip to main content
Glama

Search Census Variables

census_search_variables
Read-only

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; when totalMatches exceeds the limit, a more specific query reaches the rest — except past the limit of a table code, where a later variable's own code does.

Input Schema

NameRequiredDescriptionDefault
yearNoVintage year to search (default: latest available for the dataset).
limitNoMaximum results to return (default: 20, max: 100). Increase if totalMatches greatly exceeds the limit.
queryYesKeywords 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").
datasetNoDataset 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.

Output Schema

NameRequiredDescriptionDefault
capNoThe limit that was applied.
yearNoVintage year that was searched.
errorNoPresent when the call failed. Absent on success.
shownNoNumber of variables returned after the limit.
noticeNoGuidance when no variables matched, when no variable contained every query word and the results hold only some of them, or when results were truncated — suggests other keywords, a narrower query, or a higher limit. For a code the dataset does not publish, it names the sibling dataset confirmed to hold it, or census_get_variable for an attribute column (annotation, flag, label, or significance); for a table cut at the limit, the last code shown.
datasetNoDataset that was searched.
truncatedNoTrue when totalMatches exceeded the limit and results were cut off.
variablesNoMatching 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.
totalMatchesNoVariables 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.
effectiveQueryNoQuery as the server parsed it.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changed
    • changedInput schema / properties / query / description
      Previous value: -"Keywords to search (e.g., \"median household income\", \"poverty\", \"bachelor's degree\"). 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."New value: +"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\")."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"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. Other values are possible when a failure originates below the handler."New value: +"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."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "dataset_not_found",
      -  "year_not_available",
      -  "variables_unavailable"
      -]New value: +[
      +  "dataset_not_found",
      +  "year_not_available",
      +  "variables_unavailable",
      +  "upstream_error"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when no variables matched, when no variable contained every query word and the results hold only some of them, or when results were truncated — suggests other keywords, a narrower query, or a higher limit."New value: +"Guidance when no variables matched, when no variable contained every query word and the results hold only some of them, or when results were truncated — suggests other keywords, a narrower query, or a higher limit. For a code the dataset does not publish, it names the sibling dataset confirmed to hold it, or census_get_variable for an attribute column (annotation, flag, label, or significance); for a table cut at the limit, the last code shown."
    • changedOutput schema / properties / totalMatches / description
      Previous value: -"Variables that contain every query word, before the limit was applied — or, when none does, the variables that contain the most words."New value: +"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."
    • changedOutput schema / properties / variables / description
      Previous value: -"Matching variables, best first: 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."New value: +"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."
  2. Changed10 schema fields changed
    • changedInput schema / properties / dataset / description
      Previous value: -"Dataset to search within (default: \"acs/acs5\"). Use census_list_datasets to discover options."New value: +"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."
    • changedInput schema / properties / query / description
      Previous value: -"Keyword to search (e.g., \"median household income\", \"poverty\", \"bachelor's degree\"). Multi-word queries search for all terms."New value: +"Keywords to search (e.g., \"median household income\", \"poverty\", \"bachelor's degree\"). 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."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `dataset_not_found`: Dataset code is not recognized. `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. Other values are possible when a failure originates below the handler."New value: +"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. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / notice / description
      Previous value: -"Guidance when no variables matched, or when results were truncated — suggests broader keywords, a narrower query, or a higher limit."New value: +"Guidance when no variables matched, when no variable contained every query word and the results hold only some of them, or when results were truncated — suggests other keywords, a narrower query, or a higher limit."
    • changedOutput schema / properties / totalMatches / description
      Previous value: -"Total variables matching the query before the limit was applied."New value: +"Variables that contain every query word, before the limit was applied — or, when none does, the variables that contain the most words."
    • changedOutput schema / properties / variables / description
      Previous value: -"Matching variables sorted by relevance. On ACS datasets, codes ending in E are estimates and M are their margins of error; on other datasets the suffix carries no such meaning."New value: +"Matching variables, best first: 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."
    • changedOutput schema / properties / variables / items / properties / concept / description
      Previous value: -"Concept group the variable belongs to (e.g., \"MEDIAN HOUSEHOLD INCOME\")."New value: +"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."
    • changedOutput schema / properties / variables / items / properties / estimate_code / description
      Previous value: -"Corresponding estimate variable code when this is a margin-of-error variable. ACS datasets only — no other family publishes margins of error."New value: +"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."
    • changedOutput schema / properties / variables / items / properties / moe_code / description
      Previous value: -"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 — on other families an E-final code is an ordinary code with no margin-of-error sibling, so the field is absent."New value: +"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."
    • changedOutput schema / properties / variables / items / required
      Previous value: -[
      -  "variable_code",
      -  "label",
      -  "concept",
      -  "predicate_type"
      -]New value: +[
      +  "variable_code",
      +  "label",
      +  "predicate_type"
      +]
  3. Changed5 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum results to return (default: 20, max: 100). Increase if total_matches greatly exceeds the limit."New value: +"Maximum results to return (default: 20, max: 100). Increase if totalMatches greatly exceeds the limit."
    • addedInput schema / properties / limit / maximum
      Added value: +100
    • addedInput schema / properties / limit / minimum
      Added value: +1
    • changedInput schema / properties / limit / type
      Previous value: -"number"New value: +"integer"
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when total_matches exceeded the limit and results were cut off."New value: +"True when totalMatches exceeded the limit and results were cut off."
  4. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnlyHint/openWorldHint annotations: it discloses the ACS estimate/margin-of-error suffix behavior, that comparison profiles and other dataset families publish no MOE, that unpublished codes return a notice naming the owning dataset, and the ordering rules that put exact code matches ahead of keyword matches. This is exactly the behavioral context the annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded and nearly every clause carries information, but it is one dense paragraph and the closing clause ("except past the limit of a table code, where a later variable's own code does") is syntactically hard to parse. Slightly tighter phrasing would improve scanability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, yet the description still summarizes what comes back (codes with human-readable labels, E/M pairs). Combined with the dataset-resolution notes and edge-case handling, an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantics: a query may be a single code or table ID, every word must match a whole word, and the limit interacts with table codes in a specific way. It meaningfully enriches the query and limit parameters rather than restating them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (search Census variables by keyword or code) and immediately frames the job-to-be-done: going from a concept like "median household income" to the code B19013_001E needed for data queries. It also carves out the code-lookup mode and predicate-code discovery, so an agent can distinguish this from the sibling lookup tools without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage contexts — concept-to-code discovery, single code/table lookup, and finding predicate codes like NAICS2017 in cbp — plus the narrowing heuristic ("adding a word narrows the results") and what to do when totalMatches exceeds the limit. It never names an alternative tool (e.g., census_get_variable) or states when not to use this one, so it stops short of explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.