oravan
Remote MCP server for nonpartisan U.S. Congress data: plain-language bill decodes (bilingual EN/ES), representative lookup by ZIP with district-office phones, and what's-moving urgency ranking. Read-only, keyless.
README
Oravan
Your line to Congress · Tu línea con el Congreso
Oravan is free, nonpartisan civic infrastructure: find your federal representatives, understand active bills in plain language (English and Spanish), get a 30-second call script, and make the call — in under 5 minutes, with no account.
The name is the Oravan: the platform in the Roman Forum where citizens stood to address the public and the powerful — the original place a voice met power. Latin roots are the shared ancestry of English and Spanish alike.
MCP server
This repository also implements a remote MCP (Model Context Protocol) server — the same decoded corpus and lookups, exposed for AI assistants and agents:
- Endpoint (Streamable HTTP):
https://oravan.org/api/mcp/mcp— keyless, read-only, rate-limited; no account or credentials required - Local/stdio:
npm cithennpx tsx scripts/mcp-stdio.mjs— the same 5 tools over stdio, zero env vars/secrets required - Implementation:
app/api/mcp/[transport]/route.ts(built onmcp-handler+@modelcontextprotocol/sdk), tool definitions shared with the stdio entry vialib/core/mcp-tools.ts, pure data layer inlib/core/ - Five tools:
lookup_representatives,get_bill,search_bills,whats_moving,get_representative— every response carries a citation envelope (source, as-of freshness, AI-content label, license) in English or Spanish - Official MCP Registry: published as
org.oravan/mcp(server.jsonat the repo root, schema-validated in CI byscripts/check-server-json.mjs) - Docs: oravan.org/mcp (tool reference, client config, privacy posture) · docs/mcp-server-readme.md
Design principles
- Zero accounts. ZIP code, interests, and call history live in
localStorageon the visitor's device. No server-side user data exists — nothing to breach, leak, or subpoena. This is the core privacy posture for at-risk users, not a missing feature. - Static-first. Bills, legislators, district offices, and ZIP→district mappings are static JSON in
data/, baked into ~1,000 statically generated pages. Fast, nearly free to host, resilient under load. The only dynamic endpoints are/api/script(AI script generation, cached per bill+stance+language, IP rate-limited),/api/reps(pure lookup),/api/district(stateless split-ZIP address refinement: proxies the Census geocoder so the visitor's IP never reaches census.gov; the address is never stored or logged), and/api/feedback(beta feedback relayed to a private GitHub issue — only what the visitor volunteered, no identifiers). - Bilingual as a first-class feature. Full EN/ES UI via
next-intl; scripts are generated in the user's language. - The call moment is the product. Voicemail is legitimized (offices tally it identically), after-hours calling is encouraged, district offices are listed alongside DC, and outcomes (spoke / voicemail / couldn't reach) are logged locally.
- Honest about AI. Every generated summary and script is labeled, editable, and reviewed by the human before any call.
- Accessible by default. Semantic landmarks, skip link, visible focus,
prefers-reduced-motion, 44px+ touch targets, AA contrast.
Data sources
| File | Source | Refresh |
|---|---|---|
data/bills.json + data/bills-es.json |
Decoded bill corpus (Congress.gov bills + AI plain-language summaries, English and Spanish) | Nightly sync (scripts/sync-bills.mjs via sync-bills.yml): statuses refresh freely; new bills are decode-before-publish, entering the corpus only once their EN and ES summaries exist |
data/legislators.json |
unitedstates/congress-legislators (public domain) + district offices | scripts/process-data.py |
data/zip-districts.json |
OpenSourceActivismTech/us_zipcodes_congress | same |
data/vacancies.json |
Derived, not fetched: scripts/vacancy_diff.py diffs seat sets against the currently-committed data every run, so a departed member with no successor surfaces as an explicit vacancy (reps page, /api/reps, MCP lookup_representatives) instead of silently disappearing or being backfilled from a stale term record |
scripts/process-data.py (same run as legislators.json) |
data/redistricting-watch.json |
Human-authored (status/note) for the 10 states with contested-or-recent 2025–26 mid-decade map changes; rdh_lastmod is a tripwire baseline against the Redistricting Data Hub's own state-page sitemap — see docs/solutions/two-clock-district-boundaries.md |
scripts/check-redistricting-watch.mjs, weekly via refresh-legislators.yml; opens a redistricting-watch-labeled issue on change, never auto-updates status/note |
data/coverage.json |
Real news articles about top-band bills via TheNewsAPI, AI-relevance-filtered (Haiku) | scripts/sync-coverage.mjs (nightly, gated on NEWS_API_KEY) |
data/media-bias.json |
Outlet political-lean ratings by AllSides, used under CC BY-NC with attribution | Vendored snapshot |
Portraits are served from the public-domain unitedstates/images project.
Solved pipeline incidents (root cause + the CI gates that prevent recurrence) are documented in docs/solutions/.
The "Read" section (outlet-bias coverage)
Each top bill's page shows real third-party articles about it, labeled by the outlet's political lean (Left / Center / Right) — reusing AllSides' publication-level ratings, never a Oravan-invented one. Oravan takes no stance and authors no partisan text: AI is used only behind the scenes — generating each bill's news-search terms (press-style names and a subject query) and a cheap relevance gate (is this article about this bill?) — and authors nothing displayed. The ingestion runs nightly in CI and bakes results to JSON, so the site still makes zero runtime third-party calls. Without NEWS_API_KEY the sync is a no-op and the section renders nothing; a small hand-built real sample (data/coverage.json) keeps it demoable. Lean is shown by text label + position only — never party colors (a hard rule; see DESIGN.md).
Develop
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 statically generates every bill page in both locales.
Known v1 caveats
- ZIP→district mapping is ZCTA-based; a split ZIP shows all candidate districts by default (senators are unaffected). Entering a street address — optional, sent once by POST, never stored or logged — narrows it to the actual district via a server-proxied Census-geocoder lookup; the all-candidates view remains the graceful fallback whenever the geocoder can't help. The geocoder request pins the "119th Congressional Districts" layer, which needs a bump when the Census rolls the vintage to the 120th.
- Script cache and rate limits are in-memory per serverless instance — fine at demo scale, should move to a shared store before heavy traffic.
- New bills can lag behind Congress.gov: the nightly sync decodes at most
MAX_NEW_DECODESnew bills per run (cost ceiling), so after a missed window the corpus catches up over several nights (decode-before-publish; the backlog drains oldest-first). - "Read" coverage exists only for top-band bills (the long tail shows nothing); the ES locale shows the same English articles with localized chrome; outlets absent from
data/media-bias.jsonappear without a lean chip.
License
- Code: GNU AGPL-3.0. You may use, modify, and run this code — including as a network service — provided modified versions you operate or distribute remain open under the same license. Embedding Oravan's hosted widgets on your site via the loader/script tag does not subject your site to the AGPL; that's use of our service, not distribution of this code.
- Not licensed: the Oravan name, logo, and brand assets (
assets/brand/, app icons). All rights reserved — forks must use their own identity. - Content: underlying legislative data is U.S. government work (public domain). AI-generated decodes and summaries are licensed CC BY 4.0, exactly as declared in the MCP citation envelope and on the citations page.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。