racemodel
README.md
# racemodel
racemodel is a thin local bridge to the ElectionsMCP
hosted MCP server, a modelling service for U.S.
election races. Upstream, a user can resolve places
and candidates, build a scenario, set candidate
shares and turnout assumptions, apply a swing, and
then read the race back as tallies, flipped seats,
maps, charts and precinct-level roll-ups — including
separate handling for primary races.
The bridge holds no election data and computes no
forecast of its own. It serves the upstream server's
tool list locally — exactly as captured from the live
endpoint — and forwards each tool call upstream,
returning the result untouched. Scenario and
simulation state lives upstream, so writes such as
creating a scenario or setting shares are the
service's own modelling operations, forwarded like
every other call. `billing_status` is a read; there
is no payment, donation or purchase tool in the
surface.
## Tools
Geography, candidates and contests:
- `resolve_geography` — turn a place name or shorthand
into a canonical geo id (`query`, required).
- `resolve_candidate` — find who holds or runs for a
seat from a person's name (`name`, required).
- `search_candidates` — browse the candidate registry
by filters without supplying a name.
- `lookup_address` — resolve an address (`address`,
required) to its geography.
- `list_contests` — list contests for a geography
(`geo_id`, required).
- `election_calendar` — the election calendar. No
required arguments.
Scenarios and simulations:
- `create_scenario` — start a new scenario (`name`,
required).
- `list_scenarios`, `get_scenario` (`scenario_id`),
`commit_version` (`scenario_id`), and `diff_versions`
(`scenario_id`, `version_a`, `version_b`) — manage
and compare saved scenario versions.
- `set_performance` — set shares for a geography in a
scenario (`scenario_id`, `geo_id`, `shares`).
- `target_precincts` — precinct targeting for a
scenario (`scenario_id`, required).
- `set_candidates` — set the candidate list for a
simulation (`simulation_id`, `level`, `candidates`).
- `set_turnout` — set turnout assumptions
(`simulation_id`, required).
- `set_race_scope` — set a simulation's race scope
(`simulation_id`, required).
- `list_simulations` and `get_simulation`
(`simulation_id`, required) — enumerate and read
simulations.
- `share_simulation` — share a simulation
(`simulation_id`, required).
Views, swings and roll-ups:
- `get_view`, `render_view` and `set_view` — read,
render or set a simulation's view (each takes
`simulation_id`).
- `render_chart` — render a chart (`type`, required).
- `add_map_comment` (`simulation_id`, `body`) and
`list_map_comments` (`simulation_id`) — annotate and
read back a simulation's map.
- `apply_uniform_swing` — apply a uniform swing in
percentage points (`simulation_id`, `level`,
`swing_pp`).
- `apply_swing_to_query` — apply a swing scoped by a
query (`simulation_id`, `state`, `filter`).
- `get_tally` — the tally at a level (`simulation_id`,
`level`).
- `list_flipped` — seats that flipped at a level
(`simulation_id`, `level`).
- `compare_simulations` — compare two simulations at a
level (`simulation_id_a`, `simulation_id_b`,
`level`).
- `roll_up_race` — roll a simulation up to the race
level (`simulation_id`, required).
Turnout, returns and reference data:
- `get_early_voting_turnout` — early-voting turnout
for a state (`state`, required).
- `get_county_voter_turnout_and_registration`,
`get_state_historical_turnout`,
`get_live_early_vote_returns` and
`get_precinct_election_returns` — turnout,
registration, historical and returns reads. No
required arguments.
- `get_county_officials` and
`get_county_economic_and_wealth_profile` — county
reference profiles. No required arguments.
- `billing_status` and `connection_status` — account
and connection reads. No required arguments.
- `get_campaign_onboarding`, `help` and `get_catalog`
— onboarding, help and catalog reads. No required
arguments.
Primaries:
- `list_primary_calendar` — primary calendar for a
party (`party`, required).
- `set_primary_shares` — set primary shares
(`simulation_id`, `party`).
- `roll_up_primary` — roll a primary up
(`simulation_id`, `party`).
- `primary_batch_edit` — batch-edit a primary
(`simulation_id`, `edits`).
Meta:
- `call_tool` — invoke another tool by name through
the upstream (`name`, required).
## Configuration
- `ELECTIONSMCP_MCP_URL` (optional) — override the
upstream endpoint. Defaults to
`https://www.electionsmcp.com/mcp`. (The override
hook is this rebuild's own labelled reconstruction.)
- `ELECTIONSMCP_API_KEY` (optional) — when set, its
value is sent on every upstream request under the
header name the registry record pins for this
remote, `x-electionsmcp-key`. When it is unset, no
auth header is sent. (This forwarding is a labelled
reconstruction; the original capture was keyless.)
### Forwarding mechanics
On the first tool call the client opens a streamable
HTTP session with the upstream: a JSON-RPC
`initialize` request (protocolVersion `2025-03-26`,
clientInfo name `racemodel`), then a
`notifications/initialized` notification, then the
`tools/call` request carrying the caller's arguments
unchanged. When the upstream answers `initialize`
with an `Mcp-Session-Id` header, that value rides on
every later request of the session, which is reused
for the life of the process. Replies may arrive as
plain JSON or as server-sent events; both are read.
Successful upstream results pass through verbatim,
including any `isError` flag the upstream sets.
Failures — a JSON-RPC error, a non-2xx status, an
unreadable response, or a request that cannot be
completed — come back as an `isError` result whose
text starts with `racemodel error:` (this rendering
is this rebuild's own labelled reconstruction).
## CLI
Each tool is also a subcommand taking one JSON
argument string (omit it for tools that take none):
```bash
npx @reneturcios/racemodel resolve_geography '{"query":"CA-03"}'
npx @reneturcios/racemodel create_scenario '{"name":"Baseline 2026"}'
npx @reneturcios/racemodel get_catalog
npx @reneturcios/racemodel --version
```
Exit codes: `0` on success, `1` on an `isError`
result, `2` on a usage error.
## MCP server
```bash
npx -y @reneturcios/racemodel mcp
```
MCP client config:
```json
{
"mcpServers": {
"racemodel": {
"command": "npx",
"args": ["-y", "@reneturcios/racemodel", "mcp"]
}
}
}
```
## Docker
```bash
docker run -i ghcr.io/cloudcorprecords/racemodel
docker run --rm ghcr.io/cloudcorprecords/racemodel --version
```
The container's default command is `mcp`, so the first
form is a stdio MCP server; any other arguments reach
the CLI normally.
## Development
```bash
npm install
npm run build
npm test
npm run dev
```
The test suite runs entirely against a stubbed
JSON-RPC upstream — no live network calls.
## License
MIT — see `LICENSE`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues