- Standardize office codes to H|S|P across openfec_lookup_elections and the openfec://election/{cycle}/{office}[/...] resources, matching openfec_search_candidates (BREAKING for those two surfaces; internal mapping to FEC API house|senate|president preserved)
- Promote calendar `category` from free string to enum of all 18 FEC codes (20-29, 32-34, 36-40) with label legend
- Tighten pagination across 7 tools — `page`/`per_page` use int().min/max/default so JSON schema exposes bounds
- Rename openfec_search_filings output `filings` → `results` for consistency (BREAKING for clients reading structuredContent.filings)
- Validate committee_id and candidate_id format up front in search-filings
- candidate.resource returns principal_committees, parallelizes 3 upstream fetches
- committee.resource merges committee totals (graceful 404 for non-Form-3 filers)
- Both prompts .refine() to require candidate_id or candidate_name
- Add OpenFecService.getCandidateCommittees and getCommitteeTotals helpers
- Tighten output describes — results[] spell out per-mode row shapes; reuse PaginationSchema everywhere
- campaign-analysis prompt restructured: principal-committee discovery is its own step before contribution/disbursement breakdowns