@cyanheads/openstates-mcp-server

v0.1.7 pre-1.0

Search bills, legislators, committees, and events across all 50 US states, DC, and Puerto Rico via MCP. STDIO or Streamable HTTP.

@cyanheads/openstates-mcp-server
claude mcp add --transport http openstates-mcp-server https://openstates.caseyjhand.com/mcp
codex mcp add openstates-mcp-server --url https://openstates.caseyjhand.com/mcp
{
  "mcpServers": {
    "openstates-mcp-server": {
      "url": "https://openstates.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http openstates-mcp-server https://openstates.caseyjhand.com/mcp
{
  "mcpServers": {
    "openstates-mcp-server": {
      "command": "bunx",
      "args": [
        "@cyanheads/openstates-mcp-server@latest"
      ]
    }
  }
}
{
  "mcpServers": {
    "openstates-mcp-server": {
      "type": "http",
      "url": "https://openstates.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://openstates.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

10

openstates_search_bills

open-world

Search state legislative bills across all covered US jurisdictions. Supports full-text search, jurisdiction/session filtering, subject tags, sponsor lookups, and sort order. Either jurisdiction or q (full-text) is required — combining both narrows results. include=sponsorships,actions returns sponsor and action history inline. sort=latest_action_desc surfaces bills currently moving. openstates_get_jurisdiction with include=legislative_sessions returns valid session identifiers for session filtering.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_search_bills",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "jurisdiction": {
      "description": "State name, two-letter abbreviation, or OCD-ID (e.g., \"Washington\", \"wa\", or \"ocd-jurisdiction/country:us/state:wa/government\"). Required unless q is provided.",
      "type": "string"
    },
    "q": {
      "description": "Full-text search across bill titles, abstracts, and text. Required unless jurisdiction is provided. Combining with jurisdiction is recommended for precision.",
      "type": "string"
    },
    "session": {
      "description": "Session identifier (e.g., \"2025\", \"2025-2026\", \"2025rs\"). Use openstates_get_jurisdiction with include=legislative_sessions to discover valid values. Omit to search across all sessions.",
      "type": "string"
    },
    "chamber": {
      "description": "Filter by originating chamber. \"upper\" = Senate, \"lower\" = House/Assembly.",
      "type": "string",
      "enum": [
        "upper",
        "lower"
      ]
    },
    "classification": {
      "description": "Bill classification: \"bill\", \"resolution\", \"constitutional amendment\", etc.",
      "type": "string"
    },
    "subject": {
      "description": "Filter to bills tagged with one or more subject categories.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "sponsor": {
      "description": "Filter by sponsor name or OCD person ID.",
      "type": "string"
    },
    "sponsor_classification": {
      "description": "Filter sponsor type: \"primary\", \"cosponsor\".",
      "type": "string"
    },
    "sort": {
      "default": "updated_desc",
      "description": "Sort order. Use \"latest_action_desc\" for bills currently moving through the legislature.",
      "type": "string",
      "enum": [
        "updated_asc",
        "updated_desc",
        "first_action_asc",
        "first_action_desc",
        "latest_action_asc",
        "latest_action_desc"
      ]
    },
    "action_since": {
      "description": "ISO 8601 date — only return bills with an action after this date.",
      "type": "string"
    },
    "updated_since": {
      "description": "ISO 8601 date — only return bills updated after this date.",
      "type": "string"
    },
    "include": {
      "description": "Related data to inline. \"sponsorships\" and \"actions\" cover most research needs without a separate openstates_get_bill call. \"votes\" adds full vote tallies and per-legislator positions.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "sponsorships",
          "abstracts",
          "other_titles",
          "other_identifiers",
          "actions",
          "sources",
          "documents",
          "versions",
          "votes",
          "related_bills"
        ]
      }
    },
    "page": {
      "default": 1,
      "description": "Page number (1-indexed).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "per_page": {
      "default": 10,
      "description": "Results per page. Maximum 20. Default 10.",
      "type": "integer",
      "minimum": 1,
      "maximum": 20
    }
  },
  "required": [
    "sort",
    "page",
    "per_page"
  ],
  "additionalProperties": false
}
view source ↗

openstates_get_bill

open-world

Fetch full detail for a specific state bill. Accepts either the three-part path (jurisdiction + session + bill_id) or a direct OCD bill ID (openstates_id from search results). Use include to request votes, actions, sponsorships, documents, and versions in one call rather than searching again. include=votes returns the full vote tally and per-legislator positions. include=actions returns the complete action history. Prefer openstates_id when available to avoid session identifier lookup.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_get_bill",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "openstates_id": {
      "description": "OCD bill ID from openstates_search_bills results (e.g., \"ocd-bill/...\"). Preferred over the three-part path when available.",
      "type": "string"
    },
    "jurisdiction": {
      "description": "State name, abbreviation, or OCD-ID. Required when using path-based lookup with session + bill_id.",
      "type": "string"
    },
    "session": {
      "description": "Session identifier. Required with jurisdiction + bill_id.",
      "type": "string"
    },
    "bill_id": {
      "description": "Bill identifier as used by the legislature (e.g., \"HB 1000\", \"SB 42\"). Required with jurisdiction + session.",
      "type": "string"
    },
    "include": {
      "description": "Related data to inline. \"sponsorships\", \"actions\", \"votes\" are most commonly needed. \"versions\" and \"documents\" provide links to bill text and fiscal notes.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "sponsorships",
          "abstracts",
          "other_titles",
          "other_identifiers",
          "actions",
          "sources",
          "documents",
          "versions",
          "votes",
          "related_bills"
        ]
      }
    }
  },
  "additionalProperties": false
}
view source ↗

openstates_search_people

open-world

Search state legislators and officials by name, jurisdiction, chamber, district, or party. Supports name substring matching (case-insensitive). org_classification targets a specific chamber: "upper" for Senate, "lower" for House/Assembly, "legislature" for all legislators, "executive" for governors and executive officials. include=offices adds phone, fax, and address. include=links adds website and social links. Omitting jurisdiction searches across all states and may return a large result set.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_search_people",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "jurisdiction": {
      "description": "State name, abbreviation, or OCD-ID. Omitting searches across all states.",
      "type": "string"
    },
    "name": {
      "description": "Name or partial name to match (case-insensitive substring).",
      "type": "string"
    },
    "org_classification": {
      "description": "Filter by role type. \"upper\" = Senate, \"lower\" = House/Assembly, \"legislature\" = all legislators, \"executive\" = governors and executive officials.",
      "type": "string",
      "enum": [
        "legislature",
        "executive",
        "lower",
        "upper",
        "government"
      ]
    },
    "district": {
      "description": "District label (e.g., \"1\", \"37\", \"At-Large\"). Formats vary by state.",
      "type": "string"
    },
    "include": {
      "description": "Related data to inline. \"offices\" includes phone, fax, and address. \"links\" includes website and social links.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "other_names",
          "other_identifiers",
          "links",
          "sources",
          "offices"
        ]
      }
    },
    "page": {
      "default": 1,
      "description": "Page number (1-indexed).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "per_page": {
      "default": 10,
      "description": "Results per page. Maximum 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 20
    }
  },
  "required": [
    "page",
    "per_page"
  ],
  "additionalProperties": false
}
view source ↗

openstates_get_legislators_by_location

open-world

Find all state legislators representing a geographic coordinate. Pass latitude and longitude to get state senators and representatives (and potentially governor/executive officials) for that location. Useful for constituent-to-representative matching, address-based policy research, and electoral boundary analysis. This server does not geocode addresses — the caller must provide decimal-degree coordinates. Use include=offices to get contact information alongside the legislator list.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_get_legislators_by_location",
    "arguments": {
      "latitude": "<latitude>",
      "longitude": "<longitude>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "latitude": {
      "type": "number",
      "description": "Latitude in decimal degrees (e.g., 47.6062 for Seattle, WA)."
    },
    "longitude": {
      "type": "number",
      "description": "Longitude in decimal degrees (e.g., -122.3321 for Seattle, WA)."
    },
    "include": {
      "description": "Related data to inline. \"offices\" includes phone, fax, and address.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "other_names",
          "other_identifiers",
          "links",
          "sources",
          "offices"
        ]
      }
    }
  },
  "required": [
    "latitude",
    "longitude"
  ],
  "additionalProperties": false
}
view source ↗

openstates_search_committees

open-world

List committees for a jurisdiction. Experimental — Open States is actively working to restore committee support and not all states have data. Use chamber to scope to upper (senate) or lower (house) committees. Use classification=subcommittee to find subcommittees of a parent. Use include=memberships to get the full roster with member roles. The coverage_note field in the output will always note the experimental coverage limitations.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_search_committees",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "jurisdiction": {
      "description": "State name, abbreviation, or OCD-ID. Omitting searches across all states.",
      "type": "string"
    },
    "classification": {
      "description": "Filter to parent committees or subcommittees only. Omit for all.",
      "type": "string",
      "enum": [
        "committee",
        "subcommittee"
      ]
    },
    "chamber": {
      "description": "Filter by chamber. \"upper\" = Senate, \"lower\" = House/Assembly.",
      "type": "string",
      "enum": [
        "upper",
        "lower"
      ]
    },
    "parent": {
      "description": "OCD organization ID of a parent committee to retrieve its subcommittees.",
      "type": "string"
    },
    "include": {
      "description": "Related data to inline. \"memberships\" includes the full roster with member roles.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "memberships",
          "links",
          "sources"
        ]
      }
    },
    "page": {
      "default": 1,
      "description": "Page number (1-indexed).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "per_page": {
      "default": 10,
      "description": "Results per page. Maximum 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 20
    }
  },
  "required": [
    "page",
    "per_page"
  ],
  "additionalProperties": false
}
view source ↗

openstates_get_committee

open-world

Fetch committee detail by OCD organization ID. Returns name, classification, and membership roster when include=memberships is requested. Experimental — not all states have committee data in Open States. Obtain the committee_id from openstates_search_committees.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_get_committee",
    "arguments": {
      "committee_id": "<committee_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "committee_id": {
      "type": "string",
      "minLength": 1,
      "description": "OCD organization ID (from openstates_search_committees results)."
    },
    "include": {
      "description": "Related data to inline. \"memberships\" includes the full roster with member roles.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "memberships",
          "links",
          "sources"
        ]
      }
    }
  },
  "required": [
    "committee_id"
  ],
  "additionalProperties": false
}
view source ↗

openstates_search_events

open-world

Search hearings, floor sessions, and committee meetings. Experimental — most states do not publish event data to Open States. Use after and before to scope to a date range. Set require_bills=true to filter to events with bills on the agenda, which is the most useful filter for tracking legislation through committee. Use include=agenda,participants for full meeting context. Empty results often indicate the state lacks event data rather than no events occurring.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_search_events",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "jurisdiction": {
      "description": "State name, abbreviation, or OCD-ID. Omitting searches across all states.",
      "type": "string"
    },
    "after": {
      "description": "ISO 8601 datetime — events starting after this time. Use to find upcoming hearings.",
      "type": "string"
    },
    "before": {
      "description": "ISO 8601 datetime — events starting before this time.",
      "type": "string"
    },
    "require_bills": {
      "default": false,
      "description": "When true, only return events with at least one bill on the agenda. Most useful for tracking legislation through committee.",
      "type": "boolean"
    },
    "include": {
      "description": "Related data to inline. \"agenda\" includes the meeting agenda with bill references. \"participants\" includes the committee or chamber hosting the event.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "links",
          "sources",
          "media",
          "documents",
          "participants",
          "agenda"
        ]
      }
    },
    "page": {
      "default": 1,
      "description": "Page number (1-indexed).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "per_page": {
      "default": 10,
      "description": "Results per page. Maximum 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 20
    }
  },
  "required": [
    "require_bills",
    "page",
    "per_page"
  ],
  "additionalProperties": false
}
view source ↗

openstates_get_event

open-world

Fetch full event detail by OCD event ID. Returns agenda, participants, media links, and associated documents when requested via include. Experimental — event coverage is limited in Open States. Obtain the event_id from openstates_search_events.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_get_event",
    "arguments": {
      "event_id": "<event_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "event_id": {
      "type": "string",
      "minLength": 1,
      "description": "OCD event ID (from openstates_search_events results)."
    },
    "include": {
      "description": "Related data to inline. \"agenda\" and \"participants\" are most useful.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "links",
          "sources",
          "media",
          "documents",
          "participants",
          "agenda"
        ]
      }
    }
  },
  "required": [
    "event_id"
  ],
  "additionalProperties": false
}
view source ↗

openstates_list_jurisdictions

open-world

List all jurisdictions covered by Open States — all 50 states, DC, and Puerto Rico. Returns coverage metadata: latest bill update time, latest people update time, and optionally all legislative sessions with their identifiers. Use this when you need to discover valid session identifiers for a state before calling openstates_search_bills with a session filter. The legislative_sessions include option returns all historical and current sessions — always check valid session identifiers here before using them in bill searches, since formats vary widely by state (e.g., "2025", "2025-2026", "2025rs", "2025s1").

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_list_jurisdictions",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "classification": {
      "default": "state",
      "description": "Filter by jurisdiction type. Use \"state\" (default) for all 50 states, DC, and Puerto Rico.",
      "type": "string",
      "enum": [
        "state",
        "municipality",
        "country"
      ]
    },
    "include": {
      "description": "Related data to inline. \"legislative_sessions\" returns all session identifiers and date ranges — required when you need to discover valid session values for bill searches.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "organizations",
          "legislative_sessions",
          "latest_runs"
        ]
      }
    },
    "page": {
      "default": 1,
      "description": "Page number (1-indexed).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "per_page": {
      "default": 52,
      "description": "Results per page. Default 52 to cover all states, DC, and Puerto Rico in one request.",
      "type": "integer",
      "minimum": 1,
      "maximum": 52
    }
  },
  "required": [
    "classification",
    "page",
    "per_page"
  ],
  "additionalProperties": false
}
view source ↗

openstates_get_jurisdiction

open-world

Fetch full metadata for a specific jurisdiction including all legislative sessions, their identifiers, and coverage dates. Use when you need to know the exact session identifier for a state before filtering bill searches — session formats vary widely (e.g., "2025", "2025rs", "2025s1"). Jurisdiction IDs follow OCD format: ocd-jurisdiction/country:us/state:{abbr}/government (e.g., ocd-jurisdiction/country:us/state:wa/government). State names (e.g., "Washington") and two-letter abbreviations (e.g., "wa") are also accepted.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "openstates_get_jurisdiction",
    "arguments": {
      "jurisdiction_id": "<jurisdiction_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "jurisdiction_id": {
      "type": "string",
      "minLength": 1,
      "description": "OCD jurisdiction ID, state name (e.g., \"Washington\"), or two-letter abbreviation (e.g., \"wa\")."
    },
    "include": {
      "description": "Related data to inline. \"legislative_sessions\" returns all historical and current sessions with identifiers and date ranges. \"latest_runs\" shows last scraper run metadata.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "organizations",
          "legislative_sessions",
          "latest_runs"
        ]
      }
    }
  },
  "required": [
    "jurisdiction_id"
  ],
  "additionalProperties": false
}
view source ↗

Resources

1

Jurisdiction metadata including current sessions, coverage dates, and bill/people update timestamps. Use as stable reference context before querying bills or people — inject this to prime session identifiers without a tool call.

uri openstates://jurisdiction/{jurisdiction_id} mime application/json

Prompts

2

Structured framework for analyzing a state bill: summary, sponsors, committee referrals, action timeline, vote record, and related legislation. Produces a comprehensive research brief.

  • jurisdictionrequired — State name, abbreviation, or OCD-ID (e.g., "Washington", "wa").
  • sessionrequired — Session identifier (e.g., "2025", "2025rs"). Use openstates_get_jurisdiction to confirm.
  • bill_idrequired — Bill identifier as used by the legislature (e.g., "HB 1000", "SB 42").

Research framework for profiling a legislator: sponsored bills, committee assignments, voting record, and contact details. Produces a structured profile for constituent research, advocacy, or journalistic purposes.

  • namerequired — Legislator name or partial name (e.g., "Smith", "Jane Smith").
  • jurisdictionrequired — State name, abbreviation, or OCD-ID (e.g., "Washington", "wa").