openfec-mcp-server
Server Details
Access FEC campaign finance data. Query data about candidates, money trails, and election filings.
- Status
- Healthy
- Uptime
- 100.0% over 56 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
Scored across 12 tools
Each tool targets a distinct FEC dataset or action: search tools cover candidates, committees, contributions, disbursements, independent expenditures, coordinated expenditures, filings, and legal documents, while get tools retrieve specific records or totals and lookup tools handle calendar and elections. Overlapping areas like expenditures vs. coordinated expenditures are clearly differentiated in the descriptions.
All tools follow a consistent openfec_<verb>_<noun> snake_case pattern, using get, lookup, or search as the verb. The naming is predictable and makes the resource being accessed immediately identifiable.
Twelve tools is well within the ideal range and appropriately scoped for the FEC campaign finance domain. Each tool covers a meaningful slice of the data without unnecessary fragmentation or bloated surface area.
The toolset covers the major FEC data surfaces: candidates, committees, contributions, disbursements, independent and coordinated expenditures, filings, legal documents, calendar events, elections, and committee totals. As a read-only public data API, this is a comprehensive and practical set with no obvious dead ends for common campaign finance queries.
Available Tools
12 toolsopenfec_get_committee_totalsOpenfec Get Committee TotalsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Query 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 |
| page | No | Page 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. | |
| sort | No | Sort 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. | |
| cycle | No | Two-year election cycle (e.g., 2024). Even years only. Omit in single mode to get every cycle the committee has filed. | |
| per_page | No | Results per page. | |
| entity_type | No | Committee 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_id | No | Committee 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_receipts | No | Maximum total receipts in dollars. by_entity_type mode only. | |
| min_receipts | No | Minimum total receipts in dollars. by_entity_type mode only. | |
| committee_type | No | Committee type code — H (House), S (Senate), P (Presidential), O (Super PAC), N/Q (PAC), X/Y (party). by_entity_type mode only. | |
| committee_state | No | Two-letter state code of the committee. by_entity_type mode only. | |
| max_disbursements | No | Maximum total disbursements in dollars. by_entity_type mode only. | |
| min_disbursements | No | Minimum total disbursements in dollars. by_entity_type mode only. | |
| organization_type | No | Sponsoring organization type — C (corporation), L (labor), M (membership), T (trade), V (cooperative), W (corporation without capital stock). by_entity_type mode only. | |
| committee_designation | No | Committee designation — A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized). by_entity_type mode only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | No | Query 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. |
| error | No | Present when the call failed. Absent on success. |
| notice | No | 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. |
| results | No | Committee totals result set; one row per cycle in single mode, one row per committee in by_entity_type mode. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching totals rows before pagination. |
| search_criteria | No | 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. |
TDQS
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.
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.
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.
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.
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.
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_get_legal_documentOpenfec Get Legal DocumentARead-onlyIdempotentInspect
Fetch one FEC legal document — advisory opinion, MUR, ADR, administrative fine, or statute — by its type and number. openfec_search_legal replaces each result's documents and dispositions arrays with a count and category summary and cuts every commission vote down to a date and a 200-character action; this returns the record as upstream sends it, whole when it fits the 100,000-byte response budget. A larger record returns its scalar fields and the arrays that fit, with the rest listed in withheld; page through one by re-calling with array and offset. doc_type is the plural form of the document_type discriminator on a search result (advisory_opinion becomes advisory_opinions, mur becomes murs, adr becomes adrs, admin_fine becomes admin_fines, statute becomes statutes), and no is that result's no field — every document type carries it, and advisory opinions repeat it as ao_no.
| Name | Required | Description | Default |
|---|---|---|---|
| no | Yes | Document number, copied from the no field of the matching openfec_search_legal result. Advisory opinions are year-serial (e.g. "2024-01", also repeated as ao_no); murs, adrs, and admin_fines are digit strings (e.g. "8363"); statutes are U.S. Code section numbers (e.g. "30123"). | |
| array | No | Name of one top-level array field of the record to page through by entry — usually one listed in withheld when the record was too large to return whole (e.g. "dispositions", "documents"). Returns that array's entries from offset while they fit the response budget, in slice, with the record's scalar fields. Omit to fetch the record itself. | |
| offset | No | Entry offset (0-indexed) into array. Requires array; defaults to 0 when array is given. Pass the next_offset a previous slice returned to continue. | |
| doc_type | Yes | Legal document type, always plural. openfec_search_legal reports the singular form in each result document_type — advisory_opinion, mur, adr, admin_fine, statute — so add an "s" to get the value this field wants. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| slice | No | A run of the requested array. Present only when array was given. |
| notice | No | How to continue: which arrays were held back and how to page them, where a slice continues, or that an offset ran past the end of its array. |
| document | No | The legal document record, fields as upstream sends them — the full documents array openfec_search_legal summarizes, the complete dispositions and commission_votes entries, and the scalar and date fields (name, type, url, penalty and determination amounts, case dates). Whole when it fits the 100,000-byte response budget; otherwise the scalar fields and the arrays that fit, with the rest in withheld. With array set, the record's non-array fields only — the entries are in slice. Fields present vary by document type. |
| withheld | No | Arrays held back from document because the whole record exceeds the 100,000-byte response budget, smallest first. Page through one by re-calling with array set to its name. Absent when document is the whole record. |
| search_criteria | No | 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. |
| attachedDocumentCount | No | Number of related filings in the record documents array — the full count, whether this response carries them in document, in a slice, or holds them back. Compare against the document_count openfec_search_legal reported for the same record. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses substantial behavioral detail: a 100,000-byte response budget, partial return of scalar fields and arrays, a withheld list for omitted data, and offset-based paging. This lets an agent anticipate truncated responses and plan follow-up calls without experimental discovery.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: the first states purpose, the second explains the relationship to the sibling tool, and the third covers parameter conventions. It is front-loaded with the core action and keeps related details grouped coherently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers the key behaviors an agent needs: full versus truncated records, the withheld field, paging via array and offset, and how to derive parameters from a sibling tool's result. An output schema exists, so the lack of a canned return-value description is acceptable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already covers all parameters at 100%, the description adds essential cross-tool semantics: doc_type is the plural form of the search result's document_type discriminator, and no mirrors the result's no field (with advisory opinions repeating it as ao_no). It also clarifies that every document type carries no, reducing ambiguity that raw schema descriptions leave open.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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: 'Fetch one FEC legal document — advisory opinion, MUR, ADR, administrative fine, or statute — by its type and number.' It clearly differentiates itself from the sibling openfec_search_legal by explaining that this tool returns the raw, upstream record rather than the search result's summarized form.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly contrasts this tool with openfec_search_legal: the search tool aggregates and truncates fields, while this tool returns the full record as upstream sends it. It also gives concrete guidance for handling oversized records by re-calling with array and offset, so an agent knows exactly when and how to page.
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 CalendarARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | events = FEC calendar events. filing_deadlines = report due dates. election_dates = upcoming/past elections. | events |
| page | No | Page number (1-indexed). Default 1. | |
| state | No | Two-letter state code (e.g., AZ, CA). Primarily for election_dates mode. | |
| office | No | Office sought (H=House, S=Senate, P=President). Election dates mode. | |
| category | No | Calendar 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. | |
| district | No | Two-digit House district (e.g., "14", "07"); a single digit is zero-padded. Pair it with state — alone it matches that district number in every state. At-large races carry no district upstream, so a district filter never matches them. Election dates mode. | |
| max_date | No | Latest date (YYYY-MM-DD). | |
| min_date | No | Earliest date (YYYY-MM-DD). | |
| per_page | No | Results per page. Default 20, max 100. | |
| description | No | Full-text event description search. Events mode. | |
| report_type | No | Report type code (e.g. "Q1", "Q2"). Filing deadlines mode only. | |
| report_year | No | Report year. Filing deadlines mode. | |
| election_year | No | Election year. Election dates mode. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | No | 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. |
| error | No | Present when the call failed. Absent on success. |
| notice | No | 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. |
| results | No | Calendar result set; events, filing deadlines, or election dates depending on mode. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching calendar entries before pagination. |
| search_criteria | No | 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. |
TDQS
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's 'Look up' wording is consistent with these annotations and adds modest context about what can be scoped, but it does not disclose additional behavioral details such as pagination limits or mode-dependent response behavior beyond what annotations already provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The primary action is front-loaded, and the second sentence provides useful use cases that help an agent decide when to invoke the tool. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 13 parameters and mode-dependent behavior, but the schema descriptions are unusually thorough and an output schema exists, reducing the burden on the description. The description gives enough orientation for an agent to select the tool and start using it, though it does not surface every cross-parameter rule.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 13 parameters, including mode-specific constraints like 'Events mode only' and 'Filing deadlines mode only.' The description mentions categories and date ranges but does not add parameter-level meaning beyond what the schema provides, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Look up FEC calendar events, filing deadlines, and election dates.' It clearly states what the tool does and gives example use cases. However, it does not explicitly differentiate this from the sibling openfec_lookup_elections, which may cover 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: finding upcoming filing windows, locating past election dates, and scoping FEC events by date range/category. It does not mention alternatives or exclusions, such as 'for candidate-specific election lookups, use openfec_lookup_elections instead,' so it misses the top tier of explicit routing guidance.
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 ElectionsBRead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| zip | No | ZIP code — finds races covering this ZIP. Search mode only. | |
| mode | No | search = candidates in a race with financial totals. summary = aggregate race financial summary. | search |
| page | No | Page number (1-indexed). Search mode only; explicit page is rejected in summary mode. Defaults to 1 for search. | |
| cycle | Yes | Election cycle year (even years only, e.g. 2024). | |
| state | No | Two-letter US state code (e.g., AZ, CA). Required for senate/house unless zip is provided. | |
| office | Yes | Office sought: H=House, S=Senate, P=President. | |
| district | No | Two-digit district number (e.g. "07"). Required for house unless zip is provided. | |
| per_page | No | Results per page. Search mode only; defaults to 20. | |
| election_full | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| mode | No | 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. |
| error | No | Present when the call failed. Absent on success. |
| notice | No | 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. |
| results | No | Election race result set; candidate financial rows in search mode, a single aggregate summary row in summary mode. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching candidates or race summaries. |
| search_criteria | No | 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. |
TDQS
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.
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.
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.
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.
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.
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 CandidatesARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Search-results page number (1-indexed). Defaults to 1 on the search path. | |
| cycle | No | Two-year election cycle (even year, e.g., 2024). | |
| party | No | Three-letter party code (e.g., DEM, REP, LIB). | |
| query | No | Full-text candidate name search. | |
| state | No | Two-letter US state code (e.g., AZ, CA). | |
| office | No | Filter by office: H=House, S=Senate, P=President. | |
| district | No | Two-digit district number for House candidates. | |
| per_page | No | Search results per page. Defaults to 20 on the search path. With include_totals, at most 35 candidates are requested when cycle or election_year scopes the totals and 5 when the totals span every cycle, keeping the response under a 100,000-byte budget. A page bounded below your request reports truncated and cap, and pagination.per_page echoes the size applied — page numbers count at that size, so continue with the next page number. | |
| candidate_id | No | 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. | |
| election_year | No | Specific election year the candidate ran in. | |
| include_totals | No | Include financial totals (receipts, disbursements, cash on hand). Defaults to true when fetching by candidate_id. | |
| candidate_status | No | Candidate status: C=present, F=future, N=not yet, P=prior. | |
| has_raised_funds | No | Only candidates whose committee has received receipts. | |
| incumbent_challenge | No | Incumbent status: I=incumbent, C=challenger, O=open seat. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows in this page. Present only when truncated is true. |
| notice | No | Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when candidates did match, or that the page was bounded below the per_page requested and how to continue. |
| totals | No | Financial totals (receipts, disbursements, cash_on_hand) when include_totals is true. One row per candidate per cycle. |
| truncated | No | True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page. |
| candidates | No | Candidate result set; one record per match. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching candidates before pagination. |
| missing_totals | No | 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. |
| search_criteria | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, covering the safety profile. The description adds the useful behavioral note that fetching by candidate_id returns financial totals, but it does not go further into pagination, response truncation, or other runtime behavior; with annotations present, this level of added context is acceptable 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler: purpose, special lookup mode, and ID format each earn their place. It is front-loaded with the most important action ('Find federal candidates') and remains compact despite a 14-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema (100% coverage) and output schema, the description does not need to document every parameter. It covers the core selection context, the two usage modes, and the non-obvious ID format. It could mention pagination behavior or the distinction between search results and full detail, but the schema already handles those, so the description is sufficiently complete for tool selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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. The description's mention of filters and the FEC ID pattern largely repeats what the schema already documents (e.g., candidate_id format, office codes). It does not introduce meaningful new parameter semantics beyond reinforcing the ID format and the 'financial totals' behavior tied to include_totals.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description specifies a concrete verb-resource pair ('Find federal candidates' and 'Retrieve a specific candidate by FEC ID') and enumerates the key search dimensions (name, state, office, party, cycle). This clearly distinguishes it from sibling search tools like openfec_search_committees and openfec_search_contributions, while also signaling a distinct by-ID lookup mode with financial totals.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: use it to search candidates across several filters or to fetch one candidate by ID with totals. It does not explicitly name alternative tools or state when not to use it, but the purpose statement and ID-format guidance are enough for an agent to select it appropriately among the candidate-related siblings.
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 CommitteesARead-onlyIdempotentInspect
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).
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Search-results page number (1-indexed). Defaults to 1 on the search path. | |
| cycle | No | Two-year election cycle (even year). | |
| party | No | Three-letter party code (e.g., DEM, REP). | |
| query | No | Full-text committee name search. | |
| state | No | Two-letter state code. | |
| per_page | No | Search results per page. Defaults to 20 on the search path. | |
| designation | No | Committee designation. A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized). Matches each committee's current designation only, even with cycle set — a past principal committee since redesignated drops out of P. For a candidate's principal committee in a given cycle, use openfec_lookup_elections (mode: search) and read candidate_pcc_id. | |
| candidate_id | No | Find committees linked to this candidate (authorized, leadership, joint fundraising). Get IDs from openfec_search_candidates results. | |
| committee_id | No | 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. | |
| committee_type | No | Committee 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_name | No | Full-text treasurer name search. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| notice | No | 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. |
| committees | No | Committee result set; one record per match. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching committees before pagination. |
| search_criteria | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations include readOnlyHint and idempotentHint, which already signal safe, repeatable behavior. The description adds domain context (committee ID format) and confirms read-style actions ('Find', 'Retrieve') without contradicting annotations. No additional behavioral details like pagination or rate limits are given, but the output schema covers return structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded: it leads with the primary action and resource, then adds the retrieval mode and ID format. No filler or repetition. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (11 optional parameters) and the presence of a detailed schema and output schema, the description is adequate. It covers the core functionality and ID format, while pagination and parameter nuances are handled in the schema. The only minor gap is lack of explicit guidance on when to use this vs. other search tools, but the schema partially compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 11 parameters have detailed descriptions in the schema. The tool description adds no parameter-specific information beyond what the schema provides, so the baseline of 3 applies. The schema's rich descriptions (e.g., designation nuance, cross-references to other tools) already carry the semantic load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: finding political committees by various criteria (name, type, candidate affiliation, state) and retrieving a specific committee by FEC ID. It names the resource type (committees) and distinguishes from sibling tools like openfec_search_candidates. The ID format detail adds specificity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on what the tool does but does not explicitly mention alternatives or when not to use it. However, the schema's designation parameter description directs users to openfec_lookup_elections for a specific use case, and candidate_id references openfec_search_candidates. Since the description itself lacks exclusions, it earns a 4 rather than 5.
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 ContributionsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Query 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 |
| page | No | Page number (1-indexed) for aggregate modes. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for aggregates. | |
| sort | No | 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. | |
| cycle | No | Two-year election cycle (e.g., 2024). Even years only. Defaults to current cycle for itemized mode. | |
| cursor | No | 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. | |
| max_date | No | Latest contribution date (YYYY-MM-DD). Itemized only. | |
| min_date | No | Earliest contribution date (YYYY-MM-DD). Itemized only. | |
| per_page | No | Results per page. Itemized mode sends at most 30 upstream, keeping the response under a 100,000-byte budget; a page bounded below your request reports truncated and cap, and next_cursor continues it. | |
| max_amount | No | Maximum contribution amount in dollars. Itemized only. | |
| min_amount | No | Minimum contribution amount in dollars. Itemized only. | |
| candidate_id | No | Candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results. Enables by_size and by_state aggregates without a committee_id. | |
| committee_id | No | Receiving committee ID (e.g., C00703975). Get IDs from openfec_search_committees results. | |
| is_individual | No | Only individual contributions (excludes committee-to-committee transfers). Itemized only. | |
| contributor_zip | No | ZIP code prefix (starts-with match). Itemized only. | |
| contributor_city | No | Contributor city. Itemized only. | |
| contributor_name | No | Full-text donor name search. Itemized only. | |
| contributor_state | No | Two-letter state code (e.g., CA). Itemized only. | |
| contributor_employer | No | Full-text employer search. Itemized only. | |
| contributor_occupation | No | Full-text occupation search. Itemized only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true. |
| mode | No | 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. |
| count | No | Total matching contributions (itemized mode). Check count_is_approximate before quoting it as a figure. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows in this page. Present only when truncated is true. |
| notice | No | Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when contributions did match, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue. |
| results | No | Contribution result set; itemized records or aggregate buckets depending on mode. |
| committee | No | 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. |
| truncated | No | True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page. |
| pagination | No | Page-based pagination info (aggregate modes only). |
| totalCount | No | Total matching contributions or aggregate rows. |
| next_cursor | No | Pagination cursor for the next page of itemized results. Null when no more pages. |
| search_criteria | No | 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. |
| count_is_approximate | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the description need not restate that. It adds valuable behavioral context: mode-specific requirements (committee_id for itemized, candidate_id for certain aggregates), and the sort nuance that the ascending form leads with negative rows (refunds, reattributions). This goes beyond what annotations provide and helps the agent avoid common pitfalls.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences: the first states the purpose and modes, the second gives the use case, the third sets the key constraint. It's front-loaded with the primary action and resource. No filler, every clause earns its place. Excellent structure for an agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (19 parameters, 5 modes, pagination, constraints), the description provides the essential guidance: purpose, use case, and mode-dependent requirements. The output schema exists, so return values need not be explained. The description, along with a rich schema, gives an agent everything needed to invoke the tool correctly without missing critical constraints.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description compensates by clarifying which parameters apply to which modes ('Itemized only', 'Aggregate modes'), and it explains the sort behavior with the negative-row caveat. It also notes pagination semantics (keyset vs page) implicitly through mode descriptions. This adds meaning beyond mere schema listings.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search'), a clear resource ('itemized individual contributions (Schedule A)'), and enumerates the aggregate breakdown modes (size, state, employer, occupation). The phrase 'Use to answer "who is funding this committee?"' anchors the tool's purpose distinctly. Among siblings focused on disbursements, expenditures, or filings, this description unambiguously identifies the contributions search tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear use case ('who is funding this committee?') and gives concrete constraints: 'Itemized mode requires a committee_id' and 'Aggregate by_size/by_state can use candidate_id instead.' While it doesn't explicitly name alternative tools or state when not to use this one, the constraints and use case give an agent enough context to decide when to invoke it. The lack of explicit 'when-not-to-use' guidance stops it from a 5.
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 ExpendituresARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (1-indexed). Read pagination.pages in the response to see how many pages exist. | |
| sort | No | Sort 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. | |
| cycle | No | Two-year election cycle (e.g., 2024). Even years only. Omitting it searches every cycle on record. | |
| max_date | No | Latest expenditure date (YYYY-MM-DD). | |
| min_date | No | Earliest expenditure date (YYYY-MM-DD). | |
| per_page | No | Results per page. At most 80 are requested upstream when scoped by committee_id and 25 otherwise, keeping the response under a 100,000-byte budget. A page bounded below your request reports truncated and cap, and pagination.per_page echoes the size applied — page numbers count at that size, so continue with the next page number. | |
| max_amount | No | Maximum expenditure amount in dollars. | |
| min_amount | No | Minimum expenditure amount in dollars. | |
| payee_name | No | Full-text payee name search (the vendor the party paid). | |
| candidate_id | No | Benefiting candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results. | |
| committee_id | No | Spending party committee ID (e.g., C00003418). Get IDs from openfec_search_committees results — party committees carry committee_type X or Y. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows in this page. Present only when truncated is true. |
| notice | No | 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 page was bounded below the per_page requested and how to continue. |
| results | No | Coordinated expenditure result set; one record per itemized transaction. |
| committee | No | 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. |
| truncated | No | True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching coordinated expenditures before pagination. |
| search_criteria | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly and idempotent, so the safety profile is covered. The description adds meaningful behavioral context beyond annotations: statutory limits, scale of spending, Schedule F classification, and the distinction from independent expenditures and contributions. This enriches the agent's understanding of what the results represent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized: definition first, differentiation second, scoping guidance last. Every sentence carries useful information, and no space is wasted repeating schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich input schema, output schema, and annotations, the description covers what this tool returns conceptually, how to scope it, how it differs from alternatives, and why the data matters. Nothing critical is missing for correct selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds extra meaning by labeling committee_id as the 'spending party committee' and candidate_id as the 'benefiting candidate,' and it points to sibling tools for obtaining valid IDs plus committee_type X/Y guidance. This goes beyond the schema's own field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb (Search) and resource (coordinated party expenditures, Schedule F) and defines what that means. It actively distinguishes itself from independent expenditures and direct contributions, making it clear what this tool is and is not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the sibling tool openfec_search_expenditures and explains the key distinction: coordinated vs. independent expenditures. It also gives concrete scoping strategies (committee_id, candidate_id, cycle) and notes the default unscoped behavior across 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 DisbursementsARead-onlyIdempotentInspect
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?"
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Query 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 |
| page | No | Page number (1-indexed) for aggregate modes. Explicit page is rejected in itemized mode, which paginates with cursor. Defaults to 1 for aggregates. | |
| sort | No | 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. | |
| cycle | No | 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. | |
| cursor | No | 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. | |
| max_date | No | Latest disbursement date (YYYY-MM-DD). Itemized only. | |
| min_date | No | Earliest disbursement date (YYYY-MM-DD). Itemized only. | |
| per_page | No | Results per page. Itemized mode sends at most 30 upstream, keeping the response under a 100,000-byte budget; a page bounded below your request reports truncated and cap, and next_cursor continues it. | |
| max_amount | No | Maximum amount in dollars. Itemized only. | |
| min_amount | No | Minimum amount in dollars. Itemized only. | |
| committee_id | Yes | Spending committee ID (e.g., C00703975). Get IDs from openfec_search_committees results. Required for all modes. | |
| recipient_city | No | Recipient city. Itemized only. | |
| recipient_name | No | Full-text payee name search. Itemized only. | |
| recipient_state | No | Recipient state. Itemized only. | |
| recipient_committee_id | No | Recipient committee ID (for committee-to-committee transfers). Itemized only. | |
| disbursement_description | No | Full-text description search (e.g., "media buy", "consulting"). Itemized only. | |
| disbursement_purpose_category | No | Purpose category code. Itemized only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true. |
| mode | No | 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. |
| count | No | Total matching disbursements (itemized mode). Check count_is_approximate before quoting it as a figure. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows in this page. Present only when truncated is true. |
| notice | No | Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when disbursements did match, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue. |
| results | No | Disbursement result set; itemized records or aggregate buckets depending on mode. |
| committee | No | 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. |
| truncated | No | True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page. |
| pagination | No | Page-based pagination info (aggregate modes only). |
| totalCount | No | Total matching disbursements or aggregate rows. |
| next_cursor | No | Pagination cursor for the next page of itemized results. Null when no more pages. |
| search_criteria | No | 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. |
| count_is_approximate | No | 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. |
TDQS
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 without description effort. The description adds only mode-level context and the committee_id requirement; it does not disclose response-shape differences, rate limits, or upstream timeouts, which are left to schema parameter notes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler: the first establishes the primary function and alternatives, the second gives the universal requirement, and the third provides user-oriented guidance. It is front-loaded and appropriately sized for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 17 parameters, a 100%-covered schema, read-only annotations, and an output schema, the description is nearly sufficient for tool selection and invocation. It lacks a brief mode-selection cue, such as 'start with itemized for detail, aggregate for summaries', and an explicit note that aggregate modes change the response shape, though those are recoverable from the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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; the tool description adds no parameter details beyond what the schema already states. Mentioning 'by purpose or recipient' maps to mode values, but that is not new semantic content.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Search itemized committee spending (Schedule B)' plus aggregate breakdowns by purpose or recipient. It is clearly about outgoing committee payments, but it never explicitly contrasts with sibling tools like openfec_search_expenditures, so the differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the required precondition ('All modes require a committee_id') and gives two concrete use cases ('what is this committee spending money on?' / 'who is receiving payments?'). It does not provide exclusions or point to alternatives such as openfec_get_committee_totals or search_expenditures, so it misses the top benchmark.
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 ExpendituresARead-onlyIdempotentInspect
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).
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Query mode. "itemized" returns individual expenditure records (keyset pagination). "by_candidate" returns aggregated totals per candidate by committee (page-based). | itemized |
| page | No | 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. | |
| sort | No | 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. | |
| cycle | No | 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. In by_candidate mode the cycle names the election, and election_full decides whether the totals cover the full election period ending in it (4yr president, 6yr senate, 2yr house) or only this two-year cycle. | |
| cursor | No | 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. | |
| max_date | No | Latest expenditure date (YYYY-MM-DD). Itemized only. | |
| min_date | No | Earliest expenditure date (YYYY-MM-DD). Itemized only. | |
| per_page | No | Results per page. Itemized mode sends at most 60 upstream when scoped by committee_id and 30 otherwise, keeping the response under a 100,000-byte budget; a page bounded below your request reports truncated and cap, and next_cursor continues it. | |
| is_notice | No | Only 24/48-hour notice filings (near-election spending). Itemized only. | |
| max_amount | No | Maximum expenditure amount in dollars. Itemized only. | |
| min_amount | No | Minimum expenditure amount in dollars. Itemized only. | |
| payee_name | No | Full-text payee name search. Itemized only. | |
| most_recent | No | 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. | |
| candidate_id | No | Targeted candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results. | |
| committee_id | No | Spending committee ID (e.g., C00703975). Get IDs from openfec_search_committees results. | |
| election_full | No | by_candidate only: expand cycle to the full election period (4yr president, 6yr senate, 2yr house) instead of the two-year cycle alone. Defaults to true when omitted; itemized mode rejects it, since that endpoint has no such parameter. Carries no schema default, so an explicit value is distinguishable from an omission. | |
| support_oppose | No | S = support, O = oppose. Filter by whether the expenditure supports or opposes the candidate. | |
| candidate_party | No | 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. | |
| candidate_office | No | 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. | |
| candidate_office_state | No | 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. | |
| candidate_office_district | No | 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. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true. |
| mode | No | 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. |
| count | No | Total matching independent expenditures (itemized mode). Check count_is_approximate before quoting it as a figure. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows in this page. Present only when truncated is true. |
| notice | No | Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when expenditures did match, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue. |
| results | No | Expenditure result set; itemized records or per-candidate aggregates depending on mode. |
| committee | No | 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. |
| truncated | No | True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page. |
| pagination | No | Page-based pagination info (by_candidate mode only). |
| totalCount | No | Total matching expenditures or per-candidate aggregates. |
| next_cursor | No | Pagination cursor for the next page of itemized results. Null when no more pages. |
| search_criteria | No | 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. |
| count_is_approximate | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the safety burden is covered and the bar is lower. The description adds meaningful mode behavior — itemized returns individual records, by_candidate aggregates per candidate — plus the precondition that by_candidate needs either a candidate_id or a full race scope. Finer behaviors like keyset vs page pagination, cursor invalidation, and sort quirks live in the schema property descriptions, which is acceptable given annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero filler: purpose first, coverage second, mode and scope guidance third. The most decision-relevant rule (itemized vs by_candidate and what by_candidate requires) is front-loaded immediately after the purpose statement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 21-parameter, two-mode tool with an output schema, the description supplies the up-front mental model an agent needs — what the tool searches, what it covers, and how to choose a mode — while the 100%-documented schema covers every parameter and the output schema documents return values. No critical decision is left undocumented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 and the schema correctly carries the heavy lifting for all 21 parameters. The description earns the bump by composing candidate_office, candidate_office_state, and candidate_office_district into coherent race-scope rules that no single property description conveys on its own.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 independent expenditures (Schedule E)'. The parenthetical 'Schedule E' plus the qualifier 'independent' cleanly separates it from the sibling openfec_search_coordinated_expenditures, and 'outside spending supporting or opposing federal candidates' fixes the domain precisely.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit internal mode guidance is present: 'Use itemized mode for individual expenditure records, or by_candidate for aggregated totals per candidate', and the by_candidate scope requirements are spelled out exactly (candidate_office alone for President, plus state for Senate, plus district for House). It never explicitly names a sibling alternative as a when-not-to-use, so it stops short of a 5, but the Schedule E designation makes the boundary clear.
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 FilingsARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number (1-indexed). | |
| cycle | No | Two-year election cycle (even year). | |
| per_page | No | Results per page. At most 65 are requested upstream, keeping the response under a 100,000-byte budget. A page bounded below your request reports truncated and cap, and pagination.per_page echoes the size applied — page numbers count at that size, so continue with the next page number. | |
| form_type | No | FEC 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_name | No | Full-text filer name search. | |
| is_amended | No | Filter to original or amended filings only. | |
| most_recent | No | Only the most recent version (filters out superseded amendments). | |
| report_type | No | Report type code. Common: Q1/Q2/Q3 (quarterly), YE (year-end), M3-M12 (monthly), 12G/12P/30G (pre/post election). | |
| report_year | No | Filing year. | |
| candidate_id | No | Associated candidate ID (e.g., P00003392). Get IDs from openfec_search_candidates results. | |
| committee_id | No | Filing committee ID (e.g., C00358796). Get IDs from openfec_search_committees results. | |
| max_receipt_date | No | Latest FEC receipt date (YYYY-MM-DD). | |
| min_receipt_date | No | Earliest date FEC received the filing (YYYY-MM-DD). |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Rows in this page. Present only when truncated is true. |
| notice | No | Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when filings did match, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue. |
| results | No | Filing result set; one record per match. |
| truncated | No | True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page. |
| pagination | No | Page-based pagination metadata. |
| totalCount | No | Total matching filings before pagination. |
| search_criteria | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the read-only safety profile is covered and the bar is lower. The description adds the scope of covered forms (financial reports, statements of candidacy, organizational filings, etc.) but discloses no behavioral traits such as result truncation, pagination semantics, or response structure — those live in the per_page parameter schema rather than the description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero filler: the verb-resource-scope is front-loaded, and the form-type list earns its place by mapping directly to the form_type parameter and bounding the tool's coverage. Nothing extraneous and no repetition of annotation or schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a fully described 13-parameter schema, an output schema, and read-only/idempotent annotations, the description is largely complete for a search tool. The only high-level behavior it omits (truncation and pagination semantics for large page sizes) is already well documented in the per_page parameter description, so an agent is not left without guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every one of the 13 parameters is already documented in the schema, including per_page's detailed truncation/budget explanation and form_type's common-code enumeration. The description's phrase 'by committee, candidate, form type, or date range' is a light echo of those param descriptions, adding little semantic value beyond the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource-scope statement: 'Search FEC filings and reports by committee, candidate, form type, or date range.' The enumerated form types (F3/F3P/F3X, F2, F1, F24) make the resource unambiguous and visibly distinguish it from siblings openfec_search_candidates, openfec_search_committees, openfec_search_contributions, and the expenditure/disbursement searches. An agent can tell this is the filings search without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the description makes clear this is the general filings search, and siblings are cleanly separated by the resource name. However, it never explicitly says when to use this tool versus alternatives, nor does it warn that candidate/committee searches have their own dedicated siblings — an agent might attempt to use this tool to find candidate or committee profiles, which are other tools' jobs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfec_search_legalOpenfec Search LegalARead-onlyIdempotentInspect
Search FEC legal documents: advisory opinions, enforcement cases (MURs), alternative dispute resolutions, administrative fines, and statutes. The citation, penalty, respondent, ao_number, and case_number filters each apply to only some document types; with type omitted, the search returns only the types every one of them applies to. Each response is held to 100,000 bytes: when a page would exceed it, whole results are held back and nextFromHit gives the from_hit that continues each document type.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Document type filter. Omit to search every type the other filters apply to — all five when only query is given. admin_fines can be slow without a query. | |
| query | No | Full-text search across legal documents. | |
| from_hit | No | Offset for pagination (0-indexed), counted within each document type rather than across them. Default 0. When a response is bounded, nextFromHit gives the value that continues each type. 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. | |
| max_date | No | Latest date (YYYY-MM-DD) for the date_kind selected. Requires type and date_kind. | |
| min_date | No | Earliest date (YYYY-MM-DD) for the date_kind selected. Requires type and date_kind. | |
| ao_number | No | Specific advisory opinion number (e.g. "2024-01"). Applies to advisory_opinions only: rejected with any other type, and with type omitted only advisory opinions are returned. | |
| date_kind | No | 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. | |
| respondent | No | Respondent name. Applies to enforcement cases (murs, adrs) only: rejected with any other type, and with type omitted only MURs and ADRs are returned. | |
| case_number | No | Specific MUR, ADR, or administrative fine case number (e.g. "8343"). Applies to murs, adrs, and admin_fines: rejected with advisory_opinions or statutes, and with type omitted only those three types are returned. | |
| hits_returned | No | Results per page, applied per document type. Default 20, max 200. A response is held to 100,000 bytes, so a page of large records can carry fewer, with nextFromHit naming where each type continues. Bounded together with from_hit by the 10,000-result window. | |
| max_penalty_amount | No | Maximum penalty amount in dollars. Applies to murs, adrs, and admin_fines (an administrative fine matches on its reason-to-believe or final-determination amount): rejected with advisory_opinions or statutes, and with type omitted only those three types are returned. | |
| min_penalty_amount | No | Minimum penalty amount in dollars. Applies to murs, adrs, and admin_fines (an administrative fine matches on its reason-to-believe or final-determination amount): rejected with advisory_opinions or statutes, and with type omitted only those three types are returned. | |
| statutory_citation | No | U.S.C. citation in the form "<title> U.S.C. <section>" (e.g. "52 U.S.C. 30104"; "USC", "§", and a suffix such as "30104(g)" are accepted — a bare "30104" is rejected as invalid_citation). One citation per value: "52 U.S.C. 30104, 52 U.S.C. 30118" is rejected, since only the first would be applied. Given with regulatory_citation, matches a document that cites either one. On murs and adrs it cannot be combined with case_number, respondent, a penalty bound, or an open_date or close_date bound, which the search index would ignore. Applies to advisory_opinions, murs, and adrs: rejected with admin_fines or statutes, and with type omitted only those three types are returned. | |
| regulatory_citation | No | CFR citation in the form "<title> CFR <part>.<section>" (e.g. "11 CFR 110.1"; "C.F.R.", "§", and a suffix such as "110.1(b)" are accepted — a bare "110.1" is rejected as invalid_citation). One citation per value: "11 CFR 110.1; 11 CFR 110.2" is rejected, since only the first would be applied. Given with statutory_citation, matches a document that cites either one. On murs and adrs it cannot be combined with case_number, respondent, a penalty bound, or an open_date or close_date bound, which the search index would ignore. Applies to advisory_opinions, murs, and adrs: rejected with admin_fines or statutes, and with type omitted only those three types are returned. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| shown | No | Results in this response. Present only when truncated is true. |
| notice | No | Guidance on the page returned: how to broaden a search that matched nothing, that from_hit ran past the end when documents did match, or — when truncated is set — how each document type continues. |
| results | No | Legal document result set spanning advisory opinions, MURs, ADRs, admin fines, and statutes — only the types searched. Grouped by type in upstream order; when truncated is set, each type holds its first results up to the response budget. |
| truncated | No | True when results upstream returned for this page were held back because the next one would take the response past its 100,000-byte budget. Absent when the page is complete, including a naturally short page and an offset past the end. |
| totalCount | No | Total matching legal documents across the document types searched. |
| nextFromHit | No | The from_hit that continues each document type with results held back, keyed by the value to pass as type (advisory_opinions, murs, adrs, admin_fines, statutes). Re-call with the same filters, that type, and this from_hit. Present only when truncated is true. |
| total_count | No | Total matching documents across the types searched: the requested type, or with type omitted, every type the supplied filters apply to. |
| retrievalHint | No | How to recover the material trimmed out of these results. Present whenever any result was returned, because every result is trimmed. |
| search_criteria | No | 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. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the description does not need to restate safety. It adds valuable behavioral context: the 100,000-byte response limit, how whole results are held back, and that nextFromHit continues each document type. It also notes that admin_fines can be slow without a query (in the type parameter). This goes beyond the annotations and enriches the agent's understanding of the tool's runtime behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exactly two sentences, front-loaded with the primary purpose and then the key behavioral constraints. Every clause earns its place: the document types, the filter-scoping rule, and the pagination/byte-limit behavior. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (14 parameters, no required, output schema present), the description covers the essential high-level behaviors: what the tool searches, how type-scoped filters work, and the response size/pagination mechanism. The output schema exists, so the description need not explain return values. It does not mention error cases or rate limits, but those are not critical for correct invocation. Slight gap: it doesn't explicitly state that the tool is read-only (though annotations cover that), and it doesn't summarize the output structure beyond nextFromHit. Still, it is adequate for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter already has a thorough description in the schema (e.g., type, from_hit, date_kind, citations). The main description adds some high-level context about filter interactions (e.g., 'with type omitted, the search returns only the types every one of them applies to') and the byte limit, but it does not clarify individual parameter syntax beyond what the schema already provides. Baseline of 3 is appropriate since the schema carries the burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search FEC legal documents' and enumerates the exact document types (advisory opinions, MURs, ADRs, admin fines, statutes). It is specific and distinct from sibling tools like openfec_get_legal_document, which retrieves a specific document, and other search tools for candidates/committees. No ambiguity or tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use the tool (searching legal documents) and explains critical behavior like the filter applicability (only some document types) and the byte-limit pagination. However, it does not explicitly state when NOT to use it (e.g., when a specific document is needed, use openfec_get_legal_document). The guidance is strong but lacks an explicit exclusion.
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.
2 tool updates
- Changed
openfec_get_legal_document9 fields changed- added
Input schema / properties / arrayAdded value: +{ + "description": "Name of one top-level array field of the record to page through by entry — usually one listed in withheld when the record was too large to return whole (e.g. \"dispositions\", \"documents\"). Returns that array's entries from offset while they fit the response budget, in slice, with the record's scalar fields. Omit to fetch the record itself.", + "minLength": 1, + "type": "string" +} - added
Input schema / properties / offsetAdded value: +{ + "description": "Entry offset (0-indexed) into array. Requires array; defaults to 0 when array is given. Pass the next_offset a previous slice returned to continue.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / attachedDocumentCount / descriptionPrevious value: -"Number of related filings in the record documents array. Compare against the document_count openfec_search_legal reported for the same record."New value: +"Number of related filings in the record documents array — the full count, whether this response carries them in document, in a slice, or holds them back. Compare against the document_count openfec_search_legal reported for the same record." - changed
Output schema / properties / document / descriptionPrevious value: -"The complete legal document record. Carries the full documents array that openfec_search_legal replaces with a count and category summary, and the complete commission_votes entries it reduces to a vote date and a truncated action, alongside the dispositions and the scalar and date fields (name, type, url, penalty and determination amounts, case dates). Fields present vary by document type."New value: +"The legal document record, fields as upstream sends them — the full documents array openfec_search_legal summarizes, the complete dispositions and commission_votes entries, and the scalar and date fields (name, type, url, penalty and determination amounts, case dates). Whole when it fits the 100,000-byte response budget; otherwise the scalar fields and the arrays that fit, with the rest in withheld. With array set, the record's non-array fields only — the entries are in slice. Fields present vary by document type." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."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. `array_not_in_record`: The array input names a field this record does not carry as an array. `offset_without_array`: offset was given without array, so there is no array for it to index. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "legal_document_not_found" -]New value: +[ + "legal_document_not_found", + "array_not_in_record", + "offset_without_array" +] - added
Output schema / properties / noticeAdded value: +{ + "description": "How to continue: which arrays were held back and how to page them, where a slice continues, or that an offset ran past the end of its array.", + "type": "string" +} - added
Output schema / properties / sliceAdded value: +{ + "additionalProperties": false, + "description": "A run of the requested array. Present only when array was given.", + "properties": { + "array": { + "description": "The array these entries come from.", + "type": "string" + }, + "entries": { + "description": "Entries from offset, as many as fit the response budget — at least one while offset is inside the array.", + "items": { + "description": "One entry, exactly as the record carries it." + }, + "type": "array" + }, + "next_offset": { + "description": "Offset that continues the array. Absent once the last entry is here.", + "type": "number" + }, + "offset": { + "description": "Offset (0-indexed) of the first entry here.", + "type": "number" + }, + "total": { + "description": "Entries in the whole array.", + "type": "number" + } + }, + "required": [ + "array", + "offset", + "total", + "entries" + ], + "type": "object" +} - added
Output schema / properties / withheldAdded value: +{ + "description": "Arrays held back from document because the whole record exceeds the 100,000-byte response budget, smallest first. Page through one by re-calling with array set to its name. Absent when document is the whole record.", + "items": { + "additionalProperties": false, + "description": "One array held back from document.", + "properties": { + "array": { + "description": "Name of the array field held back — pass it as array.", + "type": "string" + }, + "bytes": { + "description": "Size of the whole array as JSON, in UTF-8 bytes.", + "type": "number" + }, + "count": { + "description": "Entries in the array.", + "type": "number" + } + }, + "required": [ + "array", + "count", + "bytes" + ], + "type": "object" + }, + "type": "array" +}
- Changed
openfec_search_legal20 fields changed- changed
Input schema / properties / ao_number / descriptionPrevious value: -"Specific advisory opinion number (e.g. \"2024-01\")."New value: +"Specific advisory opinion number (e.g. \"2024-01\"). Applies to advisory_opinions only: rejected with any other type, and with type omitted only advisory opinions are returned." - changed
Input schema / properties / case_number / descriptionPrevious value: -"Specific MUR or ADR case number."New value: +"Specific MUR, ADR, or administrative fine case number (e.g. \"8343\"). Applies to murs, adrs, and admin_fines: rejected with advisory_opinions or statutes, and with type omitted only those three types are returned." - changed
Input schema / properties / from_hit / descriptionPrevious 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."New value: +"Offset for pagination (0-indexed), counted within each document type rather than across them. Default 0. When a response is bounded, nextFromHit gives the value that continues each type. 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." - changed
Input schema / properties / hits_returned / descriptionPrevious value: -"Results per page, applied per document type. Default 20, max 200. Bounded together with from_hit by the 10,000-result window."New value: +"Results per page, applied per document type. Default 20, max 200. A response is held to 100,000 bytes, so a page of large records can carry fewer, with nextFromHit naming where each type continues. Bounded together with from_hit by the 10,000-result window." - changed
Input schema / properties / max_penalty_amount / descriptionPrevious value: -"Maximum penalty amount in dollars. Filters enforcement cases (murs, adrs) only — other document types are returned unfiltered by it."New value: +"Maximum penalty amount in dollars. Applies to murs, adrs, and admin_fines (an administrative fine matches on its reason-to-believe or final-determination amount): rejected with advisory_opinions or statutes, and with type omitted only those three types are returned." - changed
Input schema / properties / min_penalty_amount / descriptionPrevious value: -"Minimum penalty amount in dollars. Filters enforcement cases (murs, adrs) only — other document types are returned unfiltered by it."New value: +"Minimum penalty amount in dollars. Applies to murs, adrs, and admin_fines (an administrative fine matches on its reason-to-believe or final-determination amount): rejected with advisory_opinions or statutes, and with type omitted only those three types are returned." - changed
Input schema / properties / regulatory_citation / descriptionPrevious value: -"CFR citation (e.g. \"11 CFR 112.4\")."New value: +"CFR citation in the form \"<title> CFR <part>.<section>\" (e.g. \"11 CFR 110.1\"; \"C.F.R.\", \"§\", and a suffix such as \"110.1(b)\" are accepted — a bare \"110.1\" is rejected as invalid_citation). One citation per value: \"11 CFR 110.1; 11 CFR 110.2\" is rejected, since only the first would be applied. Given with statutory_citation, matches a document that cites either one. On murs and adrs it cannot be combined with case_number, respondent, a penalty bound, or an open_date or close_date bound, which the search index would ignore. Applies to advisory_opinions, murs, and adrs: rejected with admin_fines or statutes, and with type omitted only those three types are returned." - changed
Input schema / properties / respondent / descriptionPrevious value: -"Respondent name (enforcement cases)."New value: +"Respondent name. Applies to enforcement cases (murs, adrs) only: rejected with any other type, and with type omitted only MURs and ADRs are returned." - changed
Input schema / properties / statutory_citation / descriptionPrevious value: -"U.S.C. citation (e.g. \"52 U.S.C. 30106\")."New value: +"U.S.C. citation in the form \"<title> U.S.C. <section>\" (e.g. \"52 U.S.C. 30104\"; \"USC\", \"§\", and a suffix such as \"30104(g)\" are accepted — a bare \"30104\" is rejected as invalid_citation). One citation per value: \"52 U.S.C. 30104, 52 U.S.C. 30118\" is rejected, since only the first would be applied. Given with regulatory_citation, matches a document that cites either one. On murs and adrs it cannot be combined with case_number, respondent, a penalty bound, or an open_date or close_date bound, which the search index would ignore. Applies to advisory_opinions, murs, and adrs: rejected with admin_fines or statutes, and with type omitted only those three types are returned." - changed
Input schema / properties / type / descriptionPrevious value: -"Document type filter. Omit to search all types. admin_fines is slow without a query or respondent filter."New value: +"Document type filter. Omit to search every type the other filters apply to — all five when only query is given. admin_fines can be slow without a query." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."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. `filter_not_valid_for_type`: A type-specific filter was sent with a type it does not filter, or type-specific filters that no single document type accepts together — including a citation with case_number, respondent, a penalty bound, or an open_date or close_date bound on murs or adrs. `invalid_citation`: A citation is not in a form the search index parses, so upstream would ignore it and return the type unfiltered, or a value holds a second citation upstream would ignore. `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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "missing_filter", - "date_filter_incomplete", - "date_kind_not_valid_for_type", - "legal_window_exceeded" -]New value: +[ + "missing_filter", + "date_filter_incomplete", + "date_kind_not_valid_for_type", + "filter_not_valid_for_type", + "invalid_citation", + "legal_window_exceeded" +] - added
Output schema / properties / nextFromHitAdded value: +{ + "additionalProperties": { + "type": "number" + }, + "description": "The from_hit that continues each document type with results held back, keyed by the value to pass as type (advisory_opinions, murs, adrs, admin_fines, statutes). Re-call with the same filters, that type, and this from_hit. Present only when truncated is true.", + "propertyNames": { + "type": "string" + }, + "type": "object" +} - changed
Output schema / properties / notice / descriptionPrevious 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."New value: +"Guidance on the page returned: how to broaden a search that matched nothing, that from_hit ran past the end when documents did match, or — when truncated is set — how each document type continues." - changed
Output schema / properties / results / descriptionPrevious value: -"Legal document result set spanning advisory opinions, MURs, ADRs, admin fines, and statutes."New value: +"Legal document result set spanning advisory opinions, MURs, ADRs, admin fines, and statutes — only the types searched. Grouped by type in upstream order; when truncated is set, each type holds its first results up to the response budget." - changed
Output schema / properties / results / items / descriptionPrevious 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."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, and disposition_count and disposition_categories summarizing the dispositions." - added
Output schema / properties / shownAdded value: +{ + "description": "Results in this response. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / totalCount / descriptionPrevious value: -"Total matching legal documents across all types."New value: +"Total matching legal documents across the document types searched." - changed
Output schema / properties / total_count / descriptionPrevious value: -"Total matching documents across all types."New value: +"Total matching documents across the types searched: the requested type, or with type omitted, every type the supplied filters apply to." - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when results upstream returned for this page were held back because the next one would take the response past its 100,000-byte budget. Absent when the page is complete, including a naturally short page and an offset past the end.", + "type": "boolean" +}
6 tool updates
- Changed
openfec_search_candidates5 fields changed- changed
Input schema / properties / per_page / descriptionPrevious value: -"Search results per page. Defaults to 20 on the search path."New value: +"Search results per page. Defaults to 20 on the search path. With include_totals, at most 35 candidates are requested when cycle or election_year scopes the totals and 5 when the totals span every cycle, keeping the response under a 100,000-byte budget. A page bounded below your request reports truncated and cap, and pagination.per_page echoes the size applied — page numbers count at that size, so continue with the next page number." - added
Output schema / properties / capAdded value: +{ + "description": "The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious 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."New value: +"Guidance when the response needs context: how to broaden a search that matched nothing, which requested position ran out when candidates did match, or that the page was bounded below the per_page requested and how to continue." - added
Output schema / properties / shownAdded value: +{ + "description": "Rows in this page. Present only when truncated is true.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page.", + "type": "boolean" +}
- Changed
openfec_search_contributions5 fields changed- changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Results per page. Itemized mode sends at most 30 upstream, keeping the response under a 100,000-byte budget; a page bounded below your request reports truncated and cap, and next_cursor continues it." - added
Output schema / properties / capAdded value: +{ + "description": "The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious 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."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, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue." - added
Output schema / properties / shownAdded value: +{ + "description": "Rows in this page. Present only when truncated is true.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page.", + "type": "boolean" +}
- Changed
openfec_search_coordinated_expenditures5 fields changed- changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Results per page. At most 80 are requested upstream when scoped by committee_id and 25 otherwise, keeping the response under a 100,000-byte budget. A page bounded below your request reports truncated and cap, and pagination.per_page echoes the size applied — page numbers count at that size, so continue with the next page number." - added
Output schema / properties / capAdded value: +{ + "description": "The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious 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."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 page was bounded below the per_page requested and how to continue." - added
Output schema / properties / shownAdded value: +{ + "description": "Rows in this page. Present only when truncated is true.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page.", + "type": "boolean" +}
- Changed
openfec_search_disbursements5 fields changed- changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Results per page. Itemized mode sends at most 30 upstream, keeping the response under a 100,000-byte budget; a page bounded below your request reports truncated and cap, and next_cursor continues it." - added
Output schema / properties / capAdded value: +{ + "description": "The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious 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."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, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue." - added
Output schema / properties / shownAdded value: +{ + "description": "Rows in this page. Present only when truncated is true.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page.", + "type": "boolean" +}
- Changed
openfec_search_expenditures8 fields changed- changed
Input schema / properties / cycle / descriptionPrevious 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."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. In by_candidate mode the cycle names the election, and election_full decides whether the totals cover the full election period ending in it (4yr president, 6yr senate, 2yr house) or only this two-year cycle." - added
Input schema / properties / election_fullAdded value: +{ + "description": "by_candidate only: expand cycle to the full election period (4yr president, 6yr senate, 2yr house) instead of the two-year cycle alone. Defaults to true when omitted; itemized mode rejects it, since that endpoint has no such parameter. Carries no schema default, so an explicit value is distinguishable from an omission.", + "type": "boolean" +} - changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Results per page. Itemized mode sends at most 60 upstream when scoped by committee_id and 30 otherwise, keeping the response under a 100,000-byte budget; a page bounded below your request reports truncated and cap, and next_cursor continues it." - added
Output schema / properties / capAdded value: +{ + "description": "The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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 or election_full, neither of which its keyset endpoint can apply. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / notice / descriptionPrevious 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."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, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue." - added
Output schema / properties / shownAdded value: +{ + "description": "Rows in this page. Present only when truncated is true.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page.", + "type": "boolean" +}
- Changed
openfec_search_filings5 fields changed- changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Results per page. At most 65 are requested upstream, keeping the response under a 100,000-byte budget. A page bounded below your request reports truncated and cap, and pagination.per_page echoes the size applied — page numbers count at that size, so continue with the next page number." - added
Output schema / properties / capAdded value: +{ + "description": "The per_page this call applied in place of the one requested — the page-size ceiling for this tool and scope. Present only when truncated is true.", + "type": "number" +} - changed
Output schema / properties / notice / descriptionPrevious 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."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, that the total is an estimate, or that the page was bounded below the per_page requested and how to continue." - added
Output schema / properties / shownAdded value: +{ + "description": "Rows in this page. Present only when truncated is true.", + "type": "number" +} - added
Output schema / properties / truncatedAdded value: +{ + "description": "True when this page holds fewer rows than the per_page requested because a full page would exceed the 100,000-byte response budget, and more rows remain. Absent on a complete page, including a naturally short last page.", + "type": "boolean" +}
2 tool updates
- Changed
openfec_lookup_calendar1 field changed- added
Input schema / properties / districtAdded value: +{ + "description": "Two-digit House district (e.g., \"14\", \"07\"); a single digit is zero-padded. Pair it with state — alone it matches that district number in every state. At-large races carry no district upstream, so a district filter never matches them. Election dates mode.", + "type": "string" +}
- Changed
openfec_search_committees1 field changed- changed
Input schema / properties / designation / descriptionPrevious value: -"Committee designation. A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized)."New value: +"Committee designation. A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized). Matches each committee's current designation only, even with cycle set — a past principal committee since redesignated drops out of P. For a candidate's principal committee in a given cycle, use openfec_lookup_elections (mode: search) and read candidate_pcc_id."
11 tool updates
- Changed
openfec_get_committee_totals2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_lookup_calendar2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_lookup_elections2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_candidates2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_committees2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_contributions4 fields changed- changed
Output schema / properties / count / descriptionPrevious 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." - added
Output schema / properties / count_is_approximateAdded 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" +} - changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_coordinated_expenditures2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_disbursements4 fields changed- changed
Output schema / properties / count / descriptionPrevious 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." - added
Output schema / properties / count_is_approximateAdded 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" +} - changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_expenditures4 fields changed- changed
Output schema / properties / count / descriptionPrevious 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." - added
Output schema / properties / count_is_approximateAdded 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" +} - changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_filings2 fields changed- changed
Output schema / properties / notice / descriptionPrevious 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." - added
Output schema / properties / pagination / properties / count_is_approximateAdded 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" +}
- Changed
openfec_search_legal6 fields changed- changed
Input schema / properties / from_hit / descriptionPrevious 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." - changed
Input schema / properties / from_hit / maximumPrevious value: -9007199254740991New value: +9999 - changed
Input schema / properties / hits_returned / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious 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" +] - changed
Output schema / properties / notice / descriptionPrevious 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."
10 tool updates
- Changed
openfec_get_committee_totals1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_get_legal_document1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_lookup_calendar1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_lookup_elections1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_search_candidates1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_search_committees1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_search_contributions3 fields changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - removed
Output schema / properties / next_cursor / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / next_cursor / typeAdded value: +[ + "string", + "null" +]
- Changed
openfec_search_disbursements3 fields changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - removed
Output schema / properties / next_cursor / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / next_cursor / typeAdded value: +[ + "string", + "null" +]
- Changed
openfec_search_expenditures3 fields changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - removed
Output schema / properties / next_cursor / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / next_cursor / typeAdded value: +[ + "string", + "null" +]
- Changed
openfec_search_legal1 field changed- changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
6 tool updates
- Changed
openfec_lookup_elections5 fields changed- removed
Input schema / properties / page / defaultRemoved value: -1 - changed
Input schema / properties / page / descriptionPrevious 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." - removed
Input schema / properties / per_page / defaultRemoved value: -20 - changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page. Search mode only."New value: +"Results per page. Search mode only; defaults to 20." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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."
- Changed
openfec_search_candidates7 fields changed- changed
Input schema / properties / candidate_id / descriptionPrevious 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." - removed
Input schema / properties / page / defaultRemoved value: -1 - changed
Input schema / properties / page / descriptionPrevious value: -"Page number (1-indexed)."New value: +"Search-results page number (1-indexed). Defaults to 1 on the search path." - removed
Input schema / properties / per_page / defaultRemoved value: -20 - changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Search results per page. Defaults to 20 on the search path." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "candidate_not_found" -]New value: +[ + "candidate_not_found", + "inputs_not_applicable_to_id_lookup" +]
- Changed
openfec_search_committees7 fields changed- changed
Input schema / properties / committee_id / descriptionPrevious 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." - removed
Input schema / properties / page / defaultRemoved value: -1 - changed
Input schema / properties / page / descriptionPrevious value: -"Page number (1-indexed)."New value: +"Search-results page number (1-indexed). Defaults to 1 on the search path." - removed
Input schema / properties / per_page / defaultRemoved value: -20 - changed
Input schema / properties / per_page / descriptionPrevious value: -"Results per page."New value: +"Search results per page. Defaults to 20 on the search path." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "committee_not_found" -]New value: +[ + "committee_not_found", + "inputs_not_applicable_to_id_lookup" +]
- Changed
openfec_search_contributions4 fields changed- removed
Input schema / properties / page / defaultRemoved value: -1 - changed
Input schema / properties / page / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious 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" +]
- Changed
openfec_search_disbursements4 fields changed- removed
Input schema / properties / page / defaultRemoved value: -1 - changed
Input schema / properties / page / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "itemized_only_filters_in_aggregate_mode" -]New value: +[ + "itemized_only_filters_in_aggregate_mode", + "inputs_not_applicable_to_mode" +]
- Changed
openfec_search_expenditures4 fields changed- removed
Input schema / properties / page / defaultRemoved value: -1 - changed
Input schema / properties / page / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious 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." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious 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" +]
12 tool updates
- Changed
openfec_get_committee_totals6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "mode", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "mode", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_get_legal_document6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "document", + "search_criteria", + "attachedDocumentCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "document", - "search_criteria", - "attachedDocumentCount" -]
- Changed
openfec_lookup_calendar6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "mode", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "mode", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_lookup_elections6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "mode", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "mode", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_candidates6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "candidates", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "candidates", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_committees6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "committees", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "committees", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_contributions6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "mode", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "mode", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_coordinated_expenditures6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_disbursements6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "mode", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "mode", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_expenditures6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "mode", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "mode", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_filings6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "pagination", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "pagination", - "search_criteria", - "totalCount" -]
- Changed
openfec_search_legal6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "results", + "total_count", + "search_criteria", + "totalCount" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded 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" +} - removed
Output schema / requiredRemoved value: -[ - "results", - "total_count", - "search_criteria", - "totalCount" -]
4 tool updates
- Added
openfec_get_committee_totals - Added
openfec_get_legal_document - Added
openfec_search_coordinated_expenditures - Changed
openfec_search_legal2 fields changed- changed
Output schema / properties / results / items / descriptionPrevious 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." - added
Output schema / properties / retrievalHintAdded 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" +}
9 tool updates
- Changed
openfec_lookup_calendar3 fields changed- added
Output schema / properties / modeAdded 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" +} - changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "pagination", - "totalCount" -]New value: +[ + "results", + "mode", + "pagination", + "search_criteria", + "totalCount" +]
- Changed
openfec_lookup_elections5 fields changed- removed
Input schema / properties / election_full / defaultRemoved value: -true - changed
Input schema / properties / election_full / descriptionPrevious 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." - added
Output schema / properties / modeAdded 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" +} - changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "pagination", - "totalCount" -]New value: +[ + "results", + "mode", + "pagination", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_candidates2 fields changed- changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "candidates", - "pagination", - "totalCount" -]New value: +[ + "candidates", + "pagination", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_committees2 fields changed- changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "committees", - "pagination", - "totalCount" -]New value: +[ + "committees", + "pagination", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_contributions4 fields changed- added
Output schema / properties / committeeAdded 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" +} - added
Output schema / properties / modeAdded 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" +} - changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "totalCount" -]New value: +[ + "results", + "mode", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_disbursements4 fields changed- added
Output schema / properties / committeeAdded 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" +} - added
Output schema / properties / modeAdded 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" +} - changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "totalCount" -]New value: +[ + "results", + "mode", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_expenditures6 fields changed- removed
Input schema / properties / most_recent / defaultRemoved value: -true - changed
Input schema / properties / most_recent / descriptionPrevious 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." - added
Output schema / properties / committeeAdded 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" +} - added
Output schema / properties / modeAdded 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" +} - changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "totalCount" -]New value: +[ + "results", + "mode", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_filings2 fields changed- changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "pagination", - "totalCount" -]New value: +[ + "results", + "pagination", + "search_criteria", + "totalCount" +]
- Changed
openfec_search_legal2 fields changed- changed
Output schema / properties / search_criteria / descriptionPrevious 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." - changed
Output schema / requiredPrevious value: -[ - "results", - "total_count", - "totalCount" -]New value: +[ + "results", + "total_count", + "search_criteria", + "totalCount" +]
3 tool updates
- Changed
openfec_search_disbursements1 field changed- changed
Input schema / properties / cycle / descriptionPrevious 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."
- Changed
openfec_search_expenditures5 fields changed- changed
Input schema / properties / candidate_office / descriptionPrevious 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." - added
Input schema / properties / candidate_office_districtAdded 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" +} - changed
Input schema / properties / candidate_office_state / descriptionPrevious 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." - changed
Input schema / properties / candidate_party / descriptionPrevious 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." - changed
Input schema / properties / cycle / descriptionPrevious 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."
- Changed
openfec_search_legal5 fields changed- added
Input schema / properties / date_kindAdded 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" +} - changed
Input schema / properties / max_date / descriptionPrevious value: -"Latest document date (YYYY-MM-DD)."New value: +"Latest date (YYYY-MM-DD) for the date_kind selected. Requires type and date_kind." - changed
Input schema / properties / max_penalty_amount / descriptionPrevious 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." - changed
Input schema / properties / min_date / descriptionPrevious value: -"Earliest document date (YYYY-MM-DD)."New value: +"Earliest date (YYYY-MM-DD) for the date_kind selected. Requires type and date_kind." - changed
Input schema / properties / min_penalty_amount / descriptionPrevious 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."
5 tool updates
- Changed
openfec_lookup_elections2 fields changed- added
Input schema / properties / pageAdded 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" +} - added
Input schema / properties / per_pageAdded value: +{ + "default": 20, + "description": "Results per page. Search mode only.", + "maximum": 100, + "minimum": 1, + "type": "integer" +}
- Changed
openfec_search_candidates2 fields changed- added
Output schema / properties / missing_totalsAdded 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" +} - changed
Output schema / properties / totals / descriptionPrevious 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."
- Changed
openfec_search_contributions1 field changed- added
Input schema / properties / pageAdded 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" +}
- Changed
openfec_search_disbursements1 field changed- added
Input schema / properties / pageAdded 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" +}
- Changed
openfec_search_expenditures1 field changed- added
Input schema / properties / pageAdded 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" +}
3 tool updates
- Changed
openfec_search_contributions3 fields changed- changed
Input schema / properties / cursor / descriptionPrevious 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." - changed
Input schema / properties / sort / descriptionPrevious 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." - changed
Input schema / properties / sort / enumPrevious value: -[ - "contribution_receipt_date", - "contribution_receipt_amount" -]New value: +[ + "contribution_receipt_date", + "-contribution_receipt_date", + "contribution_receipt_amount", + "-contribution_receipt_amount" +]
- Changed
openfec_search_disbursements3 fields changed- changed
Input schema / properties / cursor / descriptionPrevious 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." - changed
Input schema / properties / sort / descriptionPrevious 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." - changed
Input schema / properties / sort / enumPrevious value: -[ - "disbursement_date", - "disbursement_amount" -]New value: +[ + "disbursement_date", + "-disbursement_date", + "disbursement_amount", + "-disbursement_amount" +]
- Changed
openfec_search_expenditures3 fields changed- changed
Input schema / properties / cursor / descriptionPrevious 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." - changed
Input schema / properties / sort / descriptionPrevious 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." - changed
Input schema / properties / sort / enumPrevious value: -[ - "expenditure_date", - "expenditure_amount", - "office_total_ytd" -]New value: +[ + "expenditure_date", + "-expenditure_date", + "expenditure_amount", + "-expenditure_amount", + "office_total_ytd", + "-office_total_ytd" +]
6 tool updates
- Changed
openfec_search_candidates1 field changed- removed
Input schema / properties / candidate_id / patternRemoved value: -"^[HSP][0-9A-Z]+$"
- Changed
openfec_search_committees2 fields changed- removed
Input schema / properties / candidate_id / patternRemoved value: -"^[HSP][0-9A-Z]+$" - removed
Input schema / properties / committee_id / patternRemoved value: -"^C\\d+$"
- Changed
openfec_search_contributions2 fields changed- removed
Input schema / properties / candidate_id / patternRemoved value: -"^[HSP][0-9A-Z]+$" - removed
Input schema / properties / committee_id / patternRemoved value: -"^C\\d+$"
- Changed
openfec_search_disbursements1 field changed- removed
Input schema / properties / committee_id / patternRemoved value: -"^C\\d+$"
- Changed
openfec_search_expenditures2 fields changed- removed
Input schema / properties / candidate_id / patternRemoved value: -"^[HSP][0-9A-Z]+$" - removed
Input schema / properties / committee_id / patternRemoved value: -"^C\\d+$"
- Changed
openfec_search_filings2 fields changed- removed
Input schema / properties / candidate_id / patternRemoved value: -"^[HSP][0-9A-Z]+$" - removed
Input schema / properties / committee_id / patternRemoved value: -"^C\\d+$"
1 tool update
- Changed
openfec_search_legal2 fields changed- added
Output schema / properties / totalCountAdded value: +{ + "description": "Total matching legal documents across all types.", + "type": "number" +} - changed
Output schema / requiredPrevious value: -[ - "results", - "total_count" -]New value: +[ + "results", + "total_count", + "totalCount" +]
Related MCP Connectors
FEC campaign finance data: candidate fundraising, donors, and spending
OpenFEC MCP — Federal Election Commission campaign finance data
Access U.S. congressional data (bills, votes, members, committees) via MCP.
Access US federal award, recipient, agency, and spending analytics data from USAspending.gov.
Related MCP Servers
- AlicenseAqualityBmaintenanceQuery FEC campaign finance data — search candidates, track donations, analyze spending, and monitor Super PAC activity via the OpenFEC API.89 npm4MIT
- AlicenseNot gradedqualityDmaintenanceConnects the OpenFEC API to AI assistants for investigating US federal campaign finance through natural language conversations.1MIT
- AlicenseNot gradedqualityBmaintenanceAccess Federal Election Commission campaign finance data through MCP tools. Enables querying OpenFEC data using natural language via ask_pipeworx or direct tool calls.29 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables searching political donations, donors, and lobbying data from any AI assistant using Federal Election Commission data.8 npmMIT
Glama MCP Gateway
Add one secure layer between your agents and this server.