关于 Oravan
Oravan 是只读 MCP 服务,可查询美国联邦代表并以通俗的英语和西班牙语了解待审法案。它提供 5 种工具,响应附带来源与时效信息,且无需账户或凭据。
主要功能
- 01查询联邦代表
- 02搜索并查看法案
- 03了解国会近期动态
- 04英语和西班牙语响应
- 05提供来源及时效信息
适用场景
- 01查询所在选区的代表
- 02通俗了解待审法案
- 03查看国会当前议程
MCP 相关
通过 Streamable HTTP 或本地 stdio 提供 5 种只读工具,包括代表查询、法案检索与查看,以及国会动态查询。无需账户或凭据,响应包含引用信息。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://oravan.org/api/mcp/mcpclaude mcp add --transport http org-oravan https://oravan.org/api/mcp/mcp{"mcpServers":{"org-oravan":{"type":"http","url":"https://oravan.org/api/mcp/mcp"}}}在 Cursor 中打开{"servers":{"org-oravan":{"type":"http","url":"https://oravan.org/api/mcp/mcp"}}}在 VS Code 中打开{"mcpServers":{"org-oravan":{"type":"http","url":"https://oravan.org/api/mcp/mcp"}}}{"mcpServers":{"org-oravan":{"serverUrl":"https://oravan.org/api/mcp/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
5| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| zip | string | 是 | 5 位数的美国 ZIP 邮政编码。 |
| locale | enum | 否 | 响应语言:"en"(默认)或 "es"。en | es |
详细介绍
Oravan
你与国会的连线 · 你与国会的连线
Oravan 是免费的无党派公民基础设施:查找你的联邦代表,用浅显易懂的语言(英语和西班牙语)了解正在审议的法案,获取一份 30 秒的通话稿,然后拨出电话——全程不到 5 分钟,无需账户。
MCP 服务
此代码库还实现了一个远程 MCP(Model Context Protocol)服务——使用同一解读语料库和查询功能,为 AI 助手和 Agent 提供服务:
- 端点(Streamable HTTP):
https://oravan.org/api/mcp/mcp— 无需密钥,只读,设有速率限制;无需账户或凭据 - 本地/stdio: 先运行
npm ci,再运行npx tsx scripts/mcp-stdio.mjs— 通过 stdio 提供相同的 5 个工具,无需环境变量或密钥 - 实现:
app/api/mcp/[transport]/route.ts(基于mcp-handler+@modelcontextprotocol/sdk构建),工具定义由 stdio 入口与lib/core/mcp-tools.ts共享,纯数据层位于lib/core/ - 五个工具:
lookup_representatives、get_bill、search_bills、whats_moving、get_representative— 每个响应都包含引用信息(来源、数据时效性、AI 内容标签、许可证),支持英语或西班牙语 - 官方 MCP Registry: 已以
org.oravan/mcp发布(代码库根目录中的server.json,由scripts/check-server-json.mjs在 CI 中进行架构验证) - 文档: oravan.org/mcp(工具参考、客户端配置、隐私说明) · docs/mcp-server-readme.md
设计原则
- 无需账户。 邮政编码、兴趣和通话记录都保存在访客设备的
localStorage中。服务器端不存在用户数据——无数据可供入侵、泄露或传唤。这是对高风险用户的核心隐私保护立场,而不是缺失的功能。 - 静态优先。 法案、议员、选区办公室和邮政编码→选区映射都是
data/中的静态 JSON,并构建到约 7,500 个静态生成页面中(2026-09-24 的构建包含 7,566 个页面,涵盖每位国会议员以及每日简报)。速度快、托管成本几乎为零,并且能在高负载下保持稳定。服务端端点包括/api/script(AI 通话脚本生成,按法案 + 立场 + 语言 + 内容版本缓存在共享存储中,并进行 IP 速率限制)、/api/reps(纯查询)、/api/district(无状态的邮政编码拆分地址细化:代理 Census 地理编码服务,因此访客的 IP 不会到达 census.gov;地址绝不会被存储或记录)、/api/mcp(下文介绍的 MCP 服务)、/api/brand(为合作伙伴网站提供 AI 主题建议,供/embeds配置器使用;嵌入功能恢复前,该配置器处于隐藏状态)、/api/stripe/webhook(合作伙伴套餐配置;在设置签名密钥前会以 503 拒绝请求)、/api/tenant/impressions(合作伙伴读取自己的嵌入展示次数),以及/embed/portrait/[bioguide](用于嵌入的同源头像代理)。有两个页面路由按请求渲染——/reps(从 URL 读取邮政编码)和/nominations/[slug]——tests/static-rendering.spec.ts说明了将它们列为例外的原因。 - 将双语作为一等功能。 通过
next-intl提供完整的 EN/ES 界面;脚本使用用户的语言生成。 - 真相优先,致电是自然的下一步。 Oravan 以不偏不倚、通俗易懂的方式说明国会实际在做什么——理解是入口,而不是任务。致电相关功能仍是差异化优势(承认语音留言的有效性;办公室对语音留言和接通电话一视同仁地统计;鼓励下班后致电;同时列出选区办公室和 DC 办公室;在设备本地记录结果——已接通 / 语音留言 / 未能联系上)。对于仍待决定的议题,每个解读后的答案都能在两次交互内提供完整的通话脚本;一旦议题已有定论——例如法案成为法律或表决被否决——页面就会改为展示结果及用户所属议员的投票情况。致电功能降为次要,但绝不隐藏。(2026-07-26 修订;此前为“致电时刻就是产品”。2026-09-28 起,范围限定为仍待决定的议题。通过
tests/funnel.spec.ts中列出的三项不变量执行。) - 诚实说明 AI 的作用。 每份生成的摘要和脚本在首次展示时都会标明由 AI 生成;只有通过自动化关卡后才会发布:两种语言的内容都必须齐全,必须附有官方记录,并对每次解读执行架构检查——如果解读结果缺少必填字段,就会被丢弃,而不会以未完成的状态存储;
scripts/verify-sync.mjs会重新检查整个内容库,并在夜间运行中失败退出,确保提交任何内容前先完成检查。(2026-08-12 修订:有一项检查移到了提交之后执行——scripts/check-cursor-age.mjs中的游标年龄上限。它是进度信号,而非内容库检查:游标停滞表示我们落后了;如果在提交前检查并失败,就会导致停滞的夜间任务丢弃一整晚已付费完成的解读。此处提及的所有内容库检查均未改变,仍会在提交任何内容前执行。参见docs/constitution-log.md#cursor-age-2026-08-12。) 非党派措辞是法案解读中对模型的起草指示,也是 Big Questions 中强制执行的词汇检查(lib/moments-gate.mjs)——两者并不提供相同的保证,文案绝不会混淆这一点。夜间解读流程不包含人工步骤,产品也绝不声称有人工审核;产品所声称的那一项审核确实存在:致电者会在拨打前阅读并可编辑通话脚本。(2026-08-06 修订;此前为“已标注、可编辑,并由人工在每次通话前审核”。参见docs/constitution-log.md中 2026-07-25 的修订;本句本应遵循该修订,但当时并未遵循。) AI 内容在首次接触时即标注;来电者在脚本拨打电话前会先阅读并可编辑该脚本。最后这项要求有意仅适用于通话脚本:解码内容和 Moment 更新摘要会通过自动化审核后发布,无需人工介入,因此标注就是此处的全部披露。该标注与内容一同显示在首屏可见区域内,绝不放在脚注中。(2026-09-27,DESIGN.md停用时,此内容从该文件移至此处。) - 默认支持无障碍访问。 语义化页面地标、跳过链接、可见焦点、
prefers-reduced-motion、至少 44px 的触控目标、AA 级对比度。
数据源
| 文件 | 来源 | 刷新方式 |
|---|---|---|
data/bills.json + data/bills-es.json | 解读后的法案语料库(Congress.gov 法案 + AI 撰写的通俗易懂摘要,英文和西班牙文) | 每晚同步(通过 sync-bills.yml 运行 scripts/sync-bills.mjs):状态可随时刷新;新法案需先完成解读,再发布;只有 EN 和 ES 摘要都存在后,才会纳入语料库。每条记录还会保存生成解读所依据的文本版本;若国会替换了法案文本——例如委员会修正案更改了文件,却没有更改标题或状态——系统会在之后的某次夜间任务中重新读取新文本,每晚最多处理 10 条(REDECODE_MAX_PER_NIGHT,这是成本上限;旧记录的积压任务每晚处理几条,优先处理紧急法案) |
data/legislators.json | unitedstates/congress-legislators(公有领域)+ 选区办公室 | scripts/process-data.py |
data/zip-districts.json | OpenSourceActivismTech/us_zipcodes_congress | 同上 |
data/vacancies.json | 推导生成,不从外部获取:每次运行时,scripts/vacancy_diff.py 都会将席位集合与当前已提交的数据进行对比,因此,离任且没有继任者的成员会显示为明确的空缺(代表页面、/api/reps、MCP lookup_representatives),而不会悄然消失,也不会根据过时的任期记录补齐 | scripts/process-data.py(与 legislators.json 在同一次运行中处理) |
data/special-elections.json | 每个空缺席位的特别选举日期,严格按照 Federal Election Commission 的选举日期 API 所列内容记录(日期 + FEC 的选举类型代码),并附上核查日期。没有记录表示列表为空,绝不猜测日期;不会记录当选成员,因为在宣誓就职前,没有官方机器可读来源会列出当选者。在 /reps 的空缺席位卡片及该席位专属页面上显示 | scripts/sync-special-elections.mjs,由 refresh-legislators.yml 每周运行一次,紧接空缺对比之后(使用 api.data.gov 的公开 DEMO_KEY,无需密钥;请求失败时保留上次记录及其旧核查日期) |
data/redistricting-watch.json | 为 2025–26 年选区中期地图变动存在争议或近期发生变动的 10 个州人工编写(status/note);rdh_lastmod 是针对 Redistricting Data Hub 自有州页面站点地图的触发基准——参见 docs/solutions/two-clock-district-boundaries.md | scripts/check-redistricting-watch.mjs,由 refresh-legislators.yml 每周运行一次;发生变化时,会在唯一一个置顶的常设 redistricting-watch issue 下发表评论,其正文会改写为包含 10 个州状态的看板(以前每个发生变化的州都会新开一个 issue——六周内累计了 10 个,其中 8 个都源自 RDH 全站的一次重新发布);绝不自动更新 status/note |
data/nominations.json | 第 119 届国会的文职参议院提名(PN),包括 Congress.gov 自身的引文、说明句和最新行动,以及由 lib/nomination-status.mjs 规则表根据行动文本推导的状态。此文件不会由 AI 处理——Oravan 不会解读或改写提名,因为 Congress.gov 的说明本来就是一句通俗易懂的英文,所以 /nominations/[slug] 会逐字呈现参议院自己的记录,并在页面上说明这一点。唯一由 AI 生成的内容是通话脚本,且生成时会标明。提名可以成为“大问题”的载体;卡片、页面和通话脚本都是实时内容。与下文提到的报道标题一样,在 /es 上仍显示英文(参见已知的 v1 限制)。不包括军队晋升名单(没有说明,也没有可具名的被提名人)。目前没有 MCP 工具提供提名数据。 | scripts/sync-nominations.mjs(每晚运行,使用一个免费请求;由 scripts/check-nominations.mjs 控制) |
data/coverage.json | 通过 TheNewsAPI 获取的有关头部法案的真实新闻文章,并通过 AI(Haiku)筛选相关性 | scripts/sync-coverage.mjs(每晚运行,需配置 NEWS_API_KEY) |
data/media-bias.json | AllSides 提供的媒体机构政治倾向评级,依据 CC BY-NC 使用并注明出处 | 随项目附带的快照 |
| 肖像图片来自公共领域项目 unitedstates/images。 |
已解决的管道事故(根本原因 + 防止再次发生的 CI 门禁)记录在 docs/solutions/ 中。
“阅读”部分(媒体倾向覆盖)
每项重点法案的页面都会展示有关该法案的真实第三方文章,并按媒体机构的政治倾向标注(左派 / 中间派 / 右派)——沿用 AllSides 对出版物的评级,绝不自行编造 Oravan 的评级。Oravan 不表明立场,也不撰写任何党派性文本:AI 只在幕后使用——生成每项法案的新闻搜索词(新闻稿风格的名称和主题查询),并进行低成本相关性筛选(这篇文章是否与该法案有关)——不会撰写任何展示给用户的内容。数据采集在 CI 中每晚运行,并将结果写入 JSON,因此网站在运行时仍不会调用任何第三方服务。未设置 NEWS_API_KEY 时,同步操作会直接跳过,该部分不显示内容;少量手工整理的真实样例(data/coverage.json)则让它仍可用于演示。倾向仅通过文字标签和位置表示,绝不使用政党颜色(硬性规定;参见 CLAUDE.md 的规则 3)。
开发
npm install
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env.local # script generation + decode/relevance
echo "NEWS_API_KEY=..." >> .env.local # optional; enables the "Read" coverage sync
npm run dev
npm run build 会为两种语言静态生成每项法案的页面。
v1 已知注意事项
- ZIP→选区映射基于 ZCTA;被多个选区拆分的 ZIP 默认会显示所有候选选区(参议员不受影响)。输入街道地址(可选,仅通过 POST 发送一次,从不存储或记录)后,会通过服务器代理的 Census 地理编码器查询,将范围缩小到实际选区;无法通过地理编码器获取帮助时,则会优雅地回退到显示所有候选选区。地理编码器请求固定使用“119th Congressional Districts”图层;Census 将版本更新至第 120 届时,需要相应更新该图层。
- 脚本缓存和速率限制存储在共享的 Upstash 存储中(
lib/scriptcache.ts、lib/ratelimit.ts)。这些存储未配置时(本地开发、CI、预览),或请求失败时,两者都会回退到每个实例的内存,而不会导致请求失败。 - 新法案可能会晚于 Congress.gov 发布:每晚同步运行最多解码
MAX_NEW_DECODES项新法案(成本上限),因此错过同步后,语料库需要几个晚上才能追上(先解码再发布;积压内容按从旧到新的顺序清空)。 - “阅读”部分仅涵盖最高评级档的法案(大量长尾法案不显示内容);ES 语言版本会显示相同的英文文章,仅界面元素已本地化;未列入
data/media-bias.json的媒体机构不会显示倾向标签。
许可证
- 代码:GNU AGPL-3.0。你可以使用、修改和运行此代码——包括将其作为网络服务——前提是你运营或分发的修改版本必须在相同许可证下保持开源。通过加载器 / 脚本标签将 Oravan 托管的小组件嵌入你的网站,不会使你的网站受 AGPL 约束;这是在使用我们的服务,而不是分发此代码。
- **不在许可范围内:**Oravan 名称、徽标和品牌素材(
assets/brand/、应用图标)。保留所有权利——分支项目必须使用自己的品牌标识。 - **内容:**底层立法数据属于美国政府作品(公共领域)。AI 生成的解读和摘要采用 CC BY 4.0 许可,具体声明见 MCP 引用信息封装和引用页面。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。