@cyanheads/openfec-mcp-server 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CLAUDE.md +328 -0
  2. package/Dockerfile +99 -0
  3. package/LICENSE +191 -0
  4. package/README.md +297 -0
  5. package/dist/config/server-config.d.ts +17 -0
  6. package/dist/config/server-config.d.ts.map +1 -0
  7. package/dist/config/server-config.js +31 -0
  8. package/dist/config/server-config.js.map +1 -0
  9. package/dist/index.d.ts +8 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +20 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mcp-server/prompts/definitions/campaign-analysis.prompt.d.ts +13 -0
  14. package/dist/mcp-server/prompts/definitions/campaign-analysis.prompt.d.ts.map +1 -0
  15. package/dist/mcp-server/prompts/definitions/campaign-analysis.prompt.js +79 -0
  16. package/dist/mcp-server/prompts/definitions/campaign-analysis.prompt.js.map +1 -0
  17. package/dist/mcp-server/prompts/definitions/index.d.ts +12 -0
  18. package/dist/mcp-server/prompts/definitions/index.d.ts.map +1 -0
  19. package/dist/mcp-server/prompts/definitions/index.js +10 -0
  20. package/dist/mcp-server/prompts/definitions/index.js.map +1 -0
  21. package/dist/mcp-server/prompts/definitions/money-trail.prompt.d.ts +13 -0
  22. package/dist/mcp-server/prompts/definitions/money-trail.prompt.d.ts.map +1 -0
  23. package/dist/mcp-server/prompts/definitions/money-trail.prompt.js +78 -0
  24. package/dist/mcp-server/prompts/definitions/money-trail.prompt.js.map +1 -0
  25. package/dist/mcp-server/resources/definitions/candidate.resource.d.ts +10 -0
  26. package/dist/mcp-server/resources/definitions/candidate.resource.d.ts.map +1 -0
  27. package/dist/mcp-server/resources/definitions/candidate.resource.js +28 -0
  28. package/dist/mcp-server/resources/definitions/candidate.resource.js.map +1 -0
  29. package/dist/mcp-server/resources/definitions/committee.resource.d.ts +10 -0
  30. package/dist/mcp-server/resources/definitions/committee.resource.d.ts.map +1 -0
  31. package/dist/mcp-server/resources/definitions/committee.resource.js +26 -0
  32. package/dist/mcp-server/resources/definitions/committee.resource.js.map +1 -0
  33. package/dist/mcp-server/resources/definitions/election.resource.d.ts +25 -0
  34. package/dist/mcp-server/resources/definitions/election.resource.d.ts.map +1 -0
  35. package/dist/mcp-server/resources/definitions/election.resource.js +73 -0
  36. package/dist/mcp-server/resources/definitions/election.resource.js.map +1 -0
  37. package/dist/mcp-server/resources/definitions/index.d.ts +16 -0
  38. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
  39. package/dist/mcp-server/resources/definitions/index.js +18 -0
  40. package/dist/mcp-server/resources/definitions/index.js.map +1 -0
  41. package/dist/mcp-server/tools/definitions/index.d.ts +285 -0
  42. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
  43. package/dist/mcp-server/tools/definitions/index.js +34 -0
  44. package/dist/mcp-server/tools/definitions/index.js.map +1 -0
  45. package/dist/mcp-server/tools/definitions/lookup-calendar.tool.d.ts +37 -0
  46. package/dist/mcp-server/tools/definitions/lookup-calendar.tool.d.ts.map +1 -0
  47. package/dist/mcp-server/tools/definitions/lookup-calendar.tool.js +172 -0
  48. package/dist/mcp-server/tools/definitions/lookup-calendar.tool.js.map +1 -0
  49. package/dist/mcp-server/tools/definitions/lookup-elections.tool.d.ts +31 -0
  50. package/dist/mcp-server/tools/definitions/lookup-elections.tool.d.ts.map +1 -0
  51. package/dist/mcp-server/tools/definitions/lookup-elections.tool.js +134 -0
  52. package/dist/mcp-server/tools/definitions/lookup-elections.tool.js.map +1 -0
  53. package/dist/mcp-server/tools/definitions/search-candidates.tool.d.ts +46 -0
  54. package/dist/mcp-server/tools/definitions/search-candidates.tool.d.ts.map +1 -0
  55. package/dist/mcp-server/tools/definitions/search-candidates.tool.js +170 -0
  56. package/dist/mcp-server/tools/definitions/search-candidates.tool.js.map +1 -0
  57. package/dist/mcp-server/tools/definitions/search-committees.tool.d.ts +29 -0
  58. package/dist/mcp-server/tools/definitions/search-committees.tool.d.ts.map +1 -0
  59. package/dist/mcp-server/tools/definitions/search-committees.tool.js +120 -0
  60. package/dist/mcp-server/tools/definitions/search-committees.tool.js.map +1 -0
  61. package/dist/mcp-server/tools/definitions/search-contributions.tool.d.ts +47 -0
  62. package/dist/mcp-server/tools/definitions/search-contributions.tool.d.ts.map +1 -0
  63. package/dist/mcp-server/tools/definitions/search-contributions.tool.js +252 -0
  64. package/dist/mcp-server/tools/definitions/search-contributions.tool.js.map +1 -0
  65. package/dist/mcp-server/tools/definitions/search-disbursements.tool.d.ts +43 -0
  66. package/dist/mcp-server/tools/definitions/search-disbursements.tool.d.ts.map +1 -0
  67. package/dist/mcp-server/tools/definitions/search-disbursements.tool.js +212 -0
  68. package/dist/mcp-server/tools/definitions/search-disbursements.tool.js.map +1 -0
  69. package/dist/mcp-server/tools/definitions/search-expenditures.tool.d.ts +52 -0
  70. package/dist/mcp-server/tools/definitions/search-expenditures.tool.d.ts.map +1 -0
  71. package/dist/mcp-server/tools/definitions/search-expenditures.tool.js +247 -0
  72. package/dist/mcp-server/tools/definitions/search-expenditures.tool.js.map +1 -0
  73. package/dist/mcp-server/tools/definitions/search-filings.tool.d.ts +31 -0
  74. package/dist/mcp-server/tools/definitions/search-filings.tool.d.ts.map +1 -0
  75. package/dist/mcp-server/tools/definitions/search-filings.tool.js +123 -0
  76. package/dist/mcp-server/tools/definitions/search-filings.tool.js.map +1 -0
  77. package/dist/mcp-server/tools/definitions/search-legal.tool.d.ts +32 -0
  78. package/dist/mcp-server/tools/definitions/search-legal.tool.d.ts.map +1 -0
  79. package/dist/mcp-server/tools/definitions/search-legal.tool.js +179 -0
  80. package/dist/mcp-server/tools/definitions/search-legal.tool.js.map +1 -0
  81. package/dist/mcp-server/tools/definitions/utils/format-helpers.d.ts +19 -0
  82. package/dist/mcp-server/tools/definitions/utils/format-helpers.d.ts.map +1 -0
  83. package/dist/mcp-server/tools/definitions/utils/format-helpers.js +19 -0
  84. package/dist/mcp-server/tools/definitions/utils/format-helpers.js.map +1 -0
  85. package/dist/mcp-server/tools/definitions/utils/id-validators.d.ts +11 -0
  86. package/dist/mcp-server/tools/definitions/utils/id-validators.d.ts.map +1 -0
  87. package/dist/mcp-server/tools/definitions/utils/id-validators.js +22 -0
  88. package/dist/mcp-server/tools/definitions/utils/id-validators.js.map +1 -0
  89. package/dist/services/openfec/openfec-service.d.ts +54 -0
  90. package/dist/services/openfec/openfec-service.d.ts.map +1 -0
  91. package/dist/services/openfec/openfec-service.js +384 -0
  92. package/dist/services/openfec/openfec-service.js.map +1 -0
  93. package/dist/services/openfec/types.d.ts +86 -0
  94. package/dist/services/openfec/types.d.ts.map +1 -0
  95. package/dist/services/openfec/types.js +8 -0
  96. package/dist/services/openfec/types.js.map +1 -0
  97. package/package.json +91 -0
  98. package/server.json +97 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * @fileoverview Tool for searching and retrieving FEC committee records.
3
+ * Supports full-text search, single-committee lookup by ID, and filtering
4
+ * by candidate affiliation, type, designation, state, and party.
5
+ * @module mcp-server/tools/definitions/search-committees.tool
6
+ */
7
+ import { tool, z } from '@cyanheads/mcp-ts-core';
8
+ import { notFound } from '@cyanheads/mcp-ts-core/errors';
9
+ import { getOpenFecService } from '../../../services/openfec/openfec-service.js';
10
+ import { PaginationSchema, str } from './utils/format-helpers.js';
11
+ import { validateCandidateId, validateCommitteeId } from './utils/id-validators.js';
12
+ export const searchCommittees = tool('openfec_search_committees', {
13
+ description: 'Find political committees (campaign, PAC, Super PAC, party) by name, type, ' +
14
+ 'candidate affiliation, or state. Retrieve a specific committee by FEC ID. ' +
15
+ 'Committee IDs start with C followed by digits (e.g., C00358796).',
16
+ annotations: { readOnlyHint: true, idempotentHint: true },
17
+ input: z.object({
18
+ query: z.string().optional().describe('Full-text committee name search.'),
19
+ committee_id: z
20
+ .string()
21
+ .optional()
22
+ .describe("FEC committee ID (e.g., C00358796). Starts with 'C' followed by digits. Returns a single committee with full detail."),
23
+ candidate_id: z
24
+ .string()
25
+ .optional()
26
+ .describe('Find committees linked to this candidate (authorized, leadership, joint fundraising).'),
27
+ state: z.string().optional().describe('Two-letter state code.'),
28
+ party: z.string().optional().describe('Three-letter party code (e.g., DEM, REP).'),
29
+ committee_type: z
30
+ .string()
31
+ .optional()
32
+ .describe('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).'),
33
+ designation: z
34
+ .string()
35
+ .optional()
36
+ .describe('Committee designation. A (authorized), B (lobbyist PAC), D (leadership PAC), J (joint fundraiser), P (principal campaign), U (unauthorized).'),
37
+ cycle: z.number().optional().describe('Two-year election cycle (even year).'),
38
+ treasurer_name: z.string().optional().describe('Full-text treasurer name search.'),
39
+ page: z.number().optional().describe('Page number (1-indexed). Default 1.'),
40
+ per_page: z.number().optional().describe('Results per page. Default 20, max 100.'),
41
+ }),
42
+ output: z.object({
43
+ committees: z
44
+ .array(z.record(z.string(), z.unknown()))
45
+ .describe('Committee records with committee_id, name, type, designation, party, state, etc.'),
46
+ pagination: PaginationSchema.describe('Page-based pagination metadata.'),
47
+ }),
48
+ async handler(input, ctx) {
49
+ const fec = getOpenFecService();
50
+ if (input.committee_id)
51
+ validateCommitteeId(input.committee_id);
52
+ if (input.candidate_id)
53
+ validateCandidateId(input.candidate_id);
54
+ let result;
55
+ if (input.committee_id) {
56
+ ctx.log.info('Fetching committee by ID', { committee_id: input.committee_id });
57
+ result = await fec.getCommittee(input.committee_id, ctx);
58
+ }
59
+ else {
60
+ const params = {
61
+ q: input.query,
62
+ candidate_id: input.candidate_id,
63
+ state: input.state,
64
+ party: input.party,
65
+ committee_type: input.committee_type,
66
+ designation: input.designation,
67
+ cycle: input.cycle,
68
+ treasurer_name: input.treasurer_name,
69
+ page: input.page,
70
+ per_page: input.per_page,
71
+ };
72
+ ctx.log.info('Searching committees', { query: input.query, state: input.state });
73
+ result = await fec.searchCommittees(params, ctx);
74
+ }
75
+ if (input.committee_id && result.results.length === 0) {
76
+ throw notFound(`Committee ${input.committee_id} not found.`, {
77
+ committee_id: input.committee_id,
78
+ });
79
+ }
80
+ return {
81
+ committees: result.results,
82
+ pagination: result.pagination,
83
+ };
84
+ },
85
+ format(result) {
86
+ if (result.committees.length === 0) {
87
+ return [
88
+ {
89
+ type: 'text',
90
+ text: 'No committees found. Try a partial name, remove type/designation filters, or search by candidate_id to find linked committees.',
91
+ },
92
+ ];
93
+ }
94
+ const lines = result.committees.map((c) => {
95
+ const id = str(c, 'committee_id');
96
+ const name = str(c, 'name');
97
+ const type = str(c, 'committee_type_full') || str(c, 'committee_type');
98
+ const designation = str(c, 'designation_full') || str(c, 'designation');
99
+ const party = str(c, 'party_full') || str(c, 'party');
100
+ const state = str(c, 'state');
101
+ const treasurer = str(c, 'treasurer_name');
102
+ let line = `**${name}** (${id})\n Type: ${type} | Designation: ${designation}`;
103
+ if (party)
104
+ line += ` | ${party}`;
105
+ if (state)
106
+ line += ` | ${state}`;
107
+ if (treasurer)
108
+ line += `\n Treasurer: ${treasurer}`;
109
+ const candidateIds = c.candidate_ids;
110
+ if (Array.isArray(candidateIds) && candidateIds.length > 0) {
111
+ line += `\n Candidates: ${candidateIds.join(', ')}`;
112
+ }
113
+ return line;
114
+ });
115
+ const { page, pages, count } = result.pagination;
116
+ lines.push(`\n---\nPage ${page} of ${pages} (${count} total)`);
117
+ return [{ type: 'text', text: lines.join('\n\n') }];
118
+ },
119
+ });
120
+ //# sourceMappingURL=search-committees.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-committees.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-committees.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @fileoverview Search itemized individual contributions (Schedule A) or get
3
+ * aggregate breakdowns by size, state, employer, or occupation. Central tool
4
+ * for answering "who's funding this candidate/committee?"
5
+ * @module mcp-server/tools/definitions/search-contributions.tool
6
+ */
7
+ import { z } from '@cyanheads/mcp-ts-core';
8
+ export declare const searchContributions: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
9
+ mode: z.ZodDefault<z.ZodEnum<{
10
+ by_size: "by_size";
11
+ by_state: "by_state";
12
+ by_employer: "by_employer";
13
+ by_occupation: "by_occupation";
14
+ itemized: "itemized";
15
+ }>>;
16
+ committee_id: z.ZodOptional<z.ZodString>;
17
+ candidate_id: z.ZodOptional<z.ZodString>;
18
+ contributor_name: z.ZodOptional<z.ZodString>;
19
+ contributor_employer: z.ZodOptional<z.ZodString>;
20
+ contributor_occupation: z.ZodOptional<z.ZodString>;
21
+ contributor_city: z.ZodOptional<z.ZodString>;
22
+ contributor_state: z.ZodOptional<z.ZodString>;
23
+ contributor_zip: z.ZodOptional<z.ZodString>;
24
+ cycle: z.ZodOptional<z.ZodNumber>;
25
+ min_date: z.ZodOptional<z.ZodString>;
26
+ max_date: z.ZodOptional<z.ZodString>;
27
+ min_amount: z.ZodOptional<z.ZodNumber>;
28
+ max_amount: z.ZodOptional<z.ZodNumber>;
29
+ is_individual: z.ZodOptional<z.ZodBoolean>;
30
+ sort: z.ZodOptional<z.ZodEnum<{
31
+ contribution_receipt_date: "contribution_receipt_date";
32
+ contribution_receipt_amount: "contribution_receipt_amount";
33
+ }>>;
34
+ per_page: z.ZodDefault<z.ZodNumber>;
35
+ cursor: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>, z.ZodObject<{
37
+ results: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
38
+ next_cursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
39
+ count: z.ZodOptional<z.ZodNumber>;
40
+ pagination: z.ZodOptional<z.ZodObject<{
41
+ page: z.ZodNumber;
42
+ pages: z.ZodNumber;
43
+ count: z.ZodNumber;
44
+ per_page: z.ZodNumber;
45
+ }, z.core.$strip>>;
46
+ }, z.core.$strip>>;
47
+ //# sourceMappingURL=search-contributions.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-contributions.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-contributions.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAejD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6P9B,CAAC"}
@@ -0,0 +1,252 @@
1
+ /**
2
+ * @fileoverview Search itemized individual contributions (Schedule A) or get
3
+ * aggregate breakdowns by size, state, employer, or occupation. Central tool
4
+ * for answering "who's funding this candidate/committee?"
5
+ * @module mcp-server/tools/definitions/search-contributions.tool
6
+ */
7
+ import { tool, z } from '@cyanheads/mcp-ts-core';
8
+ import { invalidParams } from '@cyanheads/mcp-ts-core/errors';
9
+ import { decodeCursor, getOpenFecService } from '../../../services/openfec/openfec-service.js';
10
+ import { fmt$ } from './utils/format-helpers.js';
11
+ import { validateCandidateId, validateCommitteeId } from './utils/id-validators.js';
12
+ /** Derive the current two-year election cycle (always even). */
13
+ const currentCycle = () => {
14
+ const year = new Date().getFullYear();
15
+ return year % 2 === 0 ? year : year + 1;
16
+ };
17
+ const modes = ['itemized', 'by_size', 'by_state', 'by_employer', 'by_occupation'];
18
+ export const searchContributions = tool('openfec_search_contributions', {
19
+ description: 'Search itemized individual contributions (Schedule A) or get aggregate breakdowns ' +
20
+ 'by size, state, employer, or occupation. Use to answer "who is funding this committee?" ' +
21
+ 'Itemized mode requires a committee_id. Aggregate by_size/by_state can use candidate_id instead.',
22
+ annotations: { readOnlyHint: true, idempotentHint: true },
23
+ input: z.object({
24
+ mode: z
25
+ .enum(modes)
26
+ .default('itemized')
27
+ .describe('Query mode. "itemized" returns individual contribution records (keyset pagination). ' +
28
+ '"by_size" aggregates by contribution size bucket. "by_state" aggregates by contributor state. ' +
29
+ '"by_employer" aggregates by employer. "by_occupation" aggregates by occupation.'),
30
+ committee_id: z.string().optional().describe('Receiving committee ID (e.g., C00703975).'),
31
+ candidate_id: z
32
+ .string()
33
+ .optional()
34
+ .describe('Candidate ID. Used with by_size/by_state aggregates to route to the /by_candidate variant.'),
35
+ contributor_name: z.string().optional().describe('Full-text donor name search. Itemized only.'),
36
+ contributor_employer: z
37
+ .string()
38
+ .optional()
39
+ .describe('Full-text employer search. Itemized only.'),
40
+ contributor_occupation: z
41
+ .string()
42
+ .optional()
43
+ .describe('Full-text occupation search. Itemized only.'),
44
+ contributor_city: z.string().optional().describe('Contributor city. Itemized only.'),
45
+ contributor_state: z
46
+ .string()
47
+ .optional()
48
+ .describe('Two-letter state code (e.g., CA). Itemized only.'),
49
+ contributor_zip: z
50
+ .string()
51
+ .optional()
52
+ .describe('ZIP code prefix (starts-with match). Itemized only.'),
53
+ cycle: z
54
+ .number()
55
+ .optional()
56
+ .describe('Two-year election cycle (e.g., 2024). Even years only. ' +
57
+ 'Defaults to current cycle for itemized mode (API requires two_year_transaction_period).'),
58
+ min_date: z
59
+ .string()
60
+ .optional()
61
+ .describe('Earliest contribution date (YYYY-MM-DD). Itemized only.'),
62
+ max_date: z
63
+ .string()
64
+ .optional()
65
+ .describe('Latest contribution date (YYYY-MM-DD). Itemized only.'),
66
+ min_amount: z
67
+ .number()
68
+ .optional()
69
+ .describe('Minimum contribution amount in dollars. Itemized only.'),
70
+ max_amount: z
71
+ .number()
72
+ .optional()
73
+ .describe('Maximum contribution amount in dollars. Itemized only.'),
74
+ is_individual: z
75
+ .boolean()
76
+ .optional()
77
+ .describe('Only individual contributions (excludes committee-to-committee transfers). Itemized only.'),
78
+ sort: z
79
+ .enum(['contribution_receipt_date', 'contribution_receipt_amount'])
80
+ .optional()
81
+ .describe('Sort field. Itemized only.'),
82
+ per_page: z.number().default(20).describe('Results per page (max 100).'),
83
+ cursor: z
84
+ .string()
85
+ .optional()
86
+ .describe('Opaque pagination cursor from a previous response. Itemized mode only (keyset pagination).'),
87
+ }),
88
+ output: z.object({
89
+ results: z
90
+ .array(z.record(z.string(), z.unknown()))
91
+ .describe('Contribution records (itemized) or aggregate rows.'),
92
+ next_cursor: z
93
+ .string()
94
+ .nullable()
95
+ .optional()
96
+ .describe('Pagination cursor for the next page of itemized results. Null when no more pages.'),
97
+ count: z.number().optional().describe('Total result count (may be approximate for itemized).'),
98
+ pagination: z
99
+ .object({
100
+ page: z.number().describe('Current page number.'),
101
+ pages: z.number().describe('Total pages.'),
102
+ count: z.number().describe('Total results.'),
103
+ per_page: z.number().describe('Results per page.'),
104
+ })
105
+ .optional()
106
+ .describe('Page-based pagination info (aggregate modes only).'),
107
+ }),
108
+ async handler(input, ctx) {
109
+ const fec = getOpenFecService();
110
+ const mode = input.mode;
111
+ if (input.committee_id)
112
+ validateCommitteeId(input.committee_id);
113
+ if (input.candidate_id)
114
+ validateCandidateId(input.candidate_id);
115
+ /* ---------------------------------------------------------------- */
116
+ /* Itemized contributions (keyset/SEEK) */
117
+ /* ---------------------------------------------------------------- */
118
+ if (mode === 'itemized') {
119
+ if (!input.committee_id) {
120
+ throw invalidParams('Itemized contribution search requires a committee_id. To search contributions ' +
121
+ 'by candidate, use a "by_size" or "by_state" aggregate mode with candidate_id, ' +
122
+ "or first look up the candidate's committee with openfec_search_committees.");
123
+ }
124
+ const cycle = input.cycle ?? currentCycle();
125
+ const params = {
126
+ committee_id: input.committee_id,
127
+ two_year_transaction_period: cycle,
128
+ per_page: input.per_page,
129
+ };
130
+ if (input.contributor_name)
131
+ params.contributor_name = input.contributor_name;
132
+ if (input.contributor_employer)
133
+ params.contributor_employer = input.contributor_employer;
134
+ if (input.contributor_occupation)
135
+ params.contributor_occupation = input.contributor_occupation;
136
+ if (input.contributor_city)
137
+ params.contributor_city = input.contributor_city;
138
+ if (input.contributor_state)
139
+ params.contributor_state = input.contributor_state;
140
+ if (input.contributor_zip)
141
+ params.contributor_zip = input.contributor_zip;
142
+ if (input.min_date)
143
+ params.min_date = input.min_date;
144
+ if (input.max_date)
145
+ params.max_date = input.max_date;
146
+ if (input.min_amount !== undefined)
147
+ params.min_amount = input.min_amount;
148
+ if (input.max_amount !== undefined)
149
+ params.max_amount = input.max_amount;
150
+ if (input.is_individual !== undefined)
151
+ params.is_individual = input.is_individual;
152
+ if (input.sort)
153
+ params.sort = input.sort;
154
+ if (input.cursor) {
155
+ const lastIndexes = decodeCursor(input.cursor);
156
+ Object.assign(params, lastIndexes);
157
+ }
158
+ const result = await fec.searchContributions(params, ctx);
159
+ ctx.log.info('Itemized contributions fetched', {
160
+ committee_id: input.committee_id,
161
+ cycle,
162
+ count: result.pagination.count,
163
+ returned: result.results.length,
164
+ });
165
+ return {
166
+ results: result.results,
167
+ next_cursor: result.nextCursor,
168
+ count: result.pagination.count,
169
+ };
170
+ }
171
+ /* ---------------------------------------------------------------- */
172
+ /* Aggregate modes */
173
+ /* ---------------------------------------------------------------- */
174
+ if (mode === 'by_employer' || mode === 'by_occupation') {
175
+ if (!input.committee_id) {
176
+ throw invalidParams(`Aggregate by ${mode.replace('by_', '')} requires a committee_id.`);
177
+ }
178
+ }
179
+ const params = { per_page: input.per_page };
180
+ if (input.committee_id)
181
+ params.committee_id = input.committee_id;
182
+ if (input.candidate_id)
183
+ params.candidate_id = input.candidate_id;
184
+ if (input.cycle)
185
+ params.cycle = input.cycle;
186
+ // For by_size and by_state, route to /by_candidate variant when candidate_id is provided
187
+ let aggregateMode = mode;
188
+ if ((mode === 'by_size' || mode === 'by_state') && input.candidate_id) {
189
+ aggregateMode = `${mode}_candidate`;
190
+ }
191
+ const result = await fec.getContributionAggregates(aggregateMode, params, ctx);
192
+ ctx.log.info('Contribution aggregates fetched', {
193
+ mode: aggregateMode,
194
+ count: result.pagination.count,
195
+ returned: result.results.length,
196
+ });
197
+ return {
198
+ results: result.results,
199
+ pagination: result.pagination,
200
+ };
201
+ },
202
+ format: (result) => {
203
+ if (result.results.length === 0) {
204
+ return [
205
+ {
206
+ type: 'text',
207
+ text: 'No contributions found. For itemized mode, try a different cycle or broaden name/employer filters. For aggregates, verify the committee_id or candidate_id is correct.',
208
+ },
209
+ ];
210
+ }
211
+ // Detect itemized vs aggregate by presence of next_cursor key
212
+ const isItemized = 'next_cursor' in result && result.next_cursor !== undefined;
213
+ if (isItemized) {
214
+ const lines = [
215
+ `**${result.count?.toLocaleString() ?? '?'} total contributions**\n`,
216
+ ];
217
+ for (const r of result.results) {
218
+ const name = r.contributor_name ?? 'Unknown';
219
+ const employer = r.contributor_employer ?? '';
220
+ const amount = fmt$(r.contribution_receipt_amount);
221
+ const date = r.contribution_receipt_date ?? '';
222
+ const committee = r.committee_name ?? r.committee_id ?? '';
223
+ const city = r.contributor_city ?? '';
224
+ const state = r.contributor_state ?? '';
225
+ const location = [city, state].filter(Boolean).join(', ');
226
+ lines.push(`- **${name}** ${location ? `(${location})` : ''}`);
227
+ lines.push(` ${amount} on ${date} → ${committee}`);
228
+ if (employer)
229
+ lines.push(` Employer: ${employer}`);
230
+ }
231
+ if (result.next_cursor) {
232
+ lines.push(`\n_More results available — pass cursor to continue._`);
233
+ }
234
+ return [{ type: 'text', text: lines.join('\n') }];
235
+ }
236
+ // Aggregate
237
+ const lines = [
238
+ `**${result.pagination?.count?.toLocaleString() ?? '?'} aggregate rows**\n`,
239
+ ];
240
+ for (const r of result.results) {
241
+ const dimension = r.size ?? r.state ?? r.employer ?? r.occupation ?? r.state_full ?? 'Unknown';
242
+ const total = fmt$(r.total);
243
+ const count = typeof r.count === 'number' ? ` (${r.count.toLocaleString()} contributions)` : '';
244
+ lines.push(`- **${dimension}**: ${total}${count}`);
245
+ }
246
+ if (result.pagination && result.pagination.page < result.pagination.pages) {
247
+ lines.push(`\n_Page ${result.pagination.page} of ${result.pagination.pages}_`);
248
+ }
249
+ return [{ type: 'text', text: lines.join('\n') }];
250
+ },
251
+ });
252
+ //# sourceMappingURL=search-contributions.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-contributions.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-contributions.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAExF,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpF,gEAAgE;AAChE,MAAM,YAAY,GAAG,GAAG,EAAE;IACxB,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;AAC1C,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,eAAe,CAAU,CAAC;AAE3F,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC,8BAA8B,EAAE;IACtE,WAAW,EACT,oFAAoF;QACpF,0FAA0F;QAC1F,iGAAiG;IACnG,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;IAEzD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,KAAK,CAAC;aACX,OAAO,CAAC,UAAU,CAAC;aACnB,QAAQ,CACP,sFAAsF;YACpF,gGAAgG;YAChG,iFAAiF,CACpF;QACH,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;QACzF,YAAY,EAAE,CAAC;aACZ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,4FAA4F,CAC7F;QACH,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;QAC/F,oBAAoB,EAAE,CAAC;aACpB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,2CAA2C,CAAC;QACxD,sBAAsB,EAAE,CAAC;aACtB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,6CAA6C,CAAC;QAC1D,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACpF,iBAAiB,EAAE,CAAC;aACjB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,eAAe,EAAE,CAAC;aACf,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,qDAAqD,CAAC;QAClE,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,yDAAyD;YACvD,yFAAyF,CAC5F;QACH,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,yDAAyD,CAAC;QACtE,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,uDAAuD,CAAC;QACpE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,aAAa,EAAE,CAAC;aACb,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CACP,2FAA2F,CAC5F;QACH,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,2BAA2B,EAAE,6BAA6B,CAAC,CAAC;aAClE,QAAQ,EAAE;aACV,QAAQ,CAAC,4BAA4B,CAAC;QACzC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACxE,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,4FAA4F,CAC7F;KACJ,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC;aACP,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;aACxC,QAAQ,CAAC,oDAAoD,CAAC;QACjE,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CACP,mFAAmF,CACpF;QACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QAC9F,UAAU,EAAE,CAAC;aACV,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACjD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;YAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;SACnD,CAAC;aACD,QAAQ,EAAE;aACV,QAAQ,CAAC,oDAAoD,CAAC;KAClE,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAExB,IAAI,KAAK,CAAC,YAAY;YAAE,mBAAmB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAChE,IAAI,KAAK,CAAC,YAAY;YAAE,mBAAmB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAEhE,sEAAsE;QACtE,sEAAsE;QACtE,sEAAsE;QACtE,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBACxB,MAAM,aAAa,CACjB,gFAAgF;oBAC9E,gFAAgF;oBAChF,4EAA4E,CAC/E,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,YAAY,EAAE,CAAC;YAC5C,MAAM,MAAM,GAAc;gBACxB,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,2BAA2B,EAAE,KAAK;gBAClC,QAAQ,EAAE,KAAK,CAAC,QAAQ;aACzB,CAAC;YAEF,IAAI,KAAK,CAAC,gBAAgB;gBAAE,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;YAC7E,IAAI,KAAK,CAAC,oBAAoB;gBAAE,MAAM,CAAC,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,CAAC;YACzF,IAAI,KAAK,CAAC,sBAAsB;gBAC9B,MAAM,CAAC,sBAAsB,GAAG,KAAK,CAAC,sBAAsB,CAAC;YAC/D,IAAI,KAAK,CAAC,gBAAgB;gBAAE,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;YAC7E,IAAI,KAAK,CAAC,iBAAiB;gBAAE,MAAM,CAAC,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,CAAC;YAChF,IAAI,KAAK,CAAC,eAAe;gBAAE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;YAC1E,IAAI,KAAK,CAAC,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YACrD,IAAI,KAAK,CAAC,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;YACrD,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;gBAAE,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YACzE,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;gBAAE,MAAM,CAAC,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;YACzE,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS;gBAAE,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;YAClF,IAAI,KAAK,CAAC,IAAI;gBAAE,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YAEzC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YACrC,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC1D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,EAAE;gBAC7C,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,KAAK;gBACL,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK;gBAC9B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;aAChC,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,WAAW,EAAE,MAAM,CAAC,UAAU;gBAC9B,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK;aAC/B,CAAC;QACJ,CAAC;QAED,sEAAsE;QACtE,sEAAsE;QACtE,sEAAsE;QACtE,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;YACvD,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;gBACxB,MAAM,aAAa,CAAC,gBAAgB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,2BAA2B,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAc,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QACvD,IAAI,KAAK,CAAC,YAAY;YAAE,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QACjE,IAAI,KAAK,CAAC,YAAY;YAAE,MAAM,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC;QACjE,IAAI,KAAK,CAAC,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAE5C,yFAAyF;QACzF,IAAI,aAAa,GAAW,IAAI,CAAC;QACjC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU,CAAC,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACtE,aAAa,GAAG,GAAG,IAAI,YAAY,CAAC;QACtC,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,yBAAyB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAC/E,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,iCAAiC,EAAE;YAC9C,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK;YAC9B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;SAChC,CAAC,CAAC;QAEH,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO;gBACL;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,wKAAwK;iBAC/K;aACF,CAAC;QACJ,CAAC;QAED,8DAA8D;QAC9D,MAAM,UAAU,GAAG,aAAa,IAAI,MAAM,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,CAAC;QAE/E,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,KAAK,GAAa;gBACtB,KAAK,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,GAAG,0BAA0B;aACrE,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,gBAAgB,IAAI,SAAS,CAAC;gBAC7C,MAAM,QAAQ,GAAG,CAAC,CAAC,oBAAoB,IAAI,EAAE,CAAC;gBAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,CAAC,CAAC,yBAAyB,IAAI,EAAE,CAAC;gBAC/C,MAAM,SAAS,GAAG,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,YAAY,IAAI,EAAE,CAAC;gBAC3D,MAAM,IAAI,GAAG,CAAC,CAAC,gBAAgB,IAAI,EAAE,CAAC;gBACtC,MAAM,KAAK,GAAG,CAAC,CAAC,iBAAiB,IAAI,EAAE,CAAC;gBACxC,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAE1D,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/D,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,OAAO,IAAI,MAAM,SAAS,EAAE,CAAC,CAAC;gBACpD,IAAI,QAAQ;oBAAE,KAAK,CAAC,IAAI,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;YACtE,CAAC;YACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,YAAY;QACZ,MAAM,KAAK,GAAa;YACtB,KAAK,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,GAAG,qBAAqB;SAC5E,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,SAAS,GACb,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,SAAS,CAAC;YAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC5B,MAAM,KAAK,GACT,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;YACpF,KAAK,CAAC,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YAC1E,KAAK,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,UAAU,CAAC,IAAI,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC;QACjF,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Search itemized committee spending (Schedule B) or get aggregate
3
+ * breakdowns by purpose or recipient. Answers "what is this committee spending money on?"
4
+ * @module mcp-server/tools/definitions/search-disbursements.tool
5
+ */
6
+ import { z } from '@cyanheads/mcp-ts-core';
7
+ export declare const searchDisbursements: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ mode: z.ZodDefault<z.ZodEnum<{
9
+ by_purpose: "by_purpose";
10
+ by_recipient: "by_recipient";
11
+ by_recipient_id: "by_recipient_id";
12
+ itemized: "itemized";
13
+ }>>;
14
+ committee_id: z.ZodString;
15
+ recipient_name: z.ZodOptional<z.ZodString>;
16
+ recipient_state: z.ZodOptional<z.ZodString>;
17
+ recipient_city: z.ZodOptional<z.ZodString>;
18
+ recipient_committee_id: z.ZodOptional<z.ZodString>;
19
+ disbursement_description: z.ZodOptional<z.ZodString>;
20
+ disbursement_purpose_category: z.ZodOptional<z.ZodString>;
21
+ cycle: z.ZodOptional<z.ZodNumber>;
22
+ min_date: z.ZodOptional<z.ZodString>;
23
+ max_date: z.ZodOptional<z.ZodString>;
24
+ min_amount: z.ZodOptional<z.ZodNumber>;
25
+ max_amount: z.ZodOptional<z.ZodNumber>;
26
+ sort: z.ZodOptional<z.ZodEnum<{
27
+ disbursement_date: "disbursement_date";
28
+ disbursement_amount: "disbursement_amount";
29
+ }>>;
30
+ per_page: z.ZodDefault<z.ZodNumber>;
31
+ cursor: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>, z.ZodObject<{
33
+ results: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
34
+ next_cursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
35
+ count: z.ZodOptional<z.ZodNumber>;
36
+ pagination: z.ZodOptional<z.ZodObject<{
37
+ page: z.ZodNumber;
38
+ pages: z.ZodNumber;
39
+ count: z.ZodNumber;
40
+ per_page: z.ZodNumber;
41
+ }, z.core.$strip>>;
42
+ }, z.core.$strip>>;
43
+ //# sourceMappingURL=search-disbursements.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-disbursements.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-disbursements.tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAQjD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAuN9B,CAAC"}