Skip to main content
Glama

Search People

openstates_search_people
Read-onlyIdempotent

Search state legislators and officials by name, jurisdiction, chamber, or district, or fetch specific people by OCD person ID. Party is reported on every result but cannot be filtered on — narrow by party after the call. Either jurisdiction or id is required — a search spanning all 56 jurisdictions exceeds the upstream timeout, including a name-only one, so scope every call to a single state or to specific person IDs. Use openstates_list_jurisdictions to pick a jurisdiction, or openstates_get_legislators_by_location when you have coordinates but no state. id takes the person IDs that openstates_get_bill sponsorships and openstates_get_committee memberships hand back, and resolves any number of them in one call. Supports name substring matching (case-insensitive). org_classification targets a role type: "upper" for Senate, "lower" for House/Assembly, "executive" for governors and executive officials, and "legislature" for every legislator — both chambers merged into one paginated set (all upper members, then all lower), which excludes executive-branch officials. Omitting org_classification is not the same as "legislature": it returns every officeholder, executive officials included. include=offices adds phone, fax, and address. include=links adds website and social links.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idNoOCD person IDs (e.g., "ocd-person/9eddb3cd-868e-42ba-831a-b415fd7ed445"). Required unless jurisdiction is provided — it returns exactly these people, so it scopes the call on its own and needs no jurisdiction alongside it. Resolves the IDs that openstates_search_people results, openstates_get_bill sponsorships[].person.id, and openstates_get_committee memberships[].person_id hand back — any number of them in one call, subject to per_page. An ID Open States does not know matches nothing rather than failing, as does an ID paired with a jurisdiction that person does not belong to.
nameNoName or partial name to match (case-insensitive substring). Narrows within the jurisdiction; it does not substitute for one.
pageNoPage number (1-indexed).
includeNoRelated data to inline. "offices" includes phone, fax, and address. "links" includes website and social links. "other_names" includes alternate/former names, "other_identifiers" cross-system IDs, and "sources" the provenance URLs behind the record.
districtNoDistrict label (e.g., "1", "37", "At-Large"). Formats vary by state.
per_pageNoResults per page. Maximum 20.
jurisdictionNoState name, abbreviation, or OCD-ID. Required unless id is provided — an all-states search exceeds the upstream timeout, so every call must be scoped to a single jurisdiction or to specific person IDs.
org_classificationNoFilter by role type. "upper" = Senate, "lower" = House/Assembly, "executive" = governors and executive officials, "legislature" = every legislator (both chambers merged into one paginated set, all upper members then all lower, excluding executive officials). Omitting this filter returns every officeholder including executive ones — it is not equivalent to "legislature".

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageNoCurrent page returned.
errorNoPresent when the call failed. Absent on success.
noticeNoRecovery hint when results are empty. Absent when results are returned.
maxPageNoTotal pages available.
resultsNoLegislators matching the search criteria.
paginationNoPagination metadata.
totalCountNoTotal legislators matching the query across all pages.
appliedFiltersNoFilters applied to this query as the server received them, for agent self-verification of zero or unexpected results.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / properties / results / items / properties / current_role / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "district": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "District label or null when undistricted."
      -      },
      -      "division_id": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "OCD division the district maps to (e.g., \"ocd-division/country:us/state:wa/sldu:37\"). Null when undistricted, absent when upstream omits it."
      -      },
      -      "org_classification": {
      -        "description": "Chamber classification (e.g., \"upper\", \"lower\").",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "Role title (e.g., \"Senator\", \"Representative\").",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "title",
      -      "org_classification",
      -      "district"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "district": {
      +        "description": "District label or null when undistricted.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "division_id": {
      +        "description": "OCD division the district maps to (e.g., \"ocd-division/country:us/state:wa/sldu:37\"). Null when undistricted, absent when upstream omits it.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "org_classification": {
      +        "description": "Chamber classification (e.g., \"upper\", \"lower\").",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "Role title (e.g., \"Senator\", \"Representative\").",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "title",
      +      "org_classification",
      +      "district"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
  2. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "results",
      +      "pagination",
      +      "totalCount",
      +      "page",
      +      "maxPage",
      +      "appliedFilters"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `upstream_timeout`: Open States did not answer within the per-request timeout — the query is too broad. `invalid_page`: Open States rejected the request as not found — page is past the last page for this query. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "upstream_timeout",
      +            "invalid_page"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "results",
      -  "pagination",
      -  "totalCount",
      -  "page",
      -  "maxPage",
      -  "appliedFilters"
      -]
  3. Changed10 schema fields changed
    • addedInput schema / properties / id
      Added value: +{
      +  "description": "OCD person IDs (e.g., \"ocd-person/9eddb3cd-868e-42ba-831a-b415fd7ed445\"). Required unless jurisdiction is provided — it returns exactly these people, so it scopes the call on its own and needs no jurisdiction alongside it. Resolves the IDs that openstates_search_people results, openstates_get_bill sponsorships[].person.id, and openstates_get_committee memberships[].person_id hand back — any number of them in one call, subject to per_page. An ID Open States does not know matches nothing rather than failing, as does an ID paired with a jurisdiction that person does not belong to.",
      +  "items": {
      +    "minLength": 1,
      +    "type": "string"
      +  },
      +  "minItems": 1,
      +  "type": "array"
      +}
    • changedInput schema / properties / jurisdiction / description
      Previous value: -"State name, abbreviation, or OCD-ID. Required — an all-states search exceeds the upstream timeout, so every call must be scoped to a single jurisdiction."New value: +"State name, abbreviation, or OCD-ID. Required unless id is provided — an all-states search exceeds the upstream timeout, so every call must be scoped to a single jurisdiction or to specific person IDs."
    • removedInput schema / required
      Removed value: -[
      -  "jurisdiction"
      -]
    • addedOutput schema / properties / appliedFilters / properties / id
      Added value: +{
      +  "description": "Person IDs filtered on, as received. Absent when none were supplied.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / results / items / properties / family_name / description
      Previous value: -"Family (last) name."New value: +"Family (last) name. Empty string when Open States recorded none."
    • changedOutput schema / properties / results / items / properties / given_name / description
      Previous value: -"Given (first) name."New value: +"Given (first) name. Empty string when Open States recorded none."
    • changedOutput schema / properties / results / items / properties / links / items / properties / note / description
      Previous value: -"Link description (e.g., \"website\", \"twitter\")."New value: +"Link description (e.g., \"website\", \"twitter\"). Empty string when Open States recorded no description — common on person links."
    • changedOutput schema / properties / results / items / properties / openstates_url / description
      Previous value: -"Open States profile URL."New value: +"Open States profile URL. Empty string when Open States recorded none."
    • changedOutput schema / properties / results / items / properties / other_names / items / properties / note / description
      Previous value: -"Note describing the alternate name."New value: +"Note describing the alternate name. Empty string when Open States recorded no note."
    • changedOutput schema / properties / results / items / properties / sources / items / properties / note / description
      Previous value: -"Source note."New value: +"Source note. Empty string when Open States recorded no note."
  4. Changed3 schema fields changed
    • changedInput schema / properties / jurisdiction / description
      Previous value: -"State name, abbreviation, or OCD-ID. Required — an all-states search exceeds the upstream timeout, so omitting it is rejected before any request is issued."New value: +"State name, abbreviation, or OCD-ID. Required — an all-states search exceeds the upstream timeout, so every call must be scoped to a single jurisdiction."
    • addedInput schema / properties / jurisdiction / minLength
      Added value: +1
    • addedInput schema / required
      Added value: +[
      +  "jurisdiction"
      +]
  5. Changed4 schema fields changed
    • changedInput schema / properties / jurisdiction / description
      Previous value: -"State name, abbreviation, or OCD-ID. Omitting searches across all states."New value: +"State name, abbreviation, or OCD-ID. Required — an all-states search exceeds the upstream timeout, so omitting it is rejected before any request is issued."
    • changedInput schema / properties / name / description
      Previous value: -"Name or partial name to match (case-insensitive substring)."New value: +"Name or partial name to match (case-insensitive substring). Narrows within the jurisdiction; it does not substitute for one."
    • changedOutput schema / properties / results / items / properties / current_role / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "district": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "description": "District label or null when undistricted."
      -      },
      -      "org_classification": {
      -        "description": "Chamber classification (e.g., \"upper\", \"lower\").",
      -        "type": "string"
      -      },
      -      "title": {
      -        "description": "Role title (e.g., \"Senator\", \"Representative\").",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "title",
      -      "org_classification",
      -      "district"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "district": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "District label or null when undistricted."
      +      },
      +      "division_id": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ],
      +        "description": "OCD division the district maps to (e.g., \"ocd-division/country:us/state:wa/sldu:37\"). Null when undistricted, absent when upstream omits it."
      +      },
      +      "org_classification": {
      +        "description": "Chamber classification (e.g., \"upper\", \"lower\").",
      +        "type": "string"
      +      },
      +      "title": {
      +        "description": "Role title (e.g., \"Senator\", \"Representative\").",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "title",
      +      "org_classification",
      +      "district"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedOutput schema / properties / results / items / properties / image
      Added value: +{
      +  "description": "Official headshot URL. Absent when no photo is published.",
      +  "type": "string"
      +}
  6. Changed4 schema fields changed
    • changedInput schema / properties / include / description
      Previous value: -"Related data to inline. \"offices\" includes phone, fax, and address. \"links\" includes website and social links."New value: +"Related data to inline. \"offices\" includes phone, fax, and address. \"links\" includes website and social links. \"other_names\" includes alternate/former names, \"other_identifiers\" cross-system IDs, and \"sources\" the provenance URLs behind the record."
    • addedOutput schema / properties / results / items / properties / other_identifiers
      Added value: +{
      +  "description": "Cross-system identifiers when include=other_identifiers is requested.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "Alternate identifier record.",
      +    "properties": {
      +      "identifier": {
      +        "description": "Alternate identifier.",
      +        "type": "string"
      +      },
      +      "scheme": {
      +        "description": "Identifier scheme (the issuing system).",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "identifier",
      +      "scheme"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / results / items / properties / other_names
      Added value: +{
      +  "description": "Alternate/former names when include=other_names is requested.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "Alternate name record.",
      +    "properties": {
      +      "name": {
      +        "description": "Alternate or former name.",
      +        "type": "string"
      +      },
      +      "note": {
      +        "description": "Note describing the alternate name.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "name",
      +      "note"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / results / items / properties / sources
      Added value: +{
      +  "description": "Provenance sources when include=sources is requested.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "Source record.",
      +    "properties": {
      +      "note": {
      +        "description": "Source note.",
      +        "type": "string"
      +      },
      +      "url": {
      +        "description": "Source URL.",
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "url",
      +      "note"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  7. Changed1 schema field changed
    • changedInput schema / properties / org_classification / description
      Previous value: -"Filter by role type. \"upper\" = Senate, \"lower\" = House/Assembly, \"legislature\" = all legislators, \"executive\" = governors and executive officials."New value: +"Filter by role type. \"upper\" = Senate, \"lower\" = House/Assembly, \"executive\" = governors and executive officials, \"legislature\" = every legislator (both chambers merged into one paginated set, all upper members then all lower, excluding executive officials). Omitting this filter returns every officeholder including executive ones — it is not equivalent to \"legislature\"."
  8. Changed2 schema fields changed
    • addedOutput schema / properties / appliedFilters
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Filters applied to this query as the server received them, for agent self-verification of zero or unexpected results.",
      +  "properties": {
      +    "district": {
      +      "description": "District filter as received.",
      +      "type": "string"
      +    },
      +    "jurisdiction": {
      +      "description": "Jurisdiction filter as received.",
      +      "type": "string"
      +    },
      +    "name": {
      +      "description": "Name filter as received.",
      +      "type": "string"
      +    },
      +    "org_classification": {
      +      "description": "Role-type filter as received.",
      +      "type": "string"
      +    },
      +    "page": {
      +      "description": "Page number requested.",
      +      "type": "number"
      +    },
      +    "per_page": {
      +      "description": "Results per page requested.",
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "page",
      +    "per_page"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "results",
      -  "pagination",
      -  "totalCount",
      -  "page",
      -  "maxPage"
      -]New value: +[
      +  "results",
      +  "pagination",
      +  "totalCount",
      +  "page",
      +  "maxPage",
      +  "appliedFilters"
      +]
  9. Changed3 schema fields changed
    • addedOutput schema / properties / totalCount
      Added value: +{
      +  "description": "Total legislators matching the query across all pages.",
      +  "type": "number"
      +}
    • removedOutput schema / properties / totalItems
      Removed value: -{
      -  "description": "Total legislators matching the query across all pages.",
      -  "type": "number"
      -}
    • changedOutput schema / required
      Previous value: -[
      -  "results",
      -  "pagination",
      -  "totalItems",
      -  "page",
      -  "maxPage"
      -]New value: +[
      +  "results",
      +  "pagination",
      +  "totalCount",
      +  "page",
      +  "maxPage"
      +]
  10. Changed6 schema fields changed
    • addedOutput schema / properties / maxPage
      Added value: +{
      +  "description": "Total pages available.",
      +  "type": "number"
      +}
    • removedOutput schema / properties / message
      Removed value: -{
      -  "description": "Recovery hint when results are empty. Absent when results are returned.",
      -  "type": "string"
      -}
    • addedOutput schema / properties / notice
      Added value: +{
      +  "description": "Recovery hint when results are empty. Absent when results are returned.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / page
      Added value: +{
      +  "description": "Current page returned.",
      +  "type": "number"
      +}
    • addedOutput schema / properties / totalItems
      Added value: +{
      +  "description": "Total legislators matching the query across all pages.",
      +  "type": "number"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "results",
      -  "pagination"
      -]New value: +[
      +  "results",
      +  "pagination",
      +  "totalItems",
      +  "page",
      +  "maxPage"
      +]
  11. First observed

TDQS

A5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, openWorldHint, and idempotentHint. The description adds valuable behavior beyond those: the upstream timeout on unscoped searches, unknown IDs matching nothing rather than failing, the pagination ordering for 'legislature', and the fact that omitting org_classification includes executive officials. No contradiction with annotations.

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

Conciseness5/5

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

The description is dense but every clause earns its place. It front-loads the core purpose, then the critical timeout constraint, then alternatives, then parameter-specific semantics. No filler or redundancy despite covering a complex 8-parameter tool.

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?

Given 8 parameters, an output schema, and rich annotations, the description is complete enough for an agent to select and invoke the tool correctly. It covers required scoping, alternatives, parameter semantics, pagination ordering, and include options without needing to explain return values since an output schema exists.

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

Parameters5/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 substantial meaning beyond the schema: the jurisdiction-or-id requirement, how IDs from bill sponsorships and committee memberships can be resolved in one call, the case-insensitive substring behavior for name, and the nuanced semantics of omitting org_classification. This materially helps an agent choose parameter combinations.

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?

The first sentence states a specific verb and resource ('Search state legislators and officials by name, jurisdiction, chamber, or district') and adds the alternative fetch-by-ID mode. It clearly differentiates this tool from related siblings by naming openstates_list_jurisdictions and openstates_get_legislators_by_location as alternatives for different inputs.

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance: either jurisdiction or id is required, all-states searches time out, and it references the exact sibling tools to use instead in specific situations. It also clarifies that party cannot be filtered server-side and explains the distinction between omitting org_classification and using 'legislature'.

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.