Skip to main content
Glama

Server Details

Access FEC campaign finance data. Query data about candidates, money trails, and election filings.

If you are the author of this connector, you can claim ownership with GitHub, an HTTP challenge, or a DNS record. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Uptime
100.0% over 37 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
cyanheads/openfec-mcp-server
GitHub Stars
2
Server Listing
@cyanheads/openfec-mcp-server

TDQS

A4.1/5.0

Scored across 12 tools

Disambiguation4/5

Each tool targets a distinct FEC dataset or subdomain, but the four money-movement tools (contributions, disbursements, expenditures, coordinated expenditures) could be confused despite clear descriptions distinguishing Schedule A/B/E/F. The lookup vs search split is clear, and legal/calendar/elections tools are unambiguous.

Naming Consistency5/5

All tools follow the uniform openfec_verb_noun pattern with consistent verbs: get for single records, lookup for reference lookups, and search for dataset queries. The naming is predictable and scannable across all 12 tools.

Tool Count5/5

12 tools is well within the ideal range for a domain-specific read-only API. Each tool maps to a real FEC data category without redundancy, giving the server broad coverage without bloat.

Completeness5/5

The surface covers the major FEC datasets: candidates, committees, contributions, disbursements, independent and coordinated expenditures, filings, legal documents, calendar events, elections, and committee totals. No obvious dead ends or missing core operations for a read-only campaign finance lookup server.

Available Tools

12 tools
openfec_get_committee_totalsOpenfec Get Committee TotalsA
Read-onlyIdempotent
Inspect

Get pre-aggregated committee financial totals — receipts, disbursements, cash on hand, debts, and the itemized/unitemized breakdown — without paginating Schedule A. Use mode "single" (the default) with a committee_id for one committee's totals, one row per two-year cycle it has filed. Use mode "by_entity_type" to rank or screen every committee of one type (presidential, pac, party, pac-party, house-senate, ie-only) by state, designation, or a receipts/disbursements threshold.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoQuery mode. "single" returns one committee's totals, one row per cycle. "by_entity_type" returns a page of committees of one entity type, filterable and sortable across committees.single
pageNoPage number (1-indexed). Read pagination.pages in the response to see how many pages exist — a long-running committee can have more cycles than one page holds.
sortNoSort field. A "-" prefix sorts descending: "-receipts" ranks the biggest fundraisers first in by_entity_type mode, "-cycle" puts a committee's most recent cycle first in single mode.
cycleNoTwo-year election cycle (e.g., 2024). Even years only. Omit in single mode to get every cycle the committee has filed.
per_pageNoResults per page.
entity_typeNoCommittee entity type for the grouped search. Required in by_entity_type mode. house-senate covers both chambers as one group; ie-only is committees that report only independent expenditures.
committee_idNoCommittee ID (e.g., C00703975). Get IDs from openfec_search_committees results. Required in single mode; in by_entity_type mode it narrows the grouped search to that one committee.
max_receiptsNoMaximum total receipts in dollars. by_entity_type mode only.
min_receiptsNoMinimum total receipts in dollars. by_entity_type mode only.
committee_typeNoCommittee type code — H (House), S (Senate), P (Presidential), O (Super PAC), N/Q (PAC), X/Y (party). by_entity_type mode only.
committee_stateNoTwo-letter state code of the committee. by_entity_type mode only.
max_disbursementsNoMaximum total disbursements in dollars. by_entity_type mode only.
min_disbursementsNoMinimum total disbursements in dollars. by_entity_type mode only.
organization_typeNoSponsoring organization type — C (corporation), L (labor), M (membership), T (trade), V (cooperative), W (corporation without capital stock). by_entity_type mode only.
committee_designationNoCommittee designation — A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized). by_entity_type mode only.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeNoQuery mode as the server resolved it. Rows mean different things by mode — single rows are cycles of one committee, by_entity_type rows are different committees — so read this rather than inferring from the fields present.
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response carries no totals: how to broaden a search that matched nothing, or which requested position ran out when totals did match.
resultsNoCommittee totals result set; one row per cycle in single mode, one row per committee in by_entity_type mode.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching totals rows before pagination.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the operation as read-only and idempotent, so the description can focus on additional behavior. It discloses that results are pre-aggregated, that single mode returns one row per two-year cycle, and that by_entity_type mode supports ranking across committees. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly written sentences front-load the tool's purpose and data contents, then give mode usage guidance. Every sentence earns its place and no words are wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter tool with two modes, the description provides enough high-level orientation: how to select a mode, what each mode returns, and how this tool relates to Schedule A data. The detailed input schema and output schema cover the remaining specifics, so nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3 even without additional param detail in the tool description. The description adds helpful mode-level framing, but it mostly restates the schema's mode and committee_id semantics rather than adding new parameter information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get pre-aggregated committee financial totals' and enumerates the exact data fields returned. It also distinguishes this tool from raw Schedule A lookup by the phrase 'without paginating Schedule A.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when to use each mode: 'single' for one committee's totals and 'by_entity_type' for ranking or screening committees by type, state, or thresholds. It also states the default mode and that committee_id is the key input for the single mode.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_lookup_calendarOpenfec Lookup CalendarA
Read-onlyIdempotent
Inspect

Look up FEC calendar events, filing deadlines, and election dates. Use to find upcoming filing windows for a committee, locate when a federal election occurred, or scope FEC events by date range and category.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoevents = FEC calendar events. filing_deadlines = report due dates. election_dates = upcoming/past elections.events
pageNoPage number (1-indexed). Default 1.
stateNoTwo-letter state code (e.g., AZ, CA). Primarily for election_dates mode.
officeNoOffice sought (H=House, S=Senate, P=President). Election dates mode.
categoryNoCalendar category ID. 20=Commission Meetings, 21=Reporting Deadlines, 22=Conferences and Outreach, 23=AOs and Rules, 24=Other, 25=Quarterly, 26=Monthly, 27=Pre and Post-Elections, 28=EC Periods, 29=IE Periods, 32=Open Meetings, 33=Conferences, 34=Roundtables, 36=Election Dates, 37=Federal Holidays, 38=FEA Periods, 39=Executive Sessions, 40=Public Hearings. Events mode only.
max_dateNoLatest date (YYYY-MM-DD).
min_dateNoEarliest date (YYYY-MM-DD).
per_pageNoResults per page. Default 20, max 100.
descriptionNoFull-text event description search. Events mode.
report_typeNoReport type code (e.g. "Q1", "Q2"). Filing deadlines mode only.
report_yearNoReport year. Filing deadlines mode.
election_yearNoElection year. Election dates mode.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeNoQuery mode as the server resolved it. Each mode reads a different FEC dataset with its own row shape — calendar events, report due dates, or election dates — so read this rather than inferring the dataset from the fields present.
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response carries no calendar entries: how to broaden a search that matched nothing, or which requested position ran out when entries did match.
resultsNoCalendar result set; events, filing deadlines, or election dates depending on mode.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching calendar entries before pagination.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the description only needs to confirm the read-only nature and add scope; 'Look up' does that. It does not disclose pagination behavior or any operational details, but with safe read-only annotations the gap is minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, no repeating schema content. The primary purpose is front-loaded and the use cases appear in the second sentence, making it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 100% schema coverage, the schema already explains each parameter, and the output schema handles return values. The description covers the main use cases; the only meaningful gap is not routing the agent away from openfec_lookup_elections when pure election lookups are needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema carries the detailed meaning of mode, category, date filters, and report type. The description adds only a general mention of date range and category, which maps to existing parameters but provides no new semantic information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource (FEC calendar events, filing deadlines, election dates) and provides concrete use cases, so an agent understands what the tool retrieves. It is distinguishable from candidate/committee search tools, though it does not explicitly differentiate itself from the sibling openfec_lookup_elections despite overlapping election-date functionality.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit context with 'Use to find upcoming filing windows... locate when a federal election occurred, or scope FEC events by date range and category.' It lacks exclusions or alternatives such as pointing to openfec_lookup_elections, but the situations described are clear enough for common selection decisions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_lookup_electionsOpenfec Lookup ElectionsB
Read-onlyIdempotent
Inspect

Look up federal election races and candidate financial summaries. Find who's running in a race with fundraising totals, or get an aggregate race summary.

ParametersJSON Schema
NameRequiredDescriptionDefault
zipNoZIP code — finds races covering this ZIP. Search mode only.
modeNosearch = candidates in a race with financial totals. summary = aggregate race financial summary.search
pageNoPage number (1-indexed). Search mode only; explicit page is rejected in summary mode. Defaults to 1 for search.
cycleYesElection cycle year (even years only, e.g. 2024).
stateNoTwo-letter US state code (e.g., AZ, CA). Required for senate/house unless zip is provided.
officeYesOffice sought: H=House, S=Senate, P=President.
districtNoTwo-digit district number (e.g. "07"). Required for house unless zip is provided.
per_pageNoResults per page. Search mode only; defaults to 20.
election_fullNoExpand to full election period (4yr president, 6yr senate, 2yr house). Defaults to true when omitted; a ZIP-scoped search rejects it, since that endpoint has no such parameter. Carries no schema default, so an explicit value is distinguishable from an omission.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeNoQuery mode as the server resolved it. Row shapes differ by mode — search rows are per-candidate financial records, summary is one aggregate race row — so read this rather than inferring the shape from the fields present.
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response carries no election results: how to broaden a search that matched nothing, or which requested position ran out when results did match.
resultsNoElection race result set; candidate financial rows in search mode, a single aggregate summary row in summary mode.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching candidates or race summaries.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds the behavioral distinction between search and summary modes, and the schema adds mode-specific constraints (e.g., page rejected in summary mode, ZIP-scoped search rejects election_full). However, the description itself doesn't disclose these mode-specific behaviors; they live in the schema. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core purpose and a brief mode distinction. It is concise and readable, though the second sentence could arguably be folded into the first. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 9 parameters, an output schema, and mode-specific constraints. The description covers the high-level purpose and the two modes, but it doesn't mention the ZIP vs state/district routing logic or the mode-specific parameter rejections, which are important for correct invocation. The schema carries most of the burden, and the output schema exists, so this is adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 9 parameters. The description adds a high-level framing ('search = candidates in a race with financial totals, summary = aggregate race financial summary') that helps interpret mode, but it doesn't add meaning beyond the schema for most parameters. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('look up') and resource ('federal election races and candidate financial summaries'), and distinguishes two modes: finding who's running with fundraising totals, or getting an aggregate race summary. It doesn't explicitly name a sibling to differentiate from, but the resource and modes are clear enough to separate it from the sibling search tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by describing the two modes ('search' vs 'summary') and what each returns, but it doesn't explicitly state when to prefer this tool over siblings like openfec_search_candidates. The schema provides some guidance (e.g., zip vs state/district requirements), but the description itself offers no when-to-use or when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_candidatesOpenfec Search CandidatesA
Read-onlyIdempotent
Inspect

Find federal candidates by name, state, office, party, or cycle. Retrieve a specific candidate by FEC ID with financial totals. Candidate IDs start with H (House), S (Senate), or P (President) followed by exactly eight letters or digits.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoSearch-results page number (1-indexed). Defaults to 1 on the search path.
cycleNoTwo-year election cycle (even year, e.g., 2024).
partyNoThree-letter party code (e.g., DEM, REP, LIB).
queryNoFull-text candidate name search.
stateNoTwo-letter US state code (e.g., AZ, CA).
officeNoFilter by office: H=House, S=Senate, P=President.
districtNoTwo-digit district number for House candidates.
per_pageNoSearch results per page. Defaults to 20 on the search path.
candidate_idNoFEC candidate ID: H, S, or P followed by exactly eight letters or digits (e.g., P00003392, H2CO07170). Get IDs from openfec_search_candidates results. When provided, returns a single candidate with full detail.
election_yearNoSpecific election year the candidate ran in.
include_totalsNoInclude financial totals (receipts, disbursements, cash on hand). Defaults to true when fetching by candidate_id.
candidate_statusNoCandidate status: C=present, F=future, N=not yet, P=prior.
has_raised_fundsNoOnly candidates whose committee has received receipts.
incumbent_challengeNoIncumbent status: I=incumbent, C=challenger, O=open seat.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response carries no candidates: how to broaden a search that matched nothing, or which requested position ran out when candidates did match.
totalsNoFinancial totals (receipts, disbursements, cash_on_hand) when include_totals is true. One row per candidate per cycle.
candidatesNoCandidate result set; one record per match.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching candidates before pagination.
missing_totalsNoCandidates whose financial totals were not retrieved because the totals fetch hit its page cap. Re-query each one on its own with candidate_id to get its totals.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description adds the ID-prefix rule and that a specific ID returns financial totals, but much of this is also present in the schema; no rate limits, pagination behavior, or edge-case semantics are disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences front-load the core search behavior, then add the important ID-lookup variant and ID format rule. There is no filler or redundant explanation; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 14 parameters, a fully described schema, and an output schema, the description gives enough high-level orientation: what candidates are, how to filter, and how to do exact ID lookup. It could add a brief note on when the ID-lookup path is preferable, but the schema and annotations fill most operational gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 14 parameters. The description summarizes the primary filter dimensions and candidate ID format but adds no semantic detail beyond a concise overview; per the high-coverage rule, baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs ('Find', 'Retrieve') on a clear resource ('federal candidates') and names the main filter dimensions and the ID-lookup mode. It is unmistakably a candidate search, but it does not explicitly contrast itself with sibling tools like openfec_search_committees, so it stops just short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear search contexts: filter by candidate attributes or fetch a single candidate by FEC ID, and it flags the financial-totals case. There are no exclusions or named alternatives, so the agent is not told when to prefer this over openfec_search_committees, but the intended invocation is explicit enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_committeesOpenfec Search CommitteesA
Read-onlyIdempotent
Inspect

Find political committees (campaign, PAC, Super PAC, party) by name, type, candidate affiliation, or state. Retrieve a specific committee by FEC ID. Committee IDs start with C followed by exactly eight digits (e.g., C00358796).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoSearch-results page number (1-indexed). Defaults to 1 on the search path.
cycleNoTwo-year election cycle (even year).
partyNoThree-letter party code (e.g., DEM, REP).
queryNoFull-text committee name search.
stateNoTwo-letter state code.
per_pageNoSearch results per page. Defaults to 20 on the search path.
designationNoCommittee designation. A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized).
candidate_idNoFind committees linked to this candidate (authorized, leadership, joint fundraising). Get IDs from openfec_search_candidates results.
committee_idNoFEC committee ID: 'C' followed by exactly eight digits (e.g., C00358796). Get IDs from openfec_search_committees results. Returns a single committee with full detail.
committee_typeNoCommittee type code. Common: H (House), S (Senate), P (Presidential), O (Super PAC), N (PAC nonqualified), Q (PAC qualified), X (Party nonqualified), Y (Party qualified).
treasurer_nameNoFull-text treasurer name search.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response carries no committees: how to broaden a search that matched nothing, or which requested position ran out when committees did match.
committeesNoCommittee result set; one record per match.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching committees before pagination.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already indicate a read-only, idempotent operation, and the description is consistent with that. It adds useful behavioral context by disclosing the C+8-digit ID format and single-committee retrieval, but it does not describe pagination, edge cases, or result limits. With annotations covering safety, this is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise, front-loaded sentences with no filler. The first sentence establishes the core search behavior and criteria, while the second adds the ID format detail that matters for exact lookups. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 11 parameters, no required fields, and a full output schema, the description plus structured metadata provides enough to invoke the tool correctly. It does not discuss pagination behavior or rate limits, but these are not essential for correct invocation and are partially covered by the page/per_page schema descriptions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters. The description adds little beyond restating search dimensions and the committee ID format, which the schema's committee_id field already explains in equivalent detail. This meets the baseline but does not compensate beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Find political committees' and 'Retrieve a specific committee by FEC ID', with clear scope (campaign, PAC, Super PAC, party) and search attributes. It distinguishes itself from siblings by focusing on committees, but it never explicitly contrasts itself with openfec_search_candidates.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly states the intended use cases: search by name, type, candidate affiliation, or state, plus exact FEC ID lookup. It does not mention alternatives or when-not-to-use cases, so it stops short of full exclusion guidance, but the context is clear enough for an agent to select it for committee lookup.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_contributionsOpenfec Search ContributionsA
Read-onlyIdempotent
Inspect

Search itemized individual contributions (Schedule A) or get aggregate breakdowns by size, state, employer, or occupation. Use to answer "who is funding this committee?" Itemized mode requires a committee_id. Aggregate by_size/by_state can use candidate_id instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoQuery mode. "itemized" returns individual contribution records (keyset pagination). "by_size" aggregates by contribution size bucket. "by_state" aggregates by contributor state. "by_employer" aggregates by employer. "by_occupation" aggregates by occupation.itemized
pageNoPage number (1-indexed) for aggregate modes. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for aggregates.
sortNoSort field. A "-" prefix sorts descending: use "-contribution_receipt_amount" for the largest receipts first, since the ascending form leads with the most negative rows (refunds, reattributions, redesignations). Itemized only; OpenFEC sorts by "-contribution_receipt_date" when omitted.
cycleNoTwo-year election cycle (e.g., 2024). Even years only. Defaults to current cycle for itemized mode.
cursorNoOpaque pagination cursor from a previous response of this tool. Itemized mode only (keyset pagination). Valid only for an otherwise-identical call — changing any other argument, including sort, rejects the cursor; omit it to start over.
max_dateNoLatest contribution date (YYYY-MM-DD). Itemized only.
min_dateNoEarliest contribution date (YYYY-MM-DD). Itemized only.
per_pageNoResults per page.
max_amountNoMaximum contribution amount in dollars. Itemized only.
min_amountNoMinimum contribution amount in dollars. Itemized only.
candidate_idNoCandidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results. Enables by_size and by_state aggregates without a committee_id.
committee_idNoReceiving committee ID (e.g., C00703975). Get IDs from openfec_search_committees results.
is_individualNoOnly individual contributions (excludes committee-to-committee transfers). Itemized only.
contributor_zipNoZIP code prefix (starts-with match). Itemized only.
contributor_cityNoContributor city. Itemized only.
contributor_nameNoFull-text donor name search. Itemized only.
contributor_stateNoTwo-letter state code (e.g., CA). Itemized only.
contributor_employerNoFull-text employer search. Itemized only.
contributor_occupationNoFull-text occupation search. Itemized only.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeNoQuery mode as the server resolved it. "by_size" and "by_state" resolve to "by_size_candidate" / "by_state_candidate" when scoped by candidate_id — a different endpoint with different row shapes — so read this rather than assuming the mode you sent.
countNoTotal matching contributions (itemized mode). Check count_is_approximate before quoting it as a figure.
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when contributions did match, or that the total is an estimate.
resultsNoContribution result set; itemized records or aggregate buckets depending on mode.
committeeNoThe committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.
paginationNoPage-based pagination info (aggregate modes only).
totalCountNoTotal matching contributions or aggregate rows.
next_cursorNoPagination cursor for the next page of itemized results. Null when no more pages.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.
count_is_approximateNoTrue when OpenFEC reports count as an estimate rather than a tally, which it does on its highest-volume queries. Absent means the count is a tally.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint and idempotentHint annotations already establish the safety profile, and the description adds mode constraints rather than new operational behavior such as pagination or response quirks. That is useful but modest, matching the baseline for a read-style tool with annotations present.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: mode list, use case, and mode-specific ID requirement are front-loaded and each sentence carries information. The natural-language breakdown names map directly to the mode enum values.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 19-parameter tool the description plus fully documented schema and output schema cover the call correctly, including the critical committee_id requirement. It leaves by_employer/by_occupation funding requirements implicit ('by_size/by_state can use candidate_id instead' implies the others need committee_id), a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema coverage is 100%, so the description does not need to enumerate parameters; the main text adds only a couple of high-level relationships (itemized requires committee_id; by_size/by_state can use candidate_id). This earns the baseline 3 but no higher because most parameter meaning is already in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific action and resource: 'Search itemized individual contributions (Schedule A) or get aggregate breakdowns' and ties it to a concrete user intent ('who is funding this committee?'). This separates it from sibling tools that handle filings, disbursements, or expenditures.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to use the tool and mode-specific selectors: itemized requires committee_id, while by_size/by_state can use candidate_id instead. It does not explicitly name exclusions or alternatives such as search_disbursements for spending questions, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_coordinated_expendituresOpenfec Search Coordinated ExpendituresA
Read-onlyIdempotent
Inspect

Search coordinated party expenditures (Schedule F) — spending a party committee makes on behalf of a candidate it supports, in coordination with that campaign. Distinct from independent expenditures (openfec_search_expenditures), which cannot be coordinated with the candidate, and from direct contributions: coordinated expenditures carry their own statutory limits and can run into tens of millions per party in a presidential cycle. Scope with a spending committee_id, a benefiting candidate_id, or a cycle; unscoped queries span all years.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage number (1-indexed). Read pagination.pages in the response to see how many pages exist.
sortNoSort field. A "-" prefix sorts descending: use "-expenditure_amount" for the largest coordinated spending first, since the ascending form leads with the most negative rows (corrections and voided entries). OpenFEC sorts by "-expenditure_date" when omitted.
cycleNoTwo-year election cycle (e.g., 2024). Even years only. Omitting it searches every cycle on record.
max_dateNoLatest expenditure date (YYYY-MM-DD).
min_dateNoEarliest expenditure date (YYYY-MM-DD).
per_pageNoResults per page.
max_amountNoMaximum expenditure amount in dollars.
min_amountNoMinimum expenditure amount in dollars.
payee_nameNoFull-text payee name search (the vendor the party paid).
candidate_idNoBenefiting candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results.
committee_idNoSpending party committee ID (e.g., C00003418). Get IDs from openfec_search_committees results — party committees carry committee_type X or Y.

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response carries no coordinated expenditures: how to broaden a search that matched nothing, or which requested position ran out when expenditures did match.
resultsNoCoordinated expenditure result set; one record per itemized transaction.
committeeNoThe committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching coordinated expenditures before pagination.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint and idempotentHint, so the safety profile is covered. The description adds useful behavioral context beyond that: unscoped queries search all years, the data can reach tens of millions per party, and these expenditures carry their own statutory limits. This goes beyond a bare repeat of the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no filler: the first states purpose, the second distinguishes from related concepts while naming a sibling, and the third gives scoping behavior. It is front-loaded and every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter search tool with a full input schema, an output schema, and read-only/idempotent annotations, the description provides the missing conceptual and scoping context. Nothing critical is left unexplained for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds meaningful semantic grouping by identifying committee_id, candidate_id, and cycle as the primary scoping parameters. It also clarifies that omitting cycle means 'all years,' which supplements the individual parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Search coordinated party expenditures (Schedule F)') and immediately distinguishes the tool from independent expenditures and direct contributions. It names the sibling openfec_search_expenditures, so an agent can tell them apart without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says what coordinated expenditures are not — independent expenditures and direct contributions — and names the sibling for independent expenditures. It also provides scoping guidance ('Scope with a spending committee_id, a benefiting candidate_id, or a cycle') and warns that unscoped queries span all years.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_disbursementsOpenfec Search DisbursementsA
Read-onlyIdempotent
Inspect

Search itemized committee spending (Schedule B) or get aggregate breakdowns by purpose or recipient. All modes require a committee_id. Use to answer "what is this committee spending money on?" or "who is receiving payments from this committee?"

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoQuery mode. "itemized" returns individual disbursement records (keyset pagination). "by_purpose" aggregates by purpose category. "by_recipient" aggregates by recipient name. "by_recipient_id" aggregates by recipient committee ID (committee-to-committee transfers).itemized
pageNoPage number (1-indexed) for aggregate modes. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for aggregates.
sortNoSort field. A "-" prefix sorts descending: use "-disbursement_amount" for the biggest payments first, since the ascending form leads with the most negative rows (refunds and voided payments). Itemized only; OpenFEC sorts by "-disbursement_date" when omitted.
cycleNoTwo-year election cycle (e.g., 2024). Even years only. Itemized mode defaults to the current cycle when omitted — Schedule B spans all history, and an all-history scan of an active committee times out upstream. Pass an explicit cycle to search an earlier period.
cursorNoOpaque pagination cursor from a previous response of this tool. Itemized mode only (keyset pagination). Valid only for an otherwise-identical call — changing any other argument, including sort, rejects the cursor; omit it to start over.
max_dateNoLatest disbursement date (YYYY-MM-DD). Itemized only.
min_dateNoEarliest disbursement date (YYYY-MM-DD). Itemized only.
per_pageNoResults per page.
max_amountNoMaximum amount in dollars. Itemized only.
min_amountNoMinimum amount in dollars. Itemized only.
committee_idYesSpending committee ID (e.g., C00703975). Get IDs from openfec_search_committees results. Required for all modes.
recipient_cityNoRecipient city. Itemized only.
recipient_nameNoFull-text payee name search. Itemized only.
recipient_stateNoRecipient state. Itemized only.
recipient_committee_idNoRecipient committee ID (for committee-to-committee transfers). Itemized only.
disbursement_descriptionNoFull-text description search (e.g., "media buy", "consulting"). Itemized only.
disbursement_purpose_categoryNoPurpose category code. Itemized only.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeNoQuery mode as the server resolved it. Row shapes differ by mode — itemized rows are individual payments, aggregate rows are buckets with a total — so read this rather than inferring the shape from the fields present.
countNoTotal matching disbursements (itemized mode). Check count_is_approximate before quoting it as a figure.
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when disbursements did match, or that the total is an estimate.
resultsNoDisbursement result set; itemized records or aggregate buckets depending on mode.
committeeNoThe committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.
paginationNoPage-based pagination info (aggregate modes only).
totalCountNoTotal matching disbursements or aggregate rows.
next_cursorNoPagination cursor for the next page of itemized results. Null when no more pages.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.
count_is_approximateNoTrue when OpenFEC reports count as an estimate rather than a tally, which it does on its highest-volume queries. Absent means the count is a tally.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds context about the two behavior modes (itemized vs aggregate), but does not disclose other behavioral traits such as timeout behavior or pagination rules, which are left to the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The primary function is front-loaded, followed by the key requirement and illustrative use cases. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 17-parameter tool with a rich schema and output schema, the description is adequately complete at the overview level. It successfully conveys the tool's scope and purpose, while the detailed parameter semantics are already captured in the input schema. A brief nod to the mode parameter would improve it, but nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 17 parameters. The tool description only mentions committee_id, adding no semantic detail beyond what the schema provides. Baseline 3 applies since the schema carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states a specific verb ('Search') and resource ('itemized committee spending (Schedule B)'), and extends to aggregate breakdowns by purpose or recipient. It is specific enough that an agent can grasp the tool's function, though it does not explicitly name sibling tools like openfec_search_expenditures to differentiate them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit use cases: answering 'what is this committee spending money on?' or 'who is receiving payments from this committee?' and states a hard prerequisite ('All modes require a committee_id'). It does not mention exclusions or alternative tools, but the contextual signals are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_expendituresOpenfec Search ExpendituresA
Read-onlyIdempotent
Inspect

Search independent expenditures (Schedule E) — outside spending supporting or opposing federal candidates. Covers Super PACs, party committees, and other groups. Use itemized mode for individual expenditure records, or by_candidate for aggregated totals per candidate; by_candidate needs either a candidate_id or a full race scope (candidate_office alone for President, plus candidate_office_state for Senate, plus candidate_office_district as well for House).

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNoQuery mode. "itemized" returns individual expenditure records (keyset pagination). "by_candidate" returns aggregated totals per candidate by committee (page-based).itemized
pageNoPage number (1-indexed) for by_candidate mode. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for by_candidate.
sortNoSort field. A "-" prefix sorts descending: use "-expenditure_amount" for the largest outside spending first, since the ascending form leads with the most negative rows (corrections and voided entries). Itemized only; OpenFEC sorts by "-expenditure_date" when omitted.
cycleNoTwo-year election cycle (e.g., 2024). Even years only. Itemized mode defaults to the current cycle when omitted — Schedule E spans all history and an unscoped scan times out upstream. Pass an explicit cycle to search an earlier period.
cursorNoOpaque pagination cursor from a previous response of this tool. Itemized mode only (keyset pagination). Valid only for an otherwise-identical call — changing any other argument, including sort, rejects the cursor; omit it to start over.
max_dateNoLatest expenditure date (YYYY-MM-DD). Itemized only.
min_dateNoEarliest expenditure date (YYYY-MM-DD). Itemized only.
per_pageNoResults per page.
is_noticeNoOnly 24/48-hour notice filings (near-election spending). Itemized only.
max_amountNoMaximum expenditure amount in dollars. Itemized only.
min_amountNoMinimum expenditure amount in dollars. Itemized only.
payee_nameNoFull-text payee name search. Itemized only.
most_recentNoOnly the most recent version of amended filings. Itemized only — by_candidate rejects it. Defaults to true in itemized mode when omitted; pass false to see superseded versions of amended filings.
candidate_idNoTargeted candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results.
committee_idNoSpending committee ID (e.g., C00703975). Get IDs from openfec_search_committees results.
support_opposeNoS = support, O = oppose. Filter by whether the expenditure supports or opposes the candidate.
candidate_partyNoThree-letter party code of the targeted candidate (e.g., DEM, REP). Itemized only — by_candidate rejects it, since the aggregate endpoint has no party filter.
candidate_officeNoOffice of the targeted candidate: H=House, S=Senate, P=President. In by_candidate mode this scopes a whole race: P stands alone, S also needs candidate_office_state, H also needs candidate_office_state and candidate_office_district.
candidate_office_stateNoTwo-letter state code of the targeted race. Required alongside candidate_office=H or candidate_office=S in by_candidate mode; leave it off for candidate_office=P, whose aggregate rows carry no state and match nothing when one is supplied.
candidate_office_districtNoTwo-digit House district of the targeted race (e.g., "09"). Required alongside candidate_office=H and candidate_office_state in by_candidate mode; Senate and presidential rows carry no district and match nothing when one is supplied.

Output Schema

ParametersJSON Schema
NameRequiredDescription
modeNoQuery mode as the server resolved it. Row shapes differ by mode — itemized rows are individual expenditures, by_candidate rows are per-candidate totals — so read this rather than inferring the shape from the fields present.
countNoTotal matching independent expenditures (itemized mode). Check count_is_approximate before quoting it as a figure.
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when expenditures did match, or that the total is an estimate.
resultsNoExpenditure result set; itemized records or per-candidate aggregates depending on mode.
committeeNoThe committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.
paginationNoPage-based pagination info (by_candidate mode only).
totalCountNoTotal matching expenditures or per-candidate aggregates.
next_cursorNoPagination cursor for the next page of itemized results. Null when no more pages.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.
count_is_approximateNoTrue when OpenFEC reports count as an estimate rather than a tally, which it does on its highest-volume queries. Absent means the count is a tally.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds behavioral value by explaining what each mode returns and by_candidate's candidate_id/race-scope requirements, which are not obvious from the tool name alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: first the purpose, then the mode choice, then the required by_candidate scope combinations. Every sentence adds useful information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 20 parameters, the description covers the most complex decision point—choosing between itemized and by_candidate—and the by_candidate race-scope rules. The output schema and parameter-level schema descriptions cover the remaining details, so the agent has what it needs to call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 20 parameters thoroughly. The narrative description adds mode-level framing but does not provide parameter-specific meaning beyond what the schema already explains.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource ('independent expenditures (Schedule E)') with a clear verb ('Search') and adds scope ('outside spending supporting or opposing federal candidates'). It also covers what entities are included, which distinguishes it from sibling tools like coordinated expenditures.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear guidance on the two modes ('Use itemized mode for individual expenditure records, or by_candidate for aggregated totals per candidate') and explains the key by_candidate scoping requirements. It does not explicitly name alternatives or exclusion conditions, but the independent-expenditure framing is clear enough for mode selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

openfec_search_filingsOpenfec Search FilingsA
Read-onlyIdempotent
Inspect

Search FEC filings and reports by committee, candidate, form type, or date range. Covers financial reports (F3/F3P/F3X), statements of candidacy (F2), organizational filings (F1), 24-hour IE notices (F24), and amendments.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoPage number (1-indexed).
cycleNoTwo-year election cycle (even year).
per_pageNoResults per page.
form_typeNoFEC form type. Common: F3 (House/Senate quarterly), F3P (Presidential), F3X (PAC/party), F24 (24-hour IE notice), F1 (statement of organization), F2 (statement of candidacy), F5 (IE by persons).
filer_nameNoFull-text filer name search.
is_amendedNoFilter to original or amended filings only.
most_recentNoOnly the most recent version (filters out superseded amendments).
report_typeNoReport type code. Common: Q1/Q2/Q3 (quarterly), YE (year-end), M3-M12 (monthly), 12G/12P/30G (pre/post election).
report_yearNoFiling year.
candidate_idNoAssociated candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results.
committee_idNoFiling committee ID (e.g., C00358796). Get IDs from openfec_search_committees results.
max_receipt_dateNoLatest FEC receipt date (YYYY-MM-DD).
min_receipt_dateNoEarliest date FEC received the filing (YYYY-MM-DD).

Output Schema

ParametersJSON Schema
NameRequiredDescription
errorNoPresent when the call failed. Absent on success.
noticeNoGuidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when filings did match, or that the total is an estimate.
resultsNoFiling result set; one record per match.
paginationNoPage-based pagination metadata.
totalCountNoTotal matching filings before pagination.
search_criteriaNoEcho of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so there is no safety contradiction. The description adds useful context about covered form types and amendments, but it does not disclose behavioral details such as pagination behavior or how the most_recent filter interacts with amended filings.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two dense, front-loaded sentences with no filler. The first sentence states the action and resource; the second adds a useful inventory of covered form types. Every clause contributes value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The rich schema and output schema carry most of the parameter and return-value burden, while the description adds domain context about which FEC forms are covered. The main gap is lack of explicit routing guidance among sibling search tools, but nothing essential for invoking this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides 100% description coverage across all 13 parameters, including defaults, common form types, and report codes. The description only restates high-level filter dimensions already present in the schema and adds no new syntax, format, or parameter-specific guidance, so it stays at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Search') and a specific resource ('FEC filings and reports'), then enumerates the filter dimensions and form types covered. This clearly distinguishes it from sibling tools like openfec_search_contributions or openfec_search_candidates without requiring schema inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies this tool is for finding FEC filings and reports by committee, candidate, form type, or date range, but it never explicitly says when to prefer this over the sibling search tools or when not to use it. Cross-references to openfec_search_candidates and openfec_search_committees exist only in parameter descriptions, not in the main description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 11 tool updates
    • Changedopenfec_get_committee_totals2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no totals matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no totals: how to broaden a search that matched nothing, or which requested position ran out when totals did match."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_lookup_calendar2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no calendar entries matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no calendar entries: how to broaden a search that matched nothing, or which requested position ran out when entries did match."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_lookup_elections2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no election results matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no election results: how to broaden a search that matched nothing, or which requested position ran out when results did match."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_candidates2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no candidates matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no candidates: how to broaden a search that matched nothing, or which requested position ran out when candidates did match."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_committees2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no committees matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no committees: how to broaden a search that matched nothing, or which requested position ran out when committees did match."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_contributions4 fields changed
      • changedOutput schema / properties / count / description
        Previous value: -"Total result count (may be approximate for itemized)."New value: +"Total matching contributions (itemized mode). Check count_is_approximate before quoting it as a figure."
      • addedOutput schema / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports count as an estimate rather than a tally, which it does on its highest-volume queries. Absent means the count is a tally.",
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no contributions matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when contributions did match, or that the total is an estimate."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_coordinated_expenditures2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no coordinated expenditures matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no coordinated expenditures: how to broaden a search that matched nothing, or which requested position ran out when expenditures did match."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_disbursements4 fields changed
      • changedOutput schema / properties / count / description
        Previous value: -"Total result count (may be approximate for itemized)."New value: +"Total matching disbursements (itemized mode). Check count_is_approximate before quoting it as a figure."
      • addedOutput schema / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports count as an estimate rather than a tally, which it does on its highest-volume queries. Absent means the count is a tally.",
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no disbursements matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when disbursements did match, or that the total is an estimate."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_expenditures4 fields changed
      • changedOutput schema / properties / count / description
        Previous value: -"Total result count (may be approximate for itemized)."New value: +"Total matching independent expenditures (itemized mode). Check count_is_approximate before quoting it as a figure."
      • addedOutput schema / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports count as an estimate rather than a tally, which it does on its highest-volume queries. Absent means the count is a tally.",
        +  "type": "boolean"
        +}
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no expenditures matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when expenditures did match, or that the total is an estimate."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_filings2 fields changed
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no filings matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when filings did match, or that the total is an estimate."
      • addedOutput schema / properties / pagination / properties / count_is_approximate
        Added value: +{
        +  "description": "True when OpenFEC reports this count as an estimate rather than a tally, which it does on its highest-volume datasets. Absent means the count is a tally. An estimated count — and the pages derived from it — can be off by a wide margin; treat it as an order of magnitude, not a figure to quote.",
        +  "type": "boolean"
        +}
    • Changedopenfec_search_legal6 fields changed
      • changedInput schema / properties / from_hit / description
        Previous value: -"Offset for pagination (0-indexed). Default 0."New value: +"Offset for pagination (0-indexed), counted within each document type rather than across them. Default 0. The search index serves a 10,000-result window, so from_hit plus hits_returned must be 10,000 or less — the ceiling here assumes hits_returned of 1."
      • changedInput schema / properties / from_hit / maximum
        Previous value: -9007199254740991New value: +9999
      • changedInput schema / properties / hits_returned / description
        Previous value: -"Results per page. Default 20, max 200."New value: +"Results per page, applied per document type. Default 20, max 200. Bounded together with from_hit by the 10,000-result window."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `missing_filter`: Called without any scoping filter at all. `date_filter_incomplete`: min_date or max_date given without both a type and a date_kind, or a date_kind given with neither bound. `date_kind_not_valid_for_type`: The requested date_kind is not a date this document type records. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `missing_filter`: Called without any scoping filter at all. `date_filter_incomplete`: min_date or max_date given without both a type and a date_kind, or a date_kind given with neither bound. `date_kind_not_valid_for_type`: The requested date_kind is not a date this document type records. `legal_window_exceeded`: from_hit plus hits_returned exceeds the 10,000-result window the search index serves. Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "missing_filter",
        -  "date_filter_incomplete",
        -  "date_kind_not_valid_for_type"
        -]New value: +[
        +  "missing_filter",
        +  "date_filter_incomplete",
        +  "date_kind_not_valid_for_type",
        +  "legal_window_exceeded"
        +]
      • changedOutput schema / properties / notice / description
        Previous value: -"Guidance when no legal documents matched — echoes filters and suggests how to broaden."New value: +"Guidance when the response carries no legal documents: how to broaden a search that matched nothing, or that from_hit ran past the end when documents did match."
  2. 10 tool updates
    • Changedopenfec_get_committee_totals1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `committee_id_required_for_single_mode`: Mode single invoked without a committee_id `entity_type_required_for_group_mode`: Mode by_entity_type invoked without an entity_type `inputs_not_applicable_to_mode`: A grouped-search filter (entity_type, committee_state, committee_type, committee_designation, organization_type, or a receipts/disbursements bound) was supplied alongside mode single, which cannot apply it `committee_totals_not_found`: Single-committee lookup matched no totals row — the committee_id does not exist, it filed nothing in the requested cycle, or it has never filed a financial report at all Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `committee_id_required_for_single_mode`: Mode single invoked without a committee_id. `entity_type_required_for_group_mode`: Mode by_entity_type invoked without an entity_type. `inputs_not_applicable_to_mode`: A grouped-search filter (entity_type, committee_state, committee_type, committee_designation, organization_type, or a receipts/disbursements bound) was supplied alongside mode single, which cannot apply it. `committee_totals_not_found`: Single-committee lookup matched no totals row — the committee_id does not exist, it filed nothing in the requested cycle, or it has never filed a financial report at all. Other values are possible when a failure originates below the handler."
    • Changedopenfec_get_legal_document1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `legal_document_not_found`: No legal document exists at the requested doc_type and no Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `legal_document_not_found`: No legal document exists at the requested doc_type and document number. Other values are possible when a failure originates below the handler."
    • Changedopenfec_lookup_calendar1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `inputs_not_applicable_to_mode`: A filter belonging to a different calendar mode was supplied, which the chosen mode cannot apply Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `inputs_not_applicable_to_mode`: A filter belonging to a different calendar mode was supplied, which the chosen mode cannot apply. Other values are possible when a failure originates below the handler."
    • Changedopenfec_lookup_elections1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `cycle_must_be_even`: Cycle is an odd year `missing_state_for_office`: Senate or House office without a state and without a zip `missing_district_for_house`: House office without a district number and without a zip `summary_does_not_support_zip`: Summary mode invoked with a zip parameter `inputs_not_applicable_to_mode`: The resolved elections endpoint does not accept one or more explicitly supplied inputs Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `cycle_must_be_even`: Cycle is an odd year. `missing_state_for_office`: Senate or House office without a state and without a zip. `missing_district_for_house`: House office without a district number and without a zip. `summary_does_not_support_zip`: Summary mode invoked with a zip parameter. `inputs_not_applicable_to_mode`: The resolved elections endpoint does not accept one or more explicitly supplied inputs. Other values are possible when a failure originates below the handler."
    • Changedopenfec_search_candidates1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `candidate_not_found`: Single-candidate lookup by candidate_id returned no record `inputs_not_applicable_to_id_lookup`: A direct candidate_id lookup includes search-only inputs, or totals-only scope while include_totals is false Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `candidate_not_found`: Single-candidate lookup by candidate_id returned no record. `inputs_not_applicable_to_id_lookup`: A direct candidate_id lookup includes search-only inputs, or totals-only scope while include_totals is false. Other values are possible when a failure originates below the handler."
    • Changedopenfec_search_committees1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `committee_not_found`: Single-committee lookup by committee_id returned no record `inputs_not_applicable_to_id_lookup`: A direct committee_id lookup includes inputs that only the committee search endpoint supports Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `committee_not_found`: Single-committee lookup by committee_id returned no record. `inputs_not_applicable_to_id_lookup`: A direct committee_id lookup includes inputs that only the committee search endpoint supports. Other values are possible when a failure originates below the handler."
    • Changedopenfec_search_contributions3 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `itemized_requires_committee_id`: Itemized mode invoked without a committee_id `aggregate_requires_committee_id`: by_employer or by_occupation aggregate without a committee_id `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it `inputs_not_applicable_to_mode`: The resolved Schedule A endpoint does not accept one or more explicitly supplied inputs Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `itemized_requires_committee_id`: Itemized mode invoked without a committee_id. `aggregate_requires_committee_id`: by_employer or by_occupation aggregate without a committee_id. `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it. `inputs_not_applicable_to_mode`: The resolved Schedule A endpoint does not accept one or more explicitly supplied inputs. Other values are possible when a failure originates below the handler."
      • removedOutput schema / properties / next_cursor / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / next_cursor / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedopenfec_search_disbursements3 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it `inputs_not_applicable_to_mode`: Itemized mode receives an explicit page number that its keyset endpoint cannot apply Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it. `inputs_not_applicable_to_mode`: Itemized mode receives an explicit page number that its keyset endpoint cannot apply. Other values are possible when a failure originates below the handler."
      • removedOutput schema / properties / next_cursor / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / next_cursor / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedopenfec_search_expenditures3 fields changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `by_candidate_requires_scope`: by_candidate mode invoked without a candidate_id and without a full race scope `itemized_only_filters_in_aggregate_mode`: An itemized-only filter (payee_name, candidate_party, a date or amount bound, is_notice, most_recent, sort, cursor) was supplied alongside mode by_candidate, which cannot apply it `inputs_not_applicable_to_mode`: Itemized mode receives an explicit page number that its keyset endpoint cannot apply Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `by_candidate_requires_scope`: by_candidate mode invoked without a candidate_id and without a full race scope. `itemized_only_filters_in_aggregate_mode`: An itemized-only filter (payee_name, candidate_party, a date or amount bound, is_notice, most_recent, sort, cursor) was supplied alongside mode by_candidate, which cannot apply it. `inputs_not_applicable_to_mode`: Itemized mode receives an explicit page number that its keyset endpoint cannot apply. Other values are possible when a failure originates below the handler."
      • removedOutput schema / properties / next_cursor / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / next_cursor / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedopenfec_search_legal1 field changed
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `missing_filter`: Called without any scoping filter at all `date_filter_incomplete`: min_date or max_date given without both a type and a date_kind, or a date_kind given with neither bound `date_kind_not_valid_for_type`: The requested date_kind is not a date this document type records Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `missing_filter`: Called without any scoping filter at all. `date_filter_incomplete`: min_date or max_date given without both a type and a date_kind, or a date_kind given with neither bound. `date_kind_not_valid_for_type`: The requested date_kind is not a date this document type records. Other values are possible when a failure originates below the handler."
  3. 6 tool updates
    • Changedopenfec_lookup_elections5 fields changed
      • removedInput schema / properties / page / default
        Removed value: -1
      • changedInput schema / properties / page / description
        Previous value: -"Page number (1-indexed). Search mode only — summary mode returns a single aggregate row. Read pagination.pages in the response to see how many pages exist."New value: +"Page number (1-indexed). Search mode only; explicit page is rejected in summary mode. Defaults to 1 for search."
      • removedInput schema / properties / per_page / default
        Removed value: -20
      • changedInput schema / properties / per_page / description
        Previous value: -"Results per page. Search mode only."New value: +"Results per page. Search mode only; defaults to 20."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `cycle_must_be_even`: Cycle is an odd year `missing_state_for_office`: Senate or House office without a state and without a zip `missing_district_for_house`: House office without a district number and without a zip `summary_does_not_support_zip`: Summary mode invoked with a zip parameter `inputs_not_applicable_to_mode`: election_full supplied alongside zip — a ZIP-scoped search runs an endpoint that has no such parameter Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `cycle_must_be_even`: Cycle is an odd year `missing_state_for_office`: Senate or House office without a state and without a zip `missing_district_for_house`: House office without a district number and without a zip `summary_does_not_support_zip`: Summary mode invoked with a zip parameter `inputs_not_applicable_to_mode`: The resolved elections endpoint does not accept one or more explicitly supplied inputs Other values are possible when a failure originates below the handler."
    • Changedopenfec_search_candidates7 fields changed
      • changedInput schema / properties / candidate_id / description
        Previous value: -"FEC candidate ID (e.g., P00003392, H2CO07170). Get IDs from openfec_search_candidates results. When provided, returns a single candidate with full detail."New value: +"FEC candidate ID: H, S, or P followed by exactly eight letters or digits (e.g., P00003392, H2CO07170). Get IDs from openfec_search_candidates results. When provided, returns a single candidate with full detail."
      • removedInput schema / properties / page / default
        Removed value: -1
      • changedInput schema / properties / page / description
        Previous value: -"Page number (1-indexed)."New value: +"Search-results page number (1-indexed). Defaults to 1 on the search path."
      • removedInput schema / properties / per_page / default
        Removed value: -20
      • changedInput schema / properties / per_page / description
        Previous value: -"Results per page."New value: +"Search results per page. Defaults to 20 on the search path."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `candidate_not_found`: Single-candidate lookup by candidate_id returned no record Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `candidate_not_found`: Single-candidate lookup by candidate_id returned no record `inputs_not_applicable_to_id_lookup`: A direct candidate_id lookup includes search-only inputs, or totals-only scope while include_totals is false Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "candidate_not_found"
        -]New value: +[
        +  "candidate_not_found",
        +  "inputs_not_applicable_to_id_lookup"
        +]
    • Changedopenfec_search_committees7 fields changed
      • changedInput schema / properties / committee_id / description
        Previous value: -"FEC committee ID (e.g., C00358796). Get IDs from openfec_search_committees results. Starts with 'C' followed by digits. Returns a single committee with full detail."New value: +"FEC committee ID: 'C' followed by exactly eight digits (e.g., C00358796). Get IDs from openfec_search_committees results. Returns a single committee with full detail."
      • removedInput schema / properties / page / default
        Removed value: -1
      • changedInput schema / properties / page / description
        Previous value: -"Page number (1-indexed)."New value: +"Search-results page number (1-indexed). Defaults to 1 on the search path."
      • removedInput schema / properties / per_page / default
        Removed value: -20
      • changedInput schema / properties / per_page / description
        Previous value: -"Results per page."New value: +"Search results per page. Defaults to 20 on the search path."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `committee_not_found`: Single-committee lookup by committee_id returned no record Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `committee_not_found`: Single-committee lookup by committee_id returned no record `inputs_not_applicable_to_id_lookup`: A direct committee_id lookup includes inputs that only the committee search endpoint supports Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "committee_not_found"
        -]New value: +[
        +  "committee_not_found",
        +  "inputs_not_applicable_to_id_lookup"
        +]
    • Changedopenfec_search_contributions4 fields changed
      • removedInput schema / properties / page / default
        Removed value: -1
      • changedInput schema / properties / page / description
        Previous value: -"Page number (1-indexed) for the aggregate modes. Ignored in itemized mode, which paginates with cursor. Read pagination.pages in the response to see how many pages exist."New value: +"Page number (1-indexed) for aggregate modes. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for aggregates."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `itemized_requires_committee_id`: Itemized mode invoked without a committee_id `aggregate_requires_committee_id`: by_employer or by_occupation aggregate without a committee_id `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `itemized_requires_committee_id`: Itemized mode invoked without a committee_id `aggregate_requires_committee_id`: by_employer or by_occupation aggregate without a committee_id `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it `inputs_not_applicable_to_mode`: The resolved Schedule A endpoint does not accept one or more explicitly supplied inputs Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "itemized_requires_committee_id",
        -  "aggregate_requires_committee_id",
        -  "itemized_only_filters_in_aggregate_mode"
        -]New value: +[
        +  "itemized_requires_committee_id",
        +  "aggregate_requires_committee_id",
        +  "itemized_only_filters_in_aggregate_mode",
        +  "inputs_not_applicable_to_mode"
        +]
    • Changedopenfec_search_disbursements4 fields changed
      • removedInput schema / properties / page / default
        Removed value: -1
      • changedInput schema / properties / page / description
        Previous value: -"Page number (1-indexed) for the aggregate modes. Ignored in itemized mode, which paginates with cursor. Read pagination.pages in the response to see how many pages exist."New value: +"Page number (1-indexed) for aggregate modes. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for aggregates."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it `inputs_not_applicable_to_mode`: Itemized mode receives an explicit page number that its keyset endpoint cannot apply Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "itemized_only_filters_in_aggregate_mode"
        -]New value: +[
        +  "itemized_only_filters_in_aggregate_mode",
        +  "inputs_not_applicable_to_mode"
        +]
    • Changedopenfec_search_expenditures4 fields changed
      • removedInput schema / properties / page / default
        Removed value: -1
      • changedInput schema / properties / page / description
        Previous value: -"Page number (1-indexed) for by_candidate mode. Ignored in itemized mode, which paginates with cursor. Read pagination.pages in the response to see how many pages exist."New value: +"Page number (1-indexed) for by_candidate mode. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for by_candidate."
      • changedOutput schema / properties / error / properties / data / properties / reason / description
        Previous value: -"Machine-readable failure mode. Declared by this tool: `by_candidate_requires_scope`: by_candidate mode invoked without a candidate_id and without a full race scope `itemized_only_filters_in_aggregate_mode`: An itemized-only filter (payee_name, candidate_party, a date or amount bound, is_notice, most_recent, sort, cursor) was supplied alongside mode by_candidate, which cannot apply it Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `by_candidate_requires_scope`: by_candidate mode invoked without a candidate_id and without a full race scope `itemized_only_filters_in_aggregate_mode`: An itemized-only filter (payee_name, candidate_party, a date or amount bound, is_notice, most_recent, sort, cursor) was supplied alongside mode by_candidate, which cannot apply it `inputs_not_applicable_to_mode`: Itemized mode receives an explicit page number that its keyset endpoint cannot apply Other values are possible when a failure originates below the handler."
      • changedOutput schema / properties / error / properties / data / properties / reason / examples
        Previous value: -[
        -  "by_candidate_requires_scope",
        -  "itemized_only_filters_in_aggregate_mode"
        -]New value: +[
        +  "by_candidate_requires_scope",
        +  "itemized_only_filters_in_aggregate_mode",
        +  "inputs_not_applicable_to_mode"
        +]
  4. 12 tool updates
    • Changedopenfec_get_committee_totals6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "mode",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `committee_id_required_for_single_mode`: Mode single invoked without a committee_id `entity_type_required_for_group_mode`: Mode by_entity_type invoked without an entity_type `inputs_not_applicable_to_mode`: A grouped-search filter (entity_type, committee_state, committee_type, committee_designation, organization_type, or a receipts/disbursements bound) was supplied alongside mode single, which cannot apply it `committee_totals_not_found`: Single-committee lookup matched no totals row — the committee_id does not exist, it filed nothing in the requested cycle, or it has never filed a financial report at all Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "committee_id_required_for_single_mode",
        +            "entity_type_required_for_group_mode",
        +            "inputs_not_applicable_to_mode",
        +            "committee_totals_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "mode",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_get_legal_document6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "document",
        +      "search_criteria",
        +      "attachedDocumentCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `legal_document_not_found`: No legal document exists at the requested doc_type and no Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "legal_document_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "document",
        -  "search_criteria",
        -  "attachedDocumentCount"
        -]
    • Changedopenfec_lookup_calendar6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "mode",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `inputs_not_applicable_to_mode`: A filter belonging to a different calendar mode was supplied, which the chosen mode cannot apply Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "inputs_not_applicable_to_mode"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "mode",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_lookup_elections6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "mode",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `cycle_must_be_even`: Cycle is an odd year `missing_state_for_office`: Senate or House office without a state and without a zip `missing_district_for_house`: House office without a district number and without a zip `summary_does_not_support_zip`: Summary mode invoked with a zip parameter `inputs_not_applicable_to_mode`: election_full supplied alongside zip — a ZIP-scoped search runs an endpoint that has no such parameter Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "cycle_must_be_even",
        +            "missing_state_for_office",
        +            "missing_district_for_house",
        +            "summary_does_not_support_zip",
        +            "inputs_not_applicable_to_mode"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "mode",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_candidates6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "candidates",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `candidate_not_found`: Single-candidate lookup by candidate_id returned no record Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "candidate_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "candidates",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_committees6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "committees",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `committee_not_found`: Single-committee lookup by committee_id returned no record Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "committee_not_found"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "committees",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_contributions6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "mode",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `itemized_requires_committee_id`: Itemized mode invoked without a committee_id `aggregate_requires_committee_id`: by_employer or by_occupation aggregate without a committee_id `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "itemized_requires_committee_id",
        +            "aggregate_requires_committee_id",
        +            "itemized_only_filters_in_aggregate_mode"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "mode",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_coordinated_expenditures6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode.",
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_disbursements6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "mode",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `itemized_only_filters_in_aggregate_mode`: An itemized-only filter was supplied alongside an aggregate mode, which cannot apply it Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "itemized_only_filters_in_aggregate_mode"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "mode",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_expenditures6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "mode",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `by_candidate_requires_scope`: by_candidate mode invoked without a candidate_id and without a full race scope `itemized_only_filters_in_aggregate_mode`: An itemized-only filter (payee_name, candidate_party, a date or amount bound, is_notice, most_recent, sort, cursor) was supplied alongside mode by_candidate, which cannot apply it Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "by_candidate_requires_scope",
        +            "itemized_only_filters_in_aggregate_mode"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "mode",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_filings6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "pagination",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode.",
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "pagination",
        -  "search_criteria",
        -  "totalCount"
        -]
    • Changedopenfec_search_legal6 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / additionalProperties
        Added value: +false
      • changedOutput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedOutput schema / anyOf
        Added value: +[
        +  {
        +    "not": {
        +      "required": [
        +        "error"
        +      ]
        +    },
        +    "required": [
        +      "results",
        +      "total_count",
        +      "search_criteria",
        +      "totalCount"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "error"
        +    ]
        +  }
        +]
      • addedOutput schema / properties / error
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the call failed. Absent on success.",
        +  "properties": {
        +    "code": {
        +      "description": "JSON-RPC error code for this failure.",
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "data": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "reason": {
        +          "description": "Machine-readable failure mode. Declared by this tool: `missing_filter`: Called without any scoping filter at all `date_filter_incomplete`: min_date or max_date given without both a type and a date_kind, or a date_kind given with neither bound `date_kind_not_valid_for_type`: The requested date_kind is not a date this document type records Other values are possible when a failure originates below the handler.",
        +          "examples": [
        +            "missing_filter",
        +            "date_filter_incomplete",
        +            "date_kind_not_valid_for_type"
        +          ],
        +          "type": "string"
        +        },
        +        "recovery": {
        +          "additionalProperties": {},
        +          "description": "Actionable next step for the caller.",
        +          "properties": {
        +            "hint": {
        +              "type": "string"
        +            }
        +          },
        +          "required": [
        +            "hint"
        +          ],
        +          "type": "object"
        +        },
        +        "retryable": {
        +          "description": "Whether retrying may succeed.",
        +          "type": "boolean"
        +        }
        +      },
        +      "type": "object"
        +    },
        +    "message": {
        +      "description": "Human-readable description of what went wrong.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "code",
        +    "message"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / required
        Removed value: -[
        -  "results",
        -  "total_count",
        -  "search_criteria",
        -  "totalCount"
        -]
  5. 4 tool updates
    • Addedopenfec_get_committee_totals
    • Addedopenfec_get_legal_document
    • Addedopenfec_search_coordinated_expenditures
    • Changedopenfec_search_legal2 fields changed
      • changedOutput schema / properties / results / items / description
        Previous value: -"Legal document record. The document_type field discriminates among advisory_opinion, mur, adr, admin_fine, and statute. Common fields include ao_no/case_no/no (identifier), name, document_type, document_count, and document_categories summarizing the related filings."New value: +"Legal document record. The document_type field discriminates among advisory_opinion, mur, adr, admin_fine, and statute. Common fields include no (the identifier every type carries, and the one openfec_get_legal_document takes; advisory opinions repeat it as ao_no), name, document_type, document_count, and document_categories summarizing the related filings."
      • addedOutput schema / properties / retrievalHint
        Added value: +{
        +  "description": "How to recover the material trimmed out of these results. Present whenever any result was returned, because every result is trimmed.",
        +  "type": "string"
        +}
  6. 9 tool updates
    • Changedopenfec_lookup_calendar3 fields changed
      • addedOutput schema / properties / mode
        Added value: +{
        +  "description": "Query mode as the server resolved it. Each mode reads a different FEC dataset with its own row shape — calendar events, report due dates, or election dates — so read this rather than inferring the dataset from the fields present.",
        +  "enum": [
        +    "events",
        +    "filing_deadlines",
        +    "election_dates"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "pagination",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "mode",
        +  "pagination",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_lookup_elections5 fields changed
      • removedInput schema / properties / election_full / default
        Removed value: -true
      • changedInput schema / properties / election_full / description
        Previous value: -"Expand to full election period (4yr president, 6yr senate, 2yr house). Default true. Ignored for ZIP-based searches."New value: +"Expand to full election period (4yr president, 6yr senate, 2yr house). Defaults to true when omitted; a ZIP-scoped search rejects it, since that endpoint has no such parameter. Carries no schema default, so an explicit value is distinguishable from an omission."
      • addedOutput schema / properties / mode
        Added value: +{
        +  "description": "Query mode as the server resolved it. Row shapes differ by mode — search rows are per-candidate financial records, summary is one aggregate race row — so read this rather than inferring the shape from the fields present.",
        +  "enum": [
        +    "search",
        +    "summary"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "pagination",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "mode",
        +  "pagination",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_candidates2 fields changed
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "candidates",
        -  "pagination",
        -  "totalCount"
        -]New value: +[
        +  "candidates",
        +  "pagination",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_committees2 fields changed
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "committees",
        -  "pagination",
        -  "totalCount"
        -]New value: +[
        +  "committees",
        +  "pagination",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_contributions4 fields changed
      • addedOutput schema / properties / committee
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "The committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.",
        +  "properties": {},
        +  "type": "object"
        +}
      • addedOutput schema / properties / mode
        Added value: +{
        +  "description": "Query mode as the server resolved it. \"by_size\" and \"by_state\" resolve to \"by_size_candidate\" / \"by_state_candidate\" when scoped by candidate_id — a different endpoint with different row shapes — so read this rather than assuming the mode you sent.",
        +  "enum": [
        +    "itemized",
        +    "by_size",
        +    "by_state",
        +    "by_employer",
        +    "by_occupation",
        +    "by_size_candidate",
        +    "by_state_candidate"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "mode",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_disbursements4 fields changed
      • addedOutput schema / properties / committee
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "The committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.",
        +  "properties": {},
        +  "type": "object"
        +}
      • addedOutput schema / properties / mode
        Added value: +{
        +  "description": "Query mode as the server resolved it. Row shapes differ by mode — itemized rows are individual payments, aggregate rows are buckets with a total — so read this rather than inferring the shape from the fields present.",
        +  "enum": [
        +    "itemized",
        +    "by_purpose",
        +    "by_recipient",
        +    "by_recipient_id"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "mode",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_expenditures6 fields changed
      • removedInput schema / properties / most_recent / default
        Removed value: -true
      • changedInput schema / properties / most_recent / description
        Previous value: -"Only the most recent version of amended filings. Itemized only."New value: +"Only the most recent version of amended filings. Itemized only — by_candidate rejects it. Defaults to true in itemized mode when omitted; pass false to see superseded versions of amended filings."
      • addedOutput schema / properties / committee
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "The committee every row in this response belongs to, carried once instead of repeated in each row. Present only when the query was scoped to a single committee_id; otherwise each row keeps its own committee object.",
        +  "properties": {},
        +  "type": "object"
        +}
      • addedOutput schema / properties / mode
        Added value: +{
        +  "description": "Query mode as the server resolved it. Row shapes differ by mode — itemized rows are individual expenditures, by_candidate rows are per-candidate totals — so read this rather than inferring the shape from the fields present.",
        +  "enum": [
        +    "itemized",
        +    "by_candidate"
        +  ],
        +  "type": "string"
        +}
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "mode",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_filings2 fields changed
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "pagination",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "pagination",
        +  "search_criteria",
        +  "totalCount"
        +]
    • Changedopenfec_search_legal2 fields changed
      • changedOutput schema / properties / search_criteria / description
        Previous value: -"Echo of the search filters that produced this result set. Populated when results are empty to help diagnose why nothing matched."New value: +"Echo of the search filters this call applied, as the server parsed them, minus paging arguments. Always present — compare it against what you sent to confirm every filter was honoured."
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "total_count",
        -  "totalCount"
        -]New value: +[
        +  "results",
        +  "total_count",
        +  "search_criteria",
        +  "totalCount"
        +]
  7. 3 tool updates
    • Changedopenfec_search_disbursements1 field changed
      • changedInput schema / properties / cycle / description
        Previous value: -"Two-year election cycle (e.g., 2024). Even years only."New value: +"Two-year election cycle (e.g., 2024). Even years only. Itemized mode defaults to the current cycle when omitted — Schedule B spans all history, and an all-history scan of an active committee times out upstream. Pass an explicit cycle to search an earlier period."
    • Changedopenfec_search_expenditures5 fields changed
      • changedInput schema / properties / candidate_office / description
        Previous value: -"Office of the targeted candidate: H=House, S=Senate, P=President."New value: +"Office of the targeted candidate: H=House, S=Senate, P=President. In by_candidate mode this scopes a whole race: P stands alone, S also needs candidate_office_state, H also needs candidate_office_state and candidate_office_district."
      • addedInput schema / properties / candidate_office_district
        Added value: +{
        +  "description": "Two-digit House district of the targeted race (e.g., \"09\"). Required alongside candidate_office=H and candidate_office_state in by_candidate mode; Senate and presidential rows carry no district and match nothing when one is supplied.",
        +  "type": "string"
        +}
      • changedInput schema / properties / candidate_office_state / description
        Previous value: -"Two-letter state code of the targeted race."New value: +"Two-letter state code of the targeted race. Required alongside candidate_office=H or candidate_office=S in by_candidate mode; leave it off for candidate_office=P, whose aggregate rows carry no state and match nothing when one is supplied."
      • changedInput schema / properties / candidate_party / description
        Previous value: -"Three-letter party code of the targeted candidate (e.g., DEM, REP)."New value: +"Three-letter party code of the targeted candidate (e.g., DEM, REP). Itemized only — by_candidate rejects it, since the aggregate endpoint has no party filter."
      • changedInput schema / properties / cycle / description
        Previous value: -"Two-year election cycle (e.g., 2024). Even years only."New value: +"Two-year election cycle (e.g., 2024). Even years only. Itemized mode defaults to the current cycle when omitted — Schedule E spans all history and an unscoped scan times out upstream. Pass an explicit cycle to search an earlier period."
    • Changedopenfec_search_legal5 fields changed
      • addedInput schema / properties / date_kind
        Added value: +{
        +  "description": "Which date min_date/max_date bound. Each document type records its own dates, so this must be one the chosen type has: type=advisory_opinions → issue_date (opinion issued), request_date (request received), document_date; type=murs or adrs → open_date (case opened), close_date (case closed), document_date; type=admin_fines → rtb_date (reason-to-believe finding), fd_date (final determination). type=statutes cannot be date-filtered. Required whenever min_date or max_date is given, together with type.",
        +  "enum": [
        +    "issue_date",
        +    "request_date",
        +    "open_date",
        +    "close_date",
        +    "document_date",
        +    "rtb_date",
        +    "fd_date"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / max_date / description
        Previous value: -"Latest document date (YYYY-MM-DD)."New value: +"Latest date (YYYY-MM-DD) for the date_kind selected. Requires type and date_kind."
      • changedInput schema / properties / max_penalty_amount / description
        Previous value: -"Maximum penalty amount."New value: +"Maximum penalty amount in dollars. Filters enforcement cases (murs, adrs) only — other document types are returned unfiltered by it."
      • changedInput schema / properties / min_date / description
        Previous value: -"Earliest document date (YYYY-MM-DD)."New value: +"Earliest date (YYYY-MM-DD) for the date_kind selected. Requires type and date_kind."
      • changedInput schema / properties / min_penalty_amount / description
        Previous value: -"Minimum penalty amount (enforcement cases)."New value: +"Minimum penalty amount in dollars. Filters enforcement cases (murs, adrs) only — other document types are returned unfiltered by it."
  8. 5 tool updates
    • Changedopenfec_lookup_elections2 fields changed
      • addedInput schema / properties / page
        Added value: +{
        +  "default": 1,
        +  "description": "Page number (1-indexed). Search mode only — summary mode returns a single aggregate row. Read pagination.pages in the response to see how many pages exist.",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • addedInput schema / properties / per_page
        Added value: +{
        +  "default": 20,
        +  "description": "Results per page. Search mode only.",
        +  "maximum": 100,
        +  "minimum": 1,
        +  "type": "integer"
        +}
    • Changedopenfec_search_candidates2 fields changed
      • addedOutput schema / properties / missing_totals
        Added value: +{
        +  "description": "Candidates whose financial totals were not retrieved because the totals fetch hit its page cap. Re-query each one on its own with candidate_id to get its totals.",
        +  "items": {
        +    "description": "FEC candidate ID with no totals row in this response.",
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / totals / description
        Previous value: -"Financial totals (receipts, disbursements, cash_on_hand) when include_totals is true."New value: +"Financial totals (receipts, disbursements, cash_on_hand) when include_totals is true. One row per candidate per cycle."
    • Changedopenfec_search_contributions1 field changed
      • addedInput schema / properties / page
        Added value: +{
        +  "default": 1,
        +  "description": "Page number (1-indexed) for the aggregate modes. Ignored in itemized mode, which paginates with cursor. Read pagination.pages in the response to see how many pages exist.",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
    • Changedopenfec_search_disbursements1 field changed
      • addedInput schema / properties / page
        Added value: +{
        +  "default": 1,
        +  "description": "Page number (1-indexed) for the aggregate modes. Ignored in itemized mode, which paginates with cursor. Read pagination.pages in the response to see how many pages exist.",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
    • Changedopenfec_search_expenditures1 field changed
      • addedInput schema / properties / page
        Added value: +{
        +  "default": 1,
        +  "description": "Page number (1-indexed) for by_candidate mode. Ignored in itemized mode, which paginates with cursor. Read pagination.pages in the response to see how many pages exist.",
        +  "maximum": 9007199254740991,
        +  "minimum": 1,
        +  "type": "integer"
        +}
  9. 3 tool updates
    • Changedopenfec_search_contributions3 fields changed
      • changedInput schema / properties / cursor / description
        Previous value: -"Opaque pagination cursor from a previous response. Itemized mode only (keyset pagination)."New value: +"Opaque pagination cursor from a previous response of this tool. Itemized mode only (keyset pagination). Valid only for an otherwise-identical call — changing any other argument, including sort, rejects the cursor; omit it to start over."
      • changedInput schema / properties / sort / description
        Previous value: -"Sort field. Itemized only."New value: +"Sort field. A \"-\" prefix sorts descending: use \"-contribution_receipt_amount\" for the largest receipts first, since the ascending form leads with the most negative rows (refunds, reattributions, redesignations). Itemized only; OpenFEC sorts by \"-contribution_receipt_date\" when omitted."
      • changedInput schema / properties / sort / enum
        Previous value: -[
        -  "contribution_receipt_date",
        -  "contribution_receipt_amount"
        -]New value: +[
        +  "contribution_receipt_date",
        +  "-contribution_receipt_date",
        +  "contribution_receipt_amount",
        +  "-contribution_receipt_amount"
        +]
    • Changedopenfec_search_disbursements3 fields changed
      • changedInput schema / properties / cursor / description
        Previous value: -"Opaque pagination cursor from a previous response. Itemized mode only (keyset pagination)."New value: +"Opaque pagination cursor from a previous response of this tool. Itemized mode only (keyset pagination). Valid only for an otherwise-identical call — changing any other argument, including sort, rejects the cursor; omit it to start over."
      • changedInput schema / properties / sort / description
        Previous value: -"Sort field. Itemized only."New value: +"Sort field. A \"-\" prefix sorts descending: use \"-disbursement_amount\" for the biggest payments first, since the ascending form leads with the most negative rows (refunds and voided payments). Itemized only; OpenFEC sorts by \"-disbursement_date\" when omitted."
      • changedInput schema / properties / sort / enum
        Previous value: -[
        -  "disbursement_date",
        -  "disbursement_amount"
        -]New value: +[
        +  "disbursement_date",
        +  "-disbursement_date",
        +  "disbursement_amount",
        +  "-disbursement_amount"
        +]
    • Changedopenfec_search_expenditures3 fields changed
      • changedInput schema / properties / cursor / description
        Previous value: -"Opaque pagination cursor from a previous response. Itemized mode only (keyset pagination)."New value: +"Opaque pagination cursor from a previous response of this tool. Itemized mode only (keyset pagination). Valid only for an otherwise-identical call — changing any other argument, including sort, rejects the cursor; omit it to start over."
      • changedInput schema / properties / sort / description
        Previous value: -"Sort field. Itemized only."New value: +"Sort field. A \"-\" prefix sorts descending: use \"-expenditure_amount\" for the largest outside spending first, since the ascending form leads with the most negative rows (corrections and voided entries). Itemized only; OpenFEC sorts by \"-expenditure_date\" when omitted."
      • changedInput schema / properties / sort / enum
        Previous value: -[
        -  "expenditure_date",
        -  "expenditure_amount",
        -  "office_total_ytd"
        -]New value: +[
        +  "expenditure_date",
        +  "-expenditure_date",
        +  "expenditure_amount",
        +  "-expenditure_amount",
        +  "office_total_ytd",
        +  "-office_total_ytd"
        +]
  10. 6 tool updates
    • Changedopenfec_search_candidates1 field changed
      • removedInput schema / properties / candidate_id / pattern
        Removed value: -"^[HSP][0-9A-Z]+$"
    • Changedopenfec_search_committees2 fields changed
      • removedInput schema / properties / candidate_id / pattern
        Removed value: -"^[HSP][0-9A-Z]+$"
      • removedInput schema / properties / committee_id / pattern
        Removed value: -"^C\\d+$"
    • Changedopenfec_search_contributions2 fields changed
      • removedInput schema / properties / candidate_id / pattern
        Removed value: -"^[HSP][0-9A-Z]+$"
      • removedInput schema / properties / committee_id / pattern
        Removed value: -"^C\\d+$"
    • Changedopenfec_search_disbursements1 field changed
      • removedInput schema / properties / committee_id / pattern
        Removed value: -"^C\\d+$"
    • Changedopenfec_search_expenditures2 fields changed
      • removedInput schema / properties / candidate_id / pattern
        Removed value: -"^[HSP][0-9A-Z]+$"
      • removedInput schema / properties / committee_id / pattern
        Removed value: -"^C\\d+$"
    • Changedopenfec_search_filings2 fields changed
      • removedInput schema / properties / candidate_id / pattern
        Removed value: -"^[HSP][0-9A-Z]+$"
      • removedInput schema / properties / committee_id / pattern
        Removed value: -"^C\\d+$"
  11. 1 tool update
    • Changedopenfec_search_legal2 fields changed
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching legal documents across all types.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "total_count"
        -]New value: +[
        +  "results",
        +  "total_count",
        +  "totalCount"
        +]
  12. 9 tool updates
    • Changedopenfec_lookup_calendar3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no calendar entries matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching calendar entries before pagination.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "pagination"
        -]New value: +[
        +  "results",
        +  "pagination",
        +  "totalCount"
        +]
    • Changedopenfec_lookup_elections3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no election results matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching candidates or race summaries.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "pagination"
        -]New value: +[
        +  "results",
        +  "pagination",
        +  "totalCount"
        +]
    • Changedopenfec_search_candidates3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no candidates matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching candidates before pagination.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "candidates",
        -  "pagination"
        -]New value: +[
        +  "candidates",
        +  "pagination",
        +  "totalCount"
        +]
    • Changedopenfec_search_committees3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no committees matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching committees before pagination.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "committees",
        -  "pagination"
        -]New value: +[
        +  "committees",
        +  "pagination",
        +  "totalCount"
        +]
    • Changedopenfec_search_contributions3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no contributions matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching contributions or aggregate rows.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results"
        -]New value: +[
        +  "results",
        +  "totalCount"
        +]
    • Changedopenfec_search_disbursements3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no disbursements matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching disbursements or aggregate rows.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results"
        -]New value: +[
        +  "results",
        +  "totalCount"
        +]
    • Changedopenfec_search_expenditures3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no expenditures matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching expenditures or per-candidate aggregates.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results"
        -]New value: +[
        +  "results",
        +  "totalCount"
        +]
    • Changedopenfec_search_filings3 fields changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no filings matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / totalCount
        Added value: +{
        +  "description": "Total matching filings before pagination.",
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "results",
        -  "pagination"
        -]New value: +[
        +  "results",
        +  "pagination",
        +  "totalCount"
        +]
    • Changedopenfec_search_legal1 field changed
      • addedOutput schema / properties / notice
        Added value: +{
        +  "description": "Guidance when no legal documents matched — echoes filters and suggests how to broaden.",
        +  "type": "string"
        +}
  13. 6 tool updates
    • Changedopenfec_search_candidates2 fields changed
      • changedInput schema / properties / candidate_id / description
        Previous value: -"FEC candidate ID (e.g., P00003392, H2CO07170). When provided, returns a single candidate with full detail."New value: +"FEC candidate ID (e.g., P00003392, H2CO07170). Get IDs from openfec_search_candidates results. When provided, returns a single candidate with full detail."
      • addedInput schema / properties / candidate_id / pattern
        Added value: +"^[HSP][0-9A-Z]+$"
    • Changedopenfec_search_committees4 fields changed
      • changedInput schema / properties / candidate_id / description
        Previous value: -"Find committees linked to this candidate (authorized, leadership, joint fundraising)."New value: +"Find committees linked to this candidate (authorized, leadership, joint fundraising). Get IDs from openfec_search_candidates results."
      • addedInput schema / properties / candidate_id / pattern
        Added value: +"^[HSP][0-9A-Z]+$"
      • changedInput schema / properties / committee_id / description
        Previous value: -"FEC committee ID (e.g., C00358796). Starts with 'C' followed by digits. Returns a single committee with full detail."New value: +"FEC committee ID (e.g., C00358796). Get IDs from openfec_search_committees results. Starts with 'C' followed by digits. Returns a single committee with full detail."
      • addedInput schema / properties / committee_id / pattern
        Added value: +"^C\\d+$"
    • Changedopenfec_search_contributions4 fields changed
      • changedInput schema / properties / candidate_id / description
        Previous value: -"Candidate ID. Enables by_size and by_state aggregates without a committee_id."New value: +"Candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results. Enables by_size and by_state aggregates without a committee_id."
      • addedInput schema / properties / candidate_id / pattern
        Added value: +"^[HSP][0-9A-Z]+$"
      • changedInput schema / properties / committee_id / description
        Previous value: -"Receiving committee ID (e.g., C00703975)."New value: +"Receiving committee ID (e.g., C00703975). Get IDs from openfec_search_committees results."
      • addedInput schema / properties / committee_id / pattern
        Added value: +"^C\\d+$"
    • Changedopenfec_search_disbursements2 fields changed
      • changedInput schema / properties / committee_id / description
        Previous value: -"Spending committee ID (e.g., C00703975). Required for all modes."New value: +"Spending committee ID (e.g., C00703975). Get IDs from openfec_search_committees results. Required for all modes."
      • addedInput schema / properties / committee_id / pattern
        Added value: +"^C\\d+$"
    • Changedopenfec_search_expenditures4 fields changed
      • changedInput schema / properties / candidate_id / description
        Previous value: -"Targeted candidate ID (e.g., P00003392)."New value: +"Targeted candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results."
      • addedInput schema / properties / candidate_id / pattern
        Added value: +"^[HSP][0-9A-Z]+$"
      • changedInput schema / properties / committee_id / description
        Previous value: -"Spending committee ID (e.g., C00703975)."New value: +"Spending committee ID (e.g., C00703975). Get IDs from openfec_search_committees results."
      • addedInput schema / properties / committee_id / pattern
        Added value: +"^C\\d+$"
    • Changedopenfec_search_filings4 fields changed
      • changedInput schema / properties / candidate_id / description
        Previous value: -"Associated candidate ID."New value: +"Associated candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results."
      • addedInput schema / properties / candidate_id / pattern
        Added value: +"^[HSP][0-9A-Z]+$"
      • changedInput schema / properties / committee_id / description
        Previous value: -"Filing committee ID."New value: +"Filing committee ID (e.g., C00358796). Get IDs from openfec_search_committees results."
      • addedInput schema / properties / committee_id / pattern
        Added value: +"^C\\d+$"

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Query FEC campaign finance data — search candidates, track donations, analyze spending, and monitor Super PAC activity via the OpenFEC API.
    8
    2 npm
    4
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Access Federal Election Commission campaign finance data through MCP tools. Enables querying OpenFEC data using natural language via ask_pipeworx or direct tool calls.
    2 npm
    MIT
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.