Skip to main content
Glama
ky1emayers

civic-mcp

by ky1emayers

civic-mcp

A minimal MCP server that exposes U.S. election dates. It has a single tool, get_election_dates, backed by election_dates.json loaded into memory at startup.

Requirements

  • Python 3.10+

  • pip install "mcp[cli]"

Only have Python 3.9 (macOS's default system Python)? The mcp SDK requires 3.10+ and won't install on 3.9. Install a newer version alongside your system Python without touching it — e.g. via Homebrew:

brew install python@3.12
/opt/homebrew/bin/python3.12 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Then use .venv/bin/python, .venv/bin/pytest, etc. for this project.

Run

python server.py

Or, for local development with the MCP Inspector:

mcp dev server.py

Tool: get_election_dates

Input

field

type

required

description

state

string

yes

USPS two-letter state code (e.g. "CA") or full state name (e.g. "California"), or "DC" / "District of Columbia". Case-insensitive.

Output

{
  "state": "CA",
  "state_name": "California",
  "primary": "2026-06-02",
  "days_until_primary": -47,
  "general_election": "2026-11-03",
  "days_until_general": 107,
  "cycle": "2026",
  "source": "Federal Voting Assistance Program (FVAP.gov)",
  "source_as_of": "2026-05"
}

days_until_primary / days_until_general are computed from the current date at request time and may be negative if the date has already passed. days_until_primary is null if the state has no primary currently scheduled.

Covers the 50 states + DC only; U.S. territories and local/municipal races are out of scope (see election_dates.json metadata).

Input handling

Unrecognized input raises UnknownStateError (a ValueError subclass) with a message listing valid codes — never a silent null or an unhandled crash. Input is trimmed, internal whitespace is collapsed, and stray punctuation (e.g. "D.C.") is stripped before matching. A conservative fuzzy match (cutoff 0.82) against full state names catches common misspellings (e.g. "Calfornia" → CA); anything below that confidence fails clearly instead of guessing.

Tests

pip install -e ".[dev]"
pytest

tests/test_server.py covers: a valid two-letter code, a valid full name (case-insensitive), invalid input, DC (by code, full name, and alias), a state with no primary currently scheduled, and a snapshot-style check that general_election is identical across every state. No state in election_dates.json currently lacks a primary date, so that case is exercised via monkeypatch on a synthetic entry rather than by inserting a fabricated date into the real FVAP-sourced dataset.

Related MCP Connectors