关于 openstates-mcp-server
openstates-mcp-server 为研究人员提供覆盖美国 50 个州、DC 和 5 个领地的州立法数据,涵盖法案、官员、委员会、活动及按坐标查找议员,并标注实验性数据的覆盖限制。
主要功能
- 01搜索法案并读取详情
- 02按姓名或位置查找议员
- 03浏览委员会和活动
- 04列出辖区与立法届次
- 05附带法案及会议相关数据
适用场景
- 01研究法案发起人和立法历程
- 02按坐标识别州及联邦代表
- 03查看委员会成员和会议议程
- 04在搜索法案前查找届次标识
MCP 相关
通过 STDIO 或 Streamable HTTP 向 MCP 客户端提供 10 个工具、一个辖区元数据资源和 2 个研究提示词,并提供公共托管实例。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://openstates.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-openstates https://openstates.caseyjhand.com/mcp{"mcpServers":{"cyanheads-openstates":{"type":"http","url":"https://openstates.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-openstates":{"type":"http","url":"https://openstates.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-openstates":{"type":"http","url":"https://openstates.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-openstates":{"serverUrl":"https://openstates.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
10| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| q | string | 否 | 在法案标题、摘要和正文中进行全文搜索。除非提供 jurisdiction,否则为必填项。已知州时应与 jurisdiction 配对使用——仅使用 q 搜索所有司法辖区时,常见词会导致上游超时。 |
| page | integer | 否 | 页码(从 1 开始)。 |
| sort | enum | 否 | 排序顺序。对于当前正在立法机构推进的法案,使用 "latest_action_desc"。updated_asc | updated_desc | first_action_asc | first_action_desc | latest_action_asc | latest_action_desc |
| chamber | enum | 否 | 按提出议院筛选。"upper" = 参议院,"lower" = 众议院/州议会。upper | lower |
| include | array | 否 | 内联相关数据。"sponsorships" 和 "actions" 可满足大多数研究需求,无需单独调用 openstates_get_bill。"votes" 会添加完整投票统计及每位议员的立场。 |
| session | string | 否 | 届次标识符(例如:"2025"、"2025-2026"、"2025rs")。使用 openstates_get_jurisdiction 并设置 include=legislative_sessions,以查找有效值。省略此项可搜索所有届次。 |
| sponsor | string | 否 | 按发起人姓名或 OCD 人员 ID 筛选。 |
| subject | array | 否 | 筛选带有一个或多个主题类别标签的法案。 |
| per_page | integer | 否 | 每页结果数。最多 20 条。默认值为 10。 |
| action_since | string | 否 | ISO 8601 日期 — 仅返回此日期之后有后续动作的法案(例如:"2025-01-01")。 |
| jurisdiction | string | 否 | 州名、两字母缩写或 OCD-ID(例如:"Washington"、"wa" 或 "ocd-jurisdiction/country:us/state:wa/government")。除非提供 q,否则必填。 |
| created_since | string | 否 | ISO 8601 日期 — 仅返回在此日期之后首次录入 Open States 的法案(例如:"2025-01-01")。可用于查找新提出的法案,而非最近更新或最近有后续动作的法案。 |
| updated_since | string | 否 | ISO 8601 日期 — 仅返回此日期之后更新的法案(例如:"2025-01-01")。 |
| classification | string | 否 | 法案分类:"bill"、"resolution"、"constitutional amendment" 等。 |
| sponsor_classification | string | 否 | 按发起人类型筛选:"primary"、"cosponsor"。 |
详细介绍
@cyanheads/openstates-mcp-server
通过 MCP 搜索美国全部 50 个州、DC 和 5 个美国领地的法案、立法者、委员会和活动。支持 STDIO 或 Streamable HTTP。
概述
来自 Open States 的美国州议会信息:涵盖全部 50 个州、DC 和 5 个美国领地。搜索法案、立法者、委员会和活动,并查找任意地点的代表。
工具
| 工具 | 描述 |
|---|---|
openstates_search_bills | 搜索所有已覆盖美国辖区的州立法议案,支持全文搜索、辖区/届次筛选、主题标签和发起人查询 |
openstates_get_bill | 通过 OCD ID 或由三部分组成的路径(辖区 + 届次 + bill_id)获取特定议案的完整详情 |
openstates_search_people | 按姓名、议院或选区搜索某个辖区内的州议员和官员,或通过 OCD person ID 获取特定人员信息 |
openstates_get_legislators_by_location | 查找代表某个地理坐标(纬度/经度)的所有议员,包括州议员和联邦代表团成员 |
openstates_search_committees | 列出某个辖区的委员会(实验性功能,并非所有州都有数据) |
openstates_get_committee | 通过 OCD 组织 ID 获取委员会详情,可选获取成员名单 |
openstates_search_events | 搜索听证会、全体会议和委员会会议(实验性功能) |
openstates_get_event | 获取完整的活动详情,包括议程、参与者和媒体链接 |
openstates_list_jurisdictions | 列出 Open States 覆盖的全部 56 个辖区(50 个州、DC 和 5 个美国领地),并提供届次标识符和覆盖元数据 |
openstates_get_jurisdiction | 获取特定辖区的完整元数据,包括所有立法届次及其标识符 |
资源
| 资源 | 描述 |
|---|---|
openstates://jurisdiction/{jurisdiction_id} | 辖区元数据,包括当前届次、覆盖日期以及议案/人员的更新时间戳 |
所有资源数据也可通过工具获取。以编程方式查询辖区信息时,请使用 openstates_get_jurisdiction;该资源适合注入辖区上下文,作为稳定的参考资料。
提示词
| 提示词 | 描述 |
|---|---|
openstates_bill_research | 用于分析州议案的结构化框架:摘要、发起人、委员会转交情况、行动时间线、投票记录和相关立法 |
openstates_legislator_profile | 用于研究议员档案的框架:发起的议案、委员会任职情况、投票记录和联系方式 |
能力参考
openstates_search_bills tool
- 根据架构要求,必须提供
jurisdiction或q;仅使用q搜索会覆盖全部 56 个辖区,且常见词会导致上游请求超时,因此同时提供两者是更可靠的方式 - 筛选条件:
session、chamber(upper/lower)、classification、subject标签、sponsor、sponsor_classification,以及action_since/updated_since/created_sinceISO 8601 日期筛选条件 include会内嵌发起记录、行动、投票、摘要、版本、文件和相关议案,避免后续调用openstates_get_billsort默认为updated_desc;sort=latest_action_desc可显示当前正在推进的议案;每页最多 20 条(默认 10 条)- 无结果提示会回显所有已应用的筛选条件;如果无法识别辖区,还会显示辖区名称
openstates_get_bill tool
- 通过
openstates_id(首选,可从搜索结果中获取)或由三部分组成的路径jurisdiction+session+bill_id查询;两者都未提供时,调用会因missing_lookup_params失败 - 接受立法机构格式的议案标识符(例如
HB 1000、SB 42) include会内嵌发起记录、行动、投票、版本、文件、摘要、其他标题/标识符和相关议案- ID 或路径无法解析为任何结果时返回
not_found
openstates_search_people 工具
- 必须提供
jurisdiction或id(OCD 人员 ID)之一——即使只按姓名搜索,不限定范围的查询也会超出上游超时限制 id可在一次调用中解析任意数量的指定 OCD 人员 ID——这些 ID 由法案提案人和委员会成员关系返回——无需同时提供jurisdictionorg_classification:upper/lower/executive/legislature(合并两院,不包括行政官员);省略此项会返回所有公职人员,包括行政官员- 不区分大小写的
name子字符串匹配,另支持district;include可添加 offices、links、other_names、other_identifiers、sources - 每条结果都会报告党派,但无法按党派筛选
- 每页最多 20 条
openstates_get_legislators_by_location 工具
- 传入十进制度数的
latitude/longitude;不支持对地址进行地理编码 - 一次调用返回两个政府层级:州议员,以及该坐标所在选区的 2 名美国参议员和 1 名美国众议员
jurisdiction.classification(state与country)用于区分层级——current_role.org_classification不能用于区分,因为美国参议员和州参议员的值都是upperstateCount/federalCount补充字段用于报告各层级的数量- 超出范围的坐标会返回
invalid_coordinate;没有覆盖数据的位置会返回空结果提示
openstates_search_committees 工具
- 必须提供
jurisdiction——架构会拒绝搜索所有州的请求 - 可按
classification(committee/subcommittee)和chamber筛选;parent可限定为某个委员会的子委员会 include=memberships会返回完整名册及成员角色- 实验性功能:Open States 正在恢复委员会支持,并非所有州都有覆盖数据——输出中的
coverageNote字段始终会说明这一点 - 每页最多 20 条
openstates_get_committee 工具
- 按 OCD
committee_id获取(来自openstates_search_committees) include=memberships会返回名册;include=links/sources会添加参考 URL- 实验性功能——并非所有州都有委员会数据;ID 不存在时返回
not_found
openstates_search_events 工具
- 必须提供
jurisdiction——事件端点不支持搜索所有州 after/before用于限定 ISO 8601 日期范围;require_bills=true会筛选议程中包含法案的事件include=agenda,participants会返回完整会议背景信息- 实验性功能:大多数州不发布事件数据——结果为空可能意味着没有覆盖数据,而非没有事件
- 每页最多 20 条
openstates_get_event 工具
- 按 OCD
event_id获取(来自openstates_search_events) include可添加 agenda、participants、links、media 和 documents- 实验性功能——事件覆盖范围有限;ID 不存在时返回
not_found
openstates_list_jurisdictions 工具
- 默认调用会返回全部 56 个司法辖区(50 个州、DC 和 5 个美国属地)——由于上游
per_page上限为 52,无法再覆盖完整集合,因此由服务端合并各页结果 classification筛选器默认值为stateinclude=legislative_sessions会返回所有历史和当前会期标识符——按会期筛选法案搜索前必须先获取这些标识符,因为各州的格式不同(例如,2025、2025-2026、2025rs、2025s1)include=organizations/latest_runs会添加议院/行政机构信息以及抓取器运行元数据
openstates_get_jurisdiction 工具
- 按 OCD-ID、州名或两字母缩写获取一个司法辖区
include=legislative_sessions会返回所有会期标识符及日期范围- 标识符无法解析时返回
not_found
openstates://jurisdiction/{jurisdiction_id} 资源
jurisdiction_id可接受 OCD-ID、州名或两字母缩写- 以
application/json格式返回管辖区元数据:当前立法会期、覆盖日期、法案/人员更新时间戳 - 始终包含
legislative_sessions— 无需调用工具即可预先获取会期标识符 - 标识符无法解析时返回
not_found
openstates_bill_research 提示词
- 参数:
jurisdiction、session、bill_id— 均为必填 - 返回一条用户消息,要求生成结构化研究简报:概述、发起人、立法历史、投票记录、相关立法、法案文本和通过可能性评估
openstates_legislator_profile 提示词
- 参数:
name、jurisdiction— 均为必填 - 返回一条用户消息,要求生成结构化个人资料:身份/职务、发起的立法、委员会任职情况、投票记录和摘要
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔身份验证(none / jwt / oauth)、可替换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志记录。
Open States 专属功能:
- 全面覆盖 Open States v3 API:法案、人员、委员会、活动和管辖区
- 法案和委员会获取工具支持双重查询模式(OCD ID 或结构化路径)
- 通过 Open States 按地理位置查询人员的端点查找立法者,涵盖州和联邦两个层级
- 服务级说明会在任何工具调用前,为 Agent 提供会期发现工作流和
include参数使用策略 - 按密钥设置请求预算(
OPENSTATES_DAILY_REQUEST_BUDGET),并通过两级超时机制保护共享上游密钥
面向 Agent 的输出:
- 无结果恢复:搜索工具会回显所用筛选条件,并在未返回结果时建议如何扩大搜索范围
- 委员会和活动工具提供实验性的覆盖范围说明(
coverageNote)——明确提示限制,而不是静默返回空结果 - 所有搜索和获取工具均支持
include参数模式,避免常见研究工作流中的 N+1 后续调用
入门
公共托管实例
可使用公共实例 https://openstates.caseyjhand.com/mcp — 无需安装。通过 Streamable HTTP 将任意 MCP 客户端指向该实例:
{
"mcpServers": {
"openstates-mcp-server": {
"type": "streamable-http",
"url": "https://openstates.caseyjhand.com/mcp"
}
}
}
自托管/本地运行
需要 Open States API 密钥 — 在 open.pluralpolicy.com 免费注册。
将以下内容添加到 MCP 客户端配置文件中:
{
"mcpServers": {
"openstates-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/openstates-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"OPENSTATES_API_KEY": "your-api-key"
}
}
}
}
也可使用 npx(无需 Bun):
{
"mcpServers": {
"openstates-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/openstates-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"OPENSTATES_API_KEY": "your-api-key"
}
}
}
}
也可使用 Docker:
{
"mcpServers": {
"openstates-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "OPENSTATES_API_KEY=your-api-key",
"ghcr.io/cyanheads/openstates-mcp-server:latest"
]
}
}
}
使用 Streamable HTTP 时,设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 OPENSTATES_API_KEY=your-key bun run start:http
# Server listens at http://localhost:3010/mcp
前置条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- Open States API 密钥 — 在 open.pluralpolicy.com 免费注册。
安装
- 克隆代码库:
git clone https://github.com/cyanheads/openstates-mcp-server.git
- 进入目录:
cd openstates-mcp-server
- 安装依赖项:
bun install
- 配置环境:
cp .env.example .env
# edit .env and set OPENSTATES_API_KEY
配置
启动时会通过 src/config/server-config.ts 中的 Zod 模式验证所有配置。主要环境变量:
| 变量 | 说明 | 默认值 |
|---|---|---|
OPENSTATES_API_KEY | 必填。 从 open.pluralpolicy.com 获取的 Open States API 密钥。 | — |
OPENSTATES_API_BASE_URL | Open States API 基础 URL。 | https://v3.openstates.org |
OPENSTATES_DAILY_REQUEST_BUDGET | 滚动 24 小时内允许的上游请求数上限。额度用尽后,请求发出前就会被拒绝,因此超出额度的调用不会产生上游费用。默认值与 v3 免费套餐的每日上限一致;如果你的密钥所属套餐允许更多请求,可提高此值。 | 250 |
OPENSTATES_REQUEST_TIMEOUT_MS | 每次尝试的上游请求截止时间,以毫秒为单位(最小值为 1000)。超时不可重试,因此无法完成的请求只会等待一次,而非四次。Open States 的范围查询耗时从不到一秒到约 57 秒不等,其自身网关会在接近 60 秒时放弃;调低此值可更快失败,调高则可等待较慢的查询完成。 | 45000 |
OPENSTATES_TOTAL_REQUEST_BUDGET_MS | 一次调用的总用时上限(毫秒),涵盖所有重试尝试及其间的退避时间。每次尝试的截止时间限制单个请求;此值则限制整个重试流程,避免持续以可重试错误失败的慢速上游让调用在整个重试序列期间一直挂起。必须不小于 OPENSTATES_REQUEST_TIMEOUT_MS;否则启动时会拒绝配置,因为每次尝试都会在自身截止时间生效前被中止。默认值是截止时间的两倍,因此即使某次尝试在略短于截止时间时失败,下一次重试仍几乎有完整的截止时间可用。 | 90000 |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_SESSION_MODE | HTTP 会话模式:auto、stateful 或 stateless。src/index.ts 通过 createApp({ sessionMode }) 声明使用 stateless 模式——没有工具会暂停以等待调用方输入,因此无需会话状态。设置此变量会覆盖该声明;框架模式默认值为 auto,会解析为有状态模式。 | stateless |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP 端点路径。 | /mcp |
MCP_PUBLIC_URL | 用于 TLS 终止型反向代理部署的公开源站覆盖值。 | 无 |
MCP_AUTH_MODE | 身份验证模式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(debug、info、notice、warning、error)。 | info |
MCP_GC_PRESSURE_INTERVAL_MS | 选择启用的、仅限 Bun 的强制 GC 间隔(毫秒)。如果持续 HTTP 负载下堆内存不断增长,可尝试设置为 60000。 | 0(已禁用) |
LOGS_DIR | 日志文件目录(仅限 Node.js)。 | <project-root>/logs |
STORAGE_PROVIDER_TYPE | 存储后端:in-memory、filesystem、supabase、cloudflare-kv/r2/d1。 | in-memory |
OTEL_ENABLED | 启用 OpenTelemetry 插桩。 | false |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP 基础 URL;追踪数据发送到 /v1/traces,指标发送到 /v1/metrics。 | 无 |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | 选择启用的 OTLP 日志导出(例如 http://localhost:4318/v1/logs);基础端点不会启用此功能。 | 无 |
LOG_TOOL_FAILURE_PAYLOADS | 记录每次失败的工具调用参数和结果,仅按键名进行脱敏,并受 LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES 限制(默认值为 16384)。 | false |
完整的可选覆盖项列表,请参阅 .env.example。
运行服务
本地开发
-
构建并运行生产版本:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
运行检查和测试:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t openstates-mcp-server .
docker run --rm -e OPENSTATES_API_KEY=your-key -e MCP_TRANSPORT_TYPE=http -p 3010:3010 openstates-mcp-server
Dockerfile 默认使用 HTTP 传输,显式设置 MCP_SESSION_MODE=stateless,并将日志写入 /var/log/openstates-mcp-server。默认会安装 OpenTelemetry 对等依赖;构建时使用 --build-arg OTEL_ENABLED=false 可省略这些依赖。
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口点——注册工具、资源、提示词,并初始化 Open States 服务。 |
src/config | 使用 Zod 解析并验证特定服务的环境变量。 |
src/mcp-server/tools | 工具定义(*.tool.ts)。涵盖法案、人员、委员会、活动和司法辖区的 10 个工具。 |
src/mcp-server/resources | 资源定义。司法辖区元数据资源。 |
src/mcp-server/prompts | 提示词定义。法案研究和立法者简介提示词。 |
src/services/openstates | Open States API v3 服务层——HTTP 客户端、请求处理和领域类型。 |
tests/ | 与 src/ 结构对应的单元测试和集成测试。 |
开发指南
开发指南和架构规则请参阅 CLAUDE.md。简要概括如下:
- 处理器抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log进行请求级日志记录,使用ctx.state进行租户级存储 - 通过
src/index.ts中的数组注册新工具和资源 - 封装外部 API 调用:验证原始数据 → 规范化为领域类型 → 返回输出架构;绝不伪造缺失字段
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
许可证
Apache-2.0——详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。