Skip to main content
Glama
README.md
# VotePredictor — MCP server & API

US election forecasts with a public accuracy record.
[votepredictor.com](https://votepredictor.com) · [docs](https://votepredictor.com/developers)

[![smithery badge](https://smithery.ai/badge/koconnor/votepredictor)](https://smithery.ai/servers/koconnor/votepredictor)

This repo holds the MCP manifest and the integration docs. The server is **hosted** —
there is nothing here to install or run.

## MCP server

Remote, Streamable HTTP. Add the URL to any MCP client:

```json
{
  "votepredictor": {
    "url": "https://votepredictor.com/api/mcp"
  }
}
```

For stdio-only clients:

```json
{
  "votepredictor": {
    "command": "npx",
    "args": ["-y", "mcp-remote", "https://votepredictor.com/api/mcp"]
  }
}
```

Registry: [`com.votepredictor/elections`](https://registry.modelcontextprotocol.io/v0/servers?search=votepredictor)

### Tools

| Tool | What it answers |
| --- | --- |
| `forecast_race` | "Who's winning the Ohio Senate race?" — takes a state name, code, or district (`Ohio`, `OH`, `CA-12`) |
| `chamber_outlook` | "Who's favoured to control the Senate?" — control probability, expected seats, biggest movers |
| `forecaster_accuracy` | "Whose election forecast should I trust?" — difficulty-adjusted scores for every major forecaster |
| `member_profile` | A member of Congress: ideology, reported net worth, and the race for their seat |

Tools take what a person actually says, not ids you have to look up first.

## JSON API

Free, no key, CORS open. Index: <https://votepredictor.com/api/v1>

```
GET /api/v1/race/{race_id}            e.g. 2026_SEN_OH, 2026_HOUSE_CA-12
GET /api/v1/chamber/{senate|house}
GET /api/v1/member/{bioguide_id}      e.g. P000197
GET /api/v1/ratings?office=ALL
```

```bash
curl https://votepredictor.com/api/v1/race/2026_SEN_OH
```

## Three conventions

These are what make the data safe to quote. If you build on it, please carry them through.

**Nothing is certain.** `p_dem_win` is clamped to 0.01–0.99. An election that hasn't
happened is never 0% or 100%, however safe the seat.

**Provenance is always stated.** `source` is `polls` or `fundamentals`. Nobody surveys
Wyoming, so its forecast comes from state lean, incumbency and the national environment
instead. Polls take precedence wherever they exist — measured against the seats holding
both, the fundamentals model agrees with the poll-driven one on 15 of 16 safe races but
only 3 of 7 competitive ones.

**Some races publish nothing.** Where a candidate has left the ballot, the endpoint returns
`forecast: null` with a reason rather than a number, because the stored probability
describes a matchup that no longer exists. A race we hold nothing for returns 404 — a
different answer, deliberately.

## Accuracy

Every forecast is frozen when its race resolves, so the track record can't be edited after
the fact. The [ratings board](https://votepredictor.com/ratings) scores every model, market,
forecaster and pollster on resolved races since 1998, adjusted for how hard each race was —
including VotePredictor's own model, ranked in place alongside FiveThirtyEight, Cook and
Sabato's Crystal Ball.

## Attribution

Free to use. Please attribute "VotePredictor" and link the specific page. Probabilities
change daily until a race is decided.

Issues and requests welcome here.