@cyanheads/openfec-mcp-server 0.4.3 → 0.4.5

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.
package/CLAUDE.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** openfec-mcp-server
4
- **Version:** 0.4.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.8.19`
4
+ **Version:** 0.4.5
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.9.6`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
 
8
8
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
@@ -151,7 +151,7 @@ export const moneyTrailPrompt = prompt('openfec_money_trail', {
151
151
  import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
152
152
 
153
153
  const ServerConfigSchema = z.object({
154
- fecApiKey: z.string().min(1, 'FEC_API_KEY is required.'),
154
+ fecApiKey: z.string().default('DEMO_KEY').describe('OpenFEC API key — optional (DEMO_KEY: 30 req/hr, own key: 1000 req/hr)'),
155
155
  fecBaseUrl: z.string().default('https://api.open.fec.gov/v1').describe('OpenFEC API base URL'),
156
156
  fecMaxRetries: z.coerce.number().int().min(0).default(3).describe('Max retry attempts'),
157
157
  fecRequestTimeout: z.coerce.number().int().min(1000).default(30_000).describe('Request timeout in ms'),
@@ -317,9 +317,13 @@ When you complete a skill's checklist, check the boxes and add a completion time
317
317
  | `bun run rebuild` | Clean + build |
318
318
  | `bun run clean` | Remove build artifacts |
319
319
  | `bun run devcheck` | Lint + format + typecheck + security |
320
+ | `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-audit. Use when `devcheck` flags a transitive advisory — stale lockfile can mask already-patched deps. If advisory survives, it's real. |
320
321
  | `bun run tree` | Generate directory structure doc |
321
322
  | `bun run format` | Auto-fix formatting |
322
323
  | `bun run lint:mcp` | Validate MCP tool/resource/prompt definitions |
324
+ | `bun run lint:packaging` | Validate `manifest.json` + `server.json` env var alignment |
325
+ | `bun run list-skills` | Print index of available project skills |
326
+ | `bun run bundle` | Build and pack as `.mcpb` for one-click Claude Desktop install |
323
327
  | `bun run test` | Run tests |
324
328
  | `bun run start` | Production mode (transport from `MCP_TRANSPORT_TYPE`) |
325
329
  | `bun run start:stdio` | Production mode (stdio) |
@@ -329,6 +333,14 @@ For dev / smoke-testing, use `bun run rebuild && bun run start:stdio` (or `start
329
333
 
330
334
  ---
331
335
 
336
+ ## Bundling
337
+
338
+ `bun run bundle` produces a `.mcpb` extension bundle for one-click install in Claude Desktop. MCPB is stdio-only — HTTP deployments are unaffected. If you don't need it, delete `manifest.json` and `.mcpbignore`; `lint:packaging` skips cleanly.
339
+
340
+ **Adding an env var requires both files:** `server.json` (registry discovery, `environmentVariables[]`) and `manifest.json` (bundle install UX, `mcp_config.env` + `user_config`). `lint:packaging` (run by `devcheck`) verifies the env var names match.
341
+
342
+ ---
343
+
332
344
  ## Publishing
333
345
 
334
346
  Run the `release-and-publish` skill for the full flow (verification gate, push, npm + MCP Registry + GHCR). Reference commands:
@@ -359,12 +371,15 @@ import { getOpenFecService } from '@/services/openfec/openfec-service.js';
359
371
 
360
372
  ## Checklist
361
373
 
362
- - [ ] Zod schemas: all fields have `.describe()` (including nested object fields and array element types), only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`, `z.function()`, `z.nan()`)
363
- - [ ] Optional nested objects: handler guards for empty inner values from form-based clients (`if (input.obj?.field && ...)`, not just `if (input.obj)`)
374
+ - [ ] Zod schemas: all fields have `.describe()` (including nested object fields and array element types), only JSON-Schema-serializable types (no `z.custom()`, `z.date()`, `z.transform()`, `z.bigint()`, `z.symbol()`, `z.void()`, `z.map()`, `z.set()`, `z.function()`, `z.nan()`); avoid non-portable `format` emitters (`z.url()`, `z.cuid()`, `z.ulid()`, `z.nanoid()`, `z.base64()`, `z.jwt()`) — use `z.string()` with the constraint in `.describe()`
375
+ - [ ] Optional nested objects: handler guards for empty inner values from form-based clients (`if (input.obj?.field && ...)`, not just `if (input.obj)`). When regex/length constraints matter, use `z.union([z.literal(''), z.string().regex(...).describe(...)])` — literal variants are exempt from `describe-on-fields`.
364
376
  - [ ] JSDoc `@fileoverview` + `@module` on every file
365
377
  - [ ] `ctx.log` for logging, `ctx.state` for storage
366
378
  - [ ] Handlers throw on failure — error factories or plain `Error`, no try/catch
367
379
  - [ ] `format()` renders all data the LLM needs — different clients forward different surfaces (Claude Code → `structuredContent`, Claude Desktop → `content[]`); both must carry the same data
380
+ - [ ] Wrapping the OpenFEC API: raw/domain/output schemas reviewed against real upstream sparsity/nullability before finalizing required vs optional fields
381
+ - [ ] Wrapping the OpenFEC API: normalization and `format()` preserve uncertainty; do not fabricate facts from missing upstream data
382
+ - [ ] Wrapping the OpenFEC API: tests include at least one sparse payload case with omitted upstream fields
368
383
  - [ ] Registered in `createApp()` arrays (directly or via barrel exports)
369
384
  - [ ] Tests use `createMockContext()` from `@cyanheads/mcp-ts-core/testing`
370
385
  - [ ] `bun run devcheck` passes
package/README.md CHANGED
@@ -1,14 +1,21 @@
1
1
  <div align="center">
2
2
  <h1>@cyanheads/openfec-mcp-server</h1>
3
- <p><b>Access FEC campaign finance data through MCP. Query data about candidates, money trails, and election filings. STDIO & Streamable HTTP.</b></p>
4
- <p><b>9 Tools · 5 Resources · 2 Prompts</b></p>
3
+ <p><b>Access FEC campaign finance data through MCP. Query data about candidates, money trails, and election filings. STDIO & Streamable HTTP.</b>
4
+ <div>9 Tools 5 Resources 2 Prompts</div>
5
+ </p>
5
6
  </div>
6
7
 
7
8
  <div align="center">
8
9
 
9
- [![npm](https://img.shields.io/npm/v/@cyanheads/openfec-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openfec-mcp-server) [![Version](https://img.shields.io/badge/Version-0.4.3-blue.svg?style=flat-square)](./CHANGELOG.md) [![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-259?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/)
10
+ [![npm](https://img.shields.io/npm/v/@cyanheads/openfec-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openfec-mcp-server) [![Version](https://img.shields.io/badge/Version-0.4.5-blue.svg?style=flat-square)](./CHANGELOG.md) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/openfec-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-^1.3.0-f9f1e1.svg?style=flat-square)](https://bun.sh/)
10
11
 
11
- [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-^1.3.0-f9f1e1.svg?style=flat-square)](https://bun.sh/)
12
+ </div>
13
+
14
+ <div align="center">
15
+
16
+ [![Install in Claude Desktop](https://img.shields.io/badge/Install_in-Claude_Desktop-D97757?style=for-the-badge&logo=anthropic&logoColor=white)](https://github.com/cyanheads/openfec-mcp-server/releases/latest/download/openfec-mcp-server.mcpb)
17
+
18
+ [![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-67E8F9?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
12
19
 
13
20
  </div>
14
21
 
@@ -233,8 +240,8 @@ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 FEC_API_KEY=your-key bun run start:ht
233
240
 
234
241
  ### Prerequisites
235
242
 
236
- - [Bun v1.2.0](https://bun.sh/) or higher
237
- - A free [OpenFEC API key](https://api.data.gov/signup/)
243
+ - [Bun v1.3.0](https://bun.sh/) or higher (or Node ≥24)
244
+ - (Optional) A free [OpenFEC API key](https://api.data.gov/signup/) for higher rate limits (1,000 req/hr vs 30 req/hr with the default `DEMO_KEY`)
238
245
 
239
246
  ### Installation
240
247
 
@@ -260,7 +267,7 @@ bun install
260
267
 
261
268
  | Variable | Description | Default |
262
269
  |:---------|:------------|:--------|
263
- | `FEC_API_KEY` | **Required.** OpenFEC API key. Get one free at [api.data.gov/signup](https://api.data.gov/signup/). | |
270
+ | `FEC_API_KEY` | OpenFEC API key. Optional defaults to `DEMO_KEY` (30 req/hr). Provide your own key (free at [api.data.gov/signup](https://api.data.gov/signup/)) for 1,000 req/hr. | `DEMO_KEY` |
264
271
  | `FEC_BASE_URL` | OpenFEC API base URL. | `https://api.open.fec.gov/v1` |
265
272
  | `FEC_MAX_RETRIES` | Max retry attempts for failed API requests. | `3` |
266
273
  | `FEC_REQUEST_TIMEOUT` | Request timeout in milliseconds. | `30000` |
@@ -271,27 +278,22 @@ bun install
271
278
  | `MCP_LOG_LEVEL` | Log level (RFC 5424). | `info` |
272
279
  | `LOGS_DIR` | Directory for log files (Node.js only). | `<project-root>/logs` |
273
280
  | `STORAGE_PROVIDER_TYPE` | Storage backend. | `in-memory` |
274
- | `OTEL_ENABLED` | Enable OpenTelemetry tracing. | `false` |
281
+ | `OTEL_ENABLED` | Enable [OpenTelemetry instrumentation](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry) (spans, metrics, completion logs). | `false` |
275
282
 
276
283
  ## Running the Server
277
284
 
278
285
  ### Local Development
279
286
 
280
- - **Build and run the production version:**
281
- ```sh
282
- bun run build
283
- bun run start:http # or start:stdio
284
- ```
285
-
286
- - **Run in dev mode (with watch):**
287
+ - **Build and run:**
287
288
  ```sh
288
- bun run dev:stdio # or dev:http
289
+ bun run rebuild
290
+ bun run start:stdio # or start:http
289
291
  ```
290
292
 
291
293
  - **Run checks and tests:**
292
294
  ```sh
293
- bun run devcheck # Lints, formats, type-checks
294
- bun run test # Runs test suite
295
+ bun run devcheck # Lint, format, typecheck, security audit
296
+ bun run test # Runs test suite
295
297
  ```
296
298
 
297
299
  ## Project Structure
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: "Initial release: 9 tools, 3 resources, 2 prompts for FEC campaign finance data. STDIO and Streamable HTTP."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.1.0 — 2026-04-04
8
+
9
+ ## Added
10
+
11
+ - 9 tools for querying federal election campaign finance data:
12
+ - `openfec_search_candidates` — find candidates by name, state, office, party, or cycle
13
+ - `openfec_search_committees` — find committees by name, type, or candidate affiliation
14
+ - `openfec_search_contributions` — itemized individual contributions and aggregate breakdowns
15
+ - `openfec_search_disbursements` — itemized committee spending and aggregate breakdowns
16
+ - `openfec_search_expenditures` — independent expenditures supporting or opposing candidates
17
+ - `openfec_search_filings` — FEC filings and reports by form type, committee, or date
18
+ - `openfec_lookup_elections` — election races and candidate financial summaries
19
+ - `openfec_search_legal` — advisory opinions, enforcement cases, and administrative fines
20
+ - `openfec_lookup_calendar` — FEC calendar events, filing deadlines, and election dates
21
+ - 3 resources for direct entity lookup:
22
+ - `openfec://candidate/{candidate_id}` — candidate profile with financial totals
23
+ - `openfec://committee/{committee_id}` — committee profile with financial summary
24
+ - `openfec://election/{cycle}/{office}` — election race summary
25
+ - 2 prompts for guided campaign finance analysis:
26
+ - `openfec_campaign_analysis` — structured candidate financial position analysis
27
+ - `openfec_money_trail` — multi-tool money flow investigation framework
28
+ - OpenFEC API service with retry logic, configurable timeout, and type-safe client.
29
+ - STDIO and Streamable HTTP transport support.
30
+ - Docker deployment with OCI labels.
31
+ - Built on `@cyanheads/mcp-ts-core` framework.
@@ -0,0 +1,35 @@
1
+ ---
2
+ summary: "Election resource split into 3 URI templates with explicit params; API key sanitization; HTTP status enrichment; legal search trimming."
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.0 — 2026-04-04
8
+
9
+ ## Changed
10
+
11
+ - **Breaking:** Split election resource into 3 URI templates with explicit params:
12
+ - `openfec://election/{cycle}/{office}` — presidential/at-large races
13
+ - `openfec://election/{cycle}/{office}/{state}` — senate/state races
14
+ - `openfec://election/{cycle}/{office}/{state}/{district}` — house district races
15
+ - State and district are now explicit params instead of parsed from the URI path.
16
+ - Election summary mode returns a flat aggregate object (`count`, `receipts`, `disbursements`, `independent_expenditures`) instead of a paginated response.
17
+ - All empty-result format messages now include actionable troubleshooting suggestions.
18
+ - Candidate ID regex relaxed to accept alphanumeric suffixes (`[HSP][0-9A-Z]+`).
19
+
20
+ ## Fixed
21
+
22
+ - Calendar tool date parameters now map to correct endpoint-specific field names (`min_start_date`/`max_start_date` for events, `min_due_date`/`max_due_date` for filing deadlines, `min_election_date`/`max_election_date` for election dates).
23
+
24
+ ## Added
25
+
26
+ - API error sanitization: API keys are stripped from error messages before surfacing to clients.
27
+ - HTTP status errors enriched with actionable hints (rate limits, bad params, service unavailable).
28
+ - Legal search response trimming for LLM context windows (highlights capped at 3, documents summarized as count + categories, commission votes condensed).
29
+ - `NotFound` errors for candidate and committee ID-specific lookups that return empty results.
30
+ - Expenditure tool validates candidate/committee ID formats and requires `candidate_id` for `by_candidate` mode.
31
+ - `ElectionSummary` type for the flat `/elections/summary/` endpoint response.
32
+ - Defensive null coalescing on pagination fields in service layer.
33
+ - Security overrides for transitive dependencies (`brace-expansion`, `express-rate-limit`, `hono`, `path-to-regexp`, `picomatch`, `yaml`, `lodash`).
34
+ - Funding info, author email, and `typescript`/`ai-agent` keywords to package.json.
35
+ - Consistent `bun run` prefix for all package scripts; start scripts use `bun` runtime.
@@ -0,0 +1,21 @@
1
+ ---
2
+ summary: "Tool export renames; FecParams multi-value support; calendar category param; disbursements committee_id required; shared format-helpers and id-validators."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.1 — 2026-04-04
8
+
9
+ ## Changed
10
+
11
+ - Renamed tool exports for consistency: `lookupCalendarTool` → `lookupCalendar`, `lookupElectionsTool` → `lookupElections`, `searchLegalTool` → `searchLegal`.
12
+ - `FecParams` type now supports `string[]` values for repeated query parameters (e.g., multiple `candidate_id` values).
13
+ - `search-candidates` tool sends multi-candidate totals lookups as repeated query params instead of comma-separated strings.
14
+ - Calendar tool `report_type` parameter scoped to filing deadlines mode only; added dedicated `category` parameter for calendar category filtering in events mode.
15
+ - Disbursements tool `committee_id` enforced as required via `.min(1)` schema constraint instead of runtime guard.
16
+
17
+ ## Added
18
+
19
+ - Shared `utils/format-helpers.ts` — extracted `fmt$`, `str`, and `PaginationSchema` from duplicated inline definitions across tools.
20
+ - Shared `utils/id-validators.ts` — extracted `validateCandidateId` and `validateCommitteeId` with consistent error messages.
21
+ - Contributions tool now validates `candidate_id` and `committee_id` format before API calls.
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: "Legal search respondent param fix (respondent → case_respondents); STDIO & HTTP transport mention in description."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.2 — 2026-04-04
8
+
9
+ ## Fixed
10
+
11
+ - Legal search `respondent` parameter now maps to the correct API field (`case_respondents` instead of `respondent`).
12
+
13
+ ## Changed
14
+
15
+ - Server description updated to mention STDIO & Streamable HTTP transport support (server.json, Dockerfile OCI label).
16
+ - Removed stale `ctx.elicit`/`ctx.sample` guidance from CLAUDE.md.
@@ -0,0 +1,13 @@
1
+ ---
2
+ summary: "Public hosted instance at openfec.caseyjhand.com/mcp; server.json remotes field."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.3 — 2026-04-04
8
+
9
+ ## Added
10
+
11
+ - Public hosted instance at `https://openfec.caseyjhand.com/mcp` — no API key or installation required.
12
+ - `remotes` field in `server.json` advertising the Streamable HTTP endpoint for MCP client discovery.
13
+ - "Public Hosted Instance" section in README Getting Started with connection config example.
@@ -0,0 +1,28 @@
1
+ ---
2
+ summary: "Format output overhaul (renderRecord helper); election ZIP support; calendar/disbursement sort defaults; error sanitization fix."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.3.0 — 2026-04-04
8
+
9
+ ## Changed
10
+
11
+ - **Format output overhaul:** All tool `format()` functions now use a shared `renderRecord()` helper instead of bespoke field-by-field rendering — text output shows raw field names (`total_receipts:`) instead of human-readable labels (`Receipts:`).
12
+ - Prompt descriptions switched from `+` string concatenation to template literals.
13
+ - Contribution aggregates now default to `sort: '-total', sort_hide_null: true` for more useful ordering.
14
+ - Disbursement aggregates likewise default to descending-total sort.
15
+ - Legal search `type` description warns that `admin_fines` is slow without a query or respondent filter.
16
+ - Elections tool relaxes state/district requirements when a ZIP code is provided; summary mode rejects ZIP lookups with an explicit error.
17
+ - `enrichStatusError()` now sanitizes the error message before pattern-matching HTTP status codes (avoids double-sanitization).
18
+
19
+ ## Added
20
+
21
+ - `renderRecord()` in `utils/format-helpers.ts` — generic key/value renderer with skip-set for header fields.
22
+ - `searchElectionsByZip()` service method using the `/elections/search/` endpoint which accepts ZIP parameters.
23
+ - Candidate resource handler validates candidate ID format before API call.
24
+ - `FETCH_TIMEOUT` recognized as transient error for retry logic.
25
+
26
+ ## Fixed
27
+
28
+ - `enrichStatusError()` was sanitizing twice in the hint branch; now sanitizes once upfront.
@@ -0,0 +1,16 @@
1
+ ---
2
+ summary: "Search criteria echo on empty results across all 9 tools; shared buildSearchCriteria/formatEmptyResult helpers."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.3.1 — 2026-04-04
8
+
9
+ ## Added
10
+
11
+ - Search criteria echo on empty results — all 9 tools now return the filters that produced zero matches, helping diagnose why a query returned nothing.
12
+ - `buildSearchCriteria()`, `formatEmptyResult()`, and `SearchCriteriaSchema` in `format-helpers.ts` for consistent empty-result rendering across tools.
13
+
14
+ ## Changed
15
+
16
+ - Empty-result format messages unified to "No results found" with echoed criteria and domain-specific suggestions (previously each tool had a bespoke message).
@@ -0,0 +1,14 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.3.8: 15 skills synced, devDep bumps, description string literal cleanup, candidate resource ID validation."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.3.2 — 2026-04-19
8
+
9
+ ## Changed
10
+
11
+ - Upgraded `@cyanheads/mcp-ts-core` from 0.2.12 to 0.3.8 and synced 15 project skills; added new `add-app-tool` skill.
12
+ - Bumped devDependencies to latest: `@biomejs/biome` 2.4.12, `@types/node` 25.6.0, `typescript` 6.0.3, `vitest` 4.1.4.
13
+ - Collapsed `+` string concatenations in all tool and resource descriptions, enum `.describe()` calls, and the itemized-contribution error message to single string literals.
14
+ - `candidate.resource.ts` now uses the shared `validateCandidateId()` helper instead of an inline regex check, so invalid candidate IDs surface as `invalidParams` (MCP error `-32602`) instead of a generic `Error`, matching the tool-side behavior.
@@ -0,0 +1,18 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.5.3: format-parity pass, looseObject output schemas, parseEnvConfig migration, security overrides."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.0 — 2026-04-20
8
+
9
+ ## Changed
10
+
11
+ - Upgraded `@cyanheads/mcp-ts-core` from 0.3.8 to 0.5.3 and synced 7 project skills (`add-tool` 1.6, `api-config` 1.2, `design-mcp-server` 2.4, `field-test` 1.2, `maintenance` 1.3, `polish-docs-meta` 1.4, `setup` 1.3).
12
+ - **Tool output now passes the new `format-parity` lint rule** — all 9 tools render every scalar field from their output schema, so clients forwarding `content[]` (Claude Desktop) see the same information as clients forwarding `structuredContent` (Claude Code). User-visible effects:
13
+ - Itemized modes (contributions, disbursements, expenditures) expose the real `next_cursor` value in the footer instead of a generic "more available" notice.
14
+ - Pagination footers consistently show `Page X of Y · N total · P per page` — `per_page` was previously hidden.
15
+ - Count headers render raw digits (`10468532 total contributions`) instead of locale-formatted (`10,468,532`) so sentinel matching in the linter stays reliable.
16
+ - Relaxed `results[]`/`candidates[]`/`committees[]`/etc. output item schemas from `z.record(z.string(), z.unknown())` to `z.looseObject({})` — the framework's documented escape hatch for genuinely dynamic upstream payloads like the FEC API. Structured data flow unchanged; linter no longer emits false `<key>` parity failures.
17
+ - Migrated `src/config/server-config.ts` to `parseEnvConfig()` from `@cyanheads/mcp-ts-core/config`. Missing `FEC_API_KEY` now produces the framework's formatted banner instead of a raw ZodError dump.
18
+ - Tightened security overrides in `package.json`: `hono >=4.12.14`, `@hono/node-server >=1.19.13`, `vite >=8.0.5`. `bun audit` now clean (was reporting 10 advisories from transitive deps).
@@ -0,0 +1,20 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.7.0: landing page, SEP-1649 server card, MCP_PUBLIC_URL, new skills (security-pass, release-and-publish, api-linter); describe-on-fields fixes."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.1 — 2026-04-24
8
+
9
+ ## Changed
10
+
11
+ - Upgraded `@cyanheads/mcp-ts-core` from 0.5.3 to 0.7.0 (skipping the 0.6.x series). Notable consumer-facing upgrades:
12
+ - **`/` landing page + `/.well-known/mcp.json` SEP-1649 Server Card** appear in HTTP mode with zero config
13
+ - **`MCP_PUBLIC_URL`** env var now available for TLS-terminating reverse-proxy deployments
14
+ - **`security-pass`**, **`release-and-publish`**, and **`api-linter`** skills added; `field-test` rewritten to drive a live HTTP server over JSON-RPC
15
+ - **ZodError** now surfaces a flat `<message> at <path> (+N more)` string plus structured `data.issues`, so validation failures read as prose in logs and tool error payloads
16
+ - Fixed 10 new `describe-on-fields` lint warnings surfaced by framework 0.6.16's recursive walk into array element types — every `z.looseObject({})` inside `z.array(...)` output now carries its own `.describe()` across all 9 tool definitions.
17
+ - Patch bumps: `@biomejs/biome` 2.4.12 → 2.4.13, `vitest` 4.1.4 → 4.1.5.
18
+ - Synced 15 project skills to their new package versions; added 3 new skills (`api-linter` 1.1, `release-and-publish` 2.1, `security-pass` 1.1).
19
+ - Synced framework scripts via the new `maintenance` skill Phase C: added `build-changelog.ts`, `check-docs-sync.ts`, `check-skills-sync.ts`; refreshed `devcheck.ts` and `tree.ts`.
20
+ - `CLAUDE.md` refreshed against the upstream consumer template.
@@ -0,0 +1,19 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.8.19: typed error contracts, error-code semantics fix (invalidParams→validationError), engines bump, skill and script syncs."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.2 — 2026-05-08
8
+
9
+ ## Changed
10
+
11
+ - Upgraded `@cyanheads/mcp-ts-core` from `^0.7.0` to `^0.8.19` (entire 0.8.x series). Notable consumer-facing additions adopted in this release:
12
+ - **Typed error contracts** — every tool and resource that surfaces a domain-specific failure now declares `errors: [{ reason, code, when, recovery }]` and routes throws through `ctx.fail(reason, msg?, data?)`. Reasons are TypeScript-checked at the throw site; declared `recovery` strings flow to the wire via `ctx.recoveryFor(reason)`.
13
+ - **`candidate.resource` and `committee.resource`** now declare contracts; `committee.resource` newly validates committee_id format up front via the shared `validateCommitteeId` helper instead of letting the API return an empty result.
14
+ - **Error-code semantics** — replaced `invalidParams` with `validationError` for all semantic post-shape checks (ID format, missing required filters, mode-specific guards). `invalidParams` is reserved for malformed JSON-RPC params; `validationError` is the correct code for "input parsed cleanly but is semantically wrong." Tests updated accordingly (`InvalidParams` → `ValidationError`).
15
+ - Engines bumped: `bun` `>=1.2.0 → >=1.3.0`, `node` `>=22.0.0 → >=24.0.0`. README Bun badge bumped in lockstep.
16
+ - DevDeps: `@biomejs/biome` `^2.4.13 → ^2.4.14`, `@types/node` `^25.6.0 → ^25.6.2`, `tsc-alias` `^1.8.16 → ^1.8.17`.
17
+ - Synced project skills against framework 0.8.19; added 3 new skills (`api-canvas`, `api-telemetry`, `tool-defs-analysis`) and refreshed 14 existing ones to their package versions.
18
+ - Synced framework scripts via `maintenance` Phase C: added `check-framework-antipatterns.ts` (now wired into `devcheck`) and `split-changelog.ts`; `build-changelog.ts` learned to render a `🛡️ Security` badge alongside `⚠️ Breaking`.
19
+ - `CLAUDE.md` refreshed against the upstream consumer template — typed-error-contract pattern documented inline, `ctx.recoveryFor` reference added, dev/start scripts updated.
@@ -0,0 +1,25 @@
1
+ ---
2
+ summary: "Office codes H|S|P standardized; calendar category enum; pagination tightened; candidate/committee resources enriched; prompt refinements."
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.3 — 2026-05-08
8
+
9
+ ## Changed
10
+
11
+ - **Office codes standardized to `H|S|P` across `openfec_lookup_elections` and the `openfec://election/{cycle}/{office}[/...]` resources** — input now matches the codes `openfec_search_candidates` already used. Internal mapping to the FEC API's `house|senate|president` form is preserved. URI examples in the election resource descriptions updated to `H/S/P`. README quick-reference updated. ⚠️ Breaking for any client wired to the old `president|senate|house` enum on those two surfaces.
12
+ - **Calendar `category` is now an enum**, not a free string. All 18 FEC calendar category codes (20–29, 32–34, 36–40) are enumerated with a label legend in the field describe (e.g. `21=Reporting Deadlines`, `36=Election Dates`).
13
+ - **Pagination inputs tightened across 7 tools** — `page` and `per_page` are now `z.number().int().min(1)[.max(100)].default(...)` instead of bare `optional()` with prose-only bounds. The framework's JSON schema now exposes the limits to clients.
14
+ - **`openfec_search_filings` output renamed `filings` → `results`** for consistency with every other search tool. Format renderer and tests updated. ⚠️ Breaking for clients reading `structuredContent.filings` directly.
15
+ - **`search-filings` validates `committee_id` and `candidate_id` format up front** via the shared `validateCommitteeId` / `validateCandidateId` helpers (matches the pattern already in `search-candidates` and `committee.resource`).
16
+ - **`candidate.resource` now returns `principal_committees`** alongside the candidate record and totals, fetched via the new `getCandidateCommittees()` service helper. All three upstream calls run in parallel via `Promise.all`.
17
+ - **`committee.resource` now merges committee totals** into the response. The totals fetch is wrapped to no-op on 404 so committees that don't file Form 3/3X/3P (which return 404 from `/committee/{id}/totals/`) still resolve cleanly through the base `committee_not_found` contract instead of bubbling the totals 404.
18
+ - **Both prompts (`openfec_money_trail`, `openfec_campaign_analysis`) now `.refine()` their args** to require either `candidate_id` or `candidate_name`. Empty invocations now fail at validation with an actionable message instead of generating a prompt referencing "the specified candidate".
19
+ - **Tightened tool/resource descriptions across the surface** — output `results[]` items now spell out which mode produces which row shape; empty-result hints in `search-disbursements` and `search-filings` now nudge users toward `openfec_search_committees` for committee-by-name lookup; reused `PaginationSchema` everywhere instead of re-inlining the four pagination fields per tool.
20
+ - **`campaign-analysis` prompt restructured** — split principal-committee discovery into its own step (Step 2) before the contribution and disbursement breakdowns; downstream steps renumbered.
21
+
22
+ ## Added
23
+
24
+ - `OpenFecService.getCandidateCommittees(candidateId, params, ctx)` — `/candidate/{id}/committees/` endpoint.
25
+ - `OpenFecService.getCommitteeTotals(committeeId, params, ctx)` — `/committee/{id}/totals/` endpoint.
@@ -0,0 +1,24 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.9.1: server instructions, schema portability lint, mcp_tool_scopes claim; skill and script syncs."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.4 — 2026-05-16
8
+
9
+ ## Changed
10
+
11
+ - Upgraded `@cyanheads/mcp-ts-core` `^0.8.19 → ^0.9.1`. Notable consumer-facing additions adopted in this release:
12
+ - **`instructions` field on `createApp()`** (framework [#91](https://github.com/cyanheads/mcp-ts-core/issues/91)) — server-level usage hints surfaced to MCP clients via the `tools/list` capabilities envelope. This server now ships a one-paragraph orientation covering tool prefix, ID conventions (H/S/P for candidates, C for committees), and cycle semantics.
13
+ - **Cross-vendor schema portability lint family** (framework [#132](https://github.com/cyanheads/mcp-ts-core/issues/132)) — new `schema-format-portability`, `schema-anyof-needs-type`, `schema-no-discriminator-keyword` (default-on) plus `schema-no-defs`, `schema-dialect-tag` (opt-in via `MCP_LINT_PORTABILITY=strict`). Catches schemas that pass `schema-serializable` but break at OpenAI's tool validator or Gemini's API. Surface passes default rules.
14
+ - **`mcp_tool_scopes` claim union + `MCP_AUTH_DISABLE_SCOPE_CHECKS` bypass** (framework [#128](https://github.com/cyanheads/mcp-ts-core/issues/128)) — `ctx.auth.scopes` now unions `scp`, `scope`, and `mcp_tool_scopes`, letting OIDC providers that can't inject scopes into `scope` (Authentik, Keycloak < 26.5, Zitadel) supply per-tool scopes via a custom claim. The bypass flag exists for managed services where no custom claim is configurable.
15
+ - **`Context.notifyPromptListChanged` / `notifyToolListChanged`** (framework 0.9.1) — handlers can now signal client-side reload for dynamically-disabled tools.
16
+ - **`devcheck` outdated-deps parser** now reads markdown-style `bun outdated` output correctly. Previous logic split on `|` and took index `[0]` — but markdown rows start with a leading `|`, so index `[0]` was an empty string and every package was treated as the "Package" header (silent allowlist bypass). Fixed to take index `[1]` and strip `(dev|peer|prod|optional)` workspace markers before allowlist comparison.
17
+ - **`scripts/build-changelog.ts` summary cap raised** `250 → 350` chars, matching the framework's relaxed limit.
18
+ - DevDep patches: `@biomejs/biome ^2.4.14 → ^2.4.15`, `@types/node ^25.6.2 → ^25.8.0`, `vitest ^4.1.5 → ^4.1.6`.
19
+
20
+ ## Docs
21
+
22
+ - Synced project skills against framework 0.9.x — `api-linter` documents the five new portability rules; `api-auth` documents the `mcp_tool_scopes` claim and OIDC operator setup; `add-tool` documents mutator response design (return raw pre/post observable state, not synthetic verdicts) plus the new "unit-bearing numeric field names" checklist item; `tool-defs-analysis` adds the matching audit category.
23
+ - `CLAUDE.md` checklist: added portability guidance (avoid non-portable `format` emitters — use `z.string()` with the constraint in `.describe()`), Zod literal-union exemption note for `describe-on-fields`, and three OpenFEC-specific items for sparse upstream payloads.
24
+ - `README.md`: removed stale `dev:stdio`/`dev:http` watch-mode references (the framework dropped these scripts in `^0.8.6`); aligned Bun prereq with the `engines` constraint (≥1.3.0); OTEL env-var row now links to the framework telemetry docs.
@@ -0,0 +1,22 @@
1
+ ---
2
+ summary: "mcp-ts-core ^0.9.1 → ^0.9.6, zod added, manifest.json + .mcpbignore scaffolded, changelog migrated to per-version format, install badges"
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.5 — 2026-05-23
8
+
9
+ ## Added
10
+
11
+ - **`manifest.json`** — MCPB bundle manifest for one-click Claude Desktop install via `bun run bundle`. Declares `user_config` entries for `FEC_API_KEY` and `MCP_LOG_LEVEL`.
12
+ - **`.mcpbignore`** — excludes source, test, and dev artefacts from the `.mcpb` bundle.
13
+ - **Install in Claude Desktop** badge on `README.md` linking to the latest `.mcpb` release asset.
14
+ - **`scripts/lint-packaging.ts`** — validates `server.json` and `manifest.json` env-var alignment; wired into `devcheck`.
15
+ - **`scripts/list-skills.ts`** — prints the skill index; powers `bun run list-skills`.
16
+
17
+ ## Changed
18
+
19
+ - Upgraded `@cyanheads/mcp-ts-core` `^0.9.1 → ^0.9.6`.
20
+ - Added `zod ^4.4.3` as a direct dependency (previously an implicit transitive).
21
+ - Changelog migrated from a single flat `CHANGELOG.md` to per-version files under `changelog/<major.minor>.x/`; `CHANGELOG.md` is now a rollup index generated by `bun run changelog:build`.
22
+ - DevDep patches: `@biomejs/biome ^2.4.14 → ^2.4.15`, `@types/node ^25.8.0 → ^25.9.1`, `vitest ^4.1.6 → ^4.1.7`.
@@ -0,0 +1,93 @@
1
+ ---
2
+ # FORMAT REFERENCE — do not edit. Copy this file to
3
+ # `changelog/<major.minor>.x/<version>.md` (e.g. `changelog/0.8.x/0.8.6.md`)
4
+ # to author a new release. Set that file's H1 to `# <version> — YYYY-MM-DD`
5
+ # with a concrete date.
6
+
7
+ # Required. One-line GitHub Release-style headline. 350 character cap.
8
+ # Default short and scannable. Don't pad, don't stitch unrelated changes with
9
+ # semicolons — pick the headline. Quotes required: unquoted YAML treats `: `
10
+ # inside the value as a key separator and fails GitHub's strict parser.
11
+ summary: ""
12
+
13
+ # Set `true` when consumers must change code to upgrade: API removals,
14
+ # signature changes, config renames, behavior changes that break existing
15
+ # usage. Flagged as `Breaking` in the rollup.
16
+ breaking: false
17
+
18
+ # Set `true` if this release contains any security fix. Pairs with the
19
+ # `## Security` section below. Flagged as `Security` in the rollup so
20
+ # users can triage upgrade urgency at a glance.
21
+ security: false
22
+ ---
23
+
24
+ # <version> — YYYY-MM-DD
25
+
26
+ <!--
27
+ AUTHORING GUIDE — applies to the new per-version file you create from this
28
+ template.
29
+
30
+ Audience: someone scanning release notes to decide what affects them. Lead
31
+ each bullet with the symbol or concept name in **bold** so they can skip
32
+ what's irrelevant and zoom in on what's not.
33
+
34
+ Tone: terse, fact-dense, not verbose. Default to one sentence per bullet —
35
+ name the symbol, state what changed, stop. Use a second sentence only when
36
+ it carries weight. If a bullet feels long, it is.
37
+
38
+ Cut: mechanism walkthroughs (those belong in JSDoc, AGENTS.md, or the
39
+ relevant skill), ceremonial framings ("This release introduces…",
40
+ backwards-compat paragraphs), file-by-file test enumerations, internal
41
+ implementation notes. Prefer code/symbol names over English re-explanations.
42
+
43
+ Narrative intro: skip by default. Add one short sentence only when the
44
+ release theme genuinely needs framing the bullets can't carry.
45
+
46
+ Sections: Keep a Changelog order — Added, Changed, Deprecated, Removed,
47
+ Fixed, Security. Include only sections with entries; delete the rest
48
+ (including the commented-out scaffolding below). Don't ship empty headers.
49
+
50
+ Include: every distinct fact a reader needs to adopt or audit the release —
51
+ new exports, signatures, lint rule IDs, env vars, breaking changes, version
52
+ bumps on shipped skills. Nothing more.
53
+
54
+ Links: link issues, PRs, docs, or skills where they help a reader jump to
55
+ context. Once per item per entry — don't re-link the same issue in summary,
56
+ narrative, and bullet. Skip links for inline symbol names; code spans speak
57
+ for themselves.
58
+
59
+ Issue/PR URLs: use full URLs. GitHub's bare `#NN` auto-link only resolves
60
+ inside its own UI, not in npm reads or local editors.
61
+
62
+ [#38](https://github.com/cyanheads/mcp-ts-core/issues/38) ← issue
63
+ [#42](https://github.com/cyanheads/mcp-ts-core/pull/42) ← PR
64
+
65
+ Verify numbers exist before linking (`gh issue view NN`, `gh pr view NN`).
66
+ Never speculate on a future number — `#42` for an upcoming PR silently
67
+ resolves to whatever real item already owns 42, and timeline previews pull
68
+ in that unrelated item's metadata.
69
+ -->
70
+
71
+ ## Added
72
+
73
+ -
74
+
75
+ ## Changed
76
+
77
+ -
78
+
79
+ <!-- ## Deprecated
80
+
81
+ - -->
82
+
83
+ <!-- ## Removed
84
+
85
+ - -->
86
+
87
+ ## Fixed
88
+
89
+ -
90
+
91
+ <!-- ## Security
92
+
93
+ - -->
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { z } from '@cyanheads/mcp-ts-core';
7
7
  declare const ServerConfigSchema: z.ZodObject<{
8
- fecApiKey: z.ZodString;
8
+ fecApiKey: z.ZodDefault<z.ZodString>;
9
9
  fecBaseUrl: z.ZodDefault<z.ZodString>;
10
10
  fecMaxRetries: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
11
11
  fecRequestTimeout: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;;iBAYtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,oEAAoE;AACpE,wBAAgB,eAAe,IAAI,YAAY,CAQ9C"}
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,QAAA,MAAM,kBAAkB;;;;;iBAetB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,oEAAoE;AACpE,wBAAgB,eAAe,IAAI,YAAY,CAQ9C"}
@@ -8,7 +8,8 @@ import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
8
8
  const ServerConfigSchema = z.object({
9
9
  fecApiKey: z
10
10
  .string()
11
- .min(1, 'FEC_API_KEY is required. Get a free key at https://api.data.gov/signup/'),
11
+ .default('DEMO_KEY')
12
+ .describe('OpenFEC API key from api.data.gov — optional (DEMO_KEY: 30 req/hr, own key: 1000 req/hr)'),
12
13
  fecBaseUrl: z.string().default('https://api.open.fec.gov/v1').describe('OpenFEC API base URL'),
13
14
  fecMaxRetries: z.coerce.number().int().min(0).default(3).describe('Max retry attempts'),
14
15
  fecRequestTimeout: z.coerce
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,yEAAyE,CAAC;IACpF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAC9F,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IACvF,iBAAiB,EAAE,CAAC,CAAC,MAAM;SACxB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,IAAI,CAAC;SACT,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,uBAAuB,CAAC;CACrC,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC,oEAAoE;AACpE,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,SAAS,EAAE,aAAa;QACxB,UAAU,EAAE,cAAc;QAC1B,aAAa,EAAE,iBAAiB;QAChC,iBAAiB,EAAE,qBAAqB;KACzC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CACP,0FAA0F,CAC3F;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAC9F,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IACvF,iBAAiB,EAAE,CAAC,CAAC,MAAM;SACxB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,IAAI,CAAC;SACT,OAAO,CAAC,MAAM,CAAC;SACf,QAAQ,CAAC,uBAAuB,CAAC;CACrC,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC,oEAAoE;AACpE,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,SAAS,EAAE,aAAa;QACxB,UAAU,EAAE,cAAc;QAC1B,aAAa,EAAE,iBAAiB;QAChC,iBAAiB,EAAE,qBAAqB;KACzC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ await createApp({
13
13
  tools: allToolDefinitions,
14
14
  resources: allResourceDefinitions,
15
15
  prompts: allPromptDefinitions,
16
+ instructions: 'Use the openfec_* tools for US federal campaign finance data: candidates, committees, contributions (Schedule A), disbursements (Schedule B), independent expenditures (Schedule E), filings, elections, calendar, and legal documents. Candidate IDs use H/S/P prefixes (House/Senate/President); committee IDs use C. Cycles are even-year integers covering the prior 2 years (2024 = Jan 2023 – Dec 2024). Itemized contributions and disbursements scope to committee_id, not candidate_id.',
16
17
  setup() {
17
18
  initOpenFecService();
18
19
  },
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,SAAS,CAAC;IACd,KAAK,EAAE,kBAAkB;IACzB,SAAS,EAAE,sBAAsB;IACjC,OAAO,EAAE,oBAAoB;IAC7B,KAAK;QACH,kBAAkB,EAAE,CAAC;IACvB,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,SAAS,CAAC;IACd,KAAK,EAAE,kBAAkB;IACzB,SAAS,EAAE,sBAAsB;IACjC,OAAO,EAAE,oBAAoB;IAC7B,YAAY,EACV,keAAke;IACpe,KAAK;QACH,kBAAkB,EAAE,CAAC;IACvB,CAAC;CACF,CAAC,CAAC"}
package/manifest.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "manifest_version": "0.3",
3
+ "name": "openfec-mcp-server",
4
+ "version": "0.4.5",
5
+ "description": "Access FEC campaign finance data. Query data about candidates, money trails, and election filings.",
6
+ "author": { "name": "cyanheads" },
7
+ "server": {
8
+ "type": "node",
9
+ "entry_point": "dist/index.js",
10
+ "mcp_config": {
11
+ "command": "node",
12
+ "args": ["${__dirname}/dist/index.js"],
13
+ "env": {
14
+ "MCP_TRANSPORT_TYPE": "stdio",
15
+ "MCP_AUTH_MODE": "none",
16
+ "NODE_ENV": "production"
17
+ }
18
+ }
19
+ },
20
+ "compatibility": {
21
+ "runtimes": { "node": ">=24.0.0" }
22
+ },
23
+ "tools_generated": true,
24
+ "prompts_generated": true,
25
+ "user_config": {
26
+ "FEC_API_KEY": {
27
+ "title": "OpenFEC API Key",
28
+ "description": "Optional. Falls back to DEMO_KEY (30 req/hr). Own key: 1000 req/hr. Free signup at api.data.gov.",
29
+ "type": "string",
30
+ "required": false
31
+ },
32
+ "MCP_LOG_LEVEL": {
33
+ "title": "Log Level",
34
+ "description": "Minimum log level for output (debug, info, warn).",
35
+ "type": "string",
36
+ "required": false,
37
+ "default": "info"
38
+ }
39
+ }
40
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/openfec-mcp-server",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "mcpName": "io.github.cyanheads/openfec-mcp-server",
5
5
  "description": "Access FEC campaign finance data through MCP. Query data about candidates, money trails, and election filings. STDIO & Streamable HTTP.",
6
6
  "type": "module",
@@ -9,7 +9,16 @@
9
9
  "bin": {
10
10
  "openfec-mcp-server": "dist/index.js"
11
11
  },
12
- "files": ["dist/", "README.md", "LICENSE", "CLAUDE.md", "Dockerfile", "server.json"],
12
+ "files": [
13
+ "dist/",
14
+ "README.md",
15
+ "LICENSE",
16
+ "CLAUDE.md",
17
+ "Dockerfile",
18
+ "server.json",
19
+ "manifest.json",
20
+ "changelog/"
21
+ ],
13
22
  "scripts": {
14
23
  "build": "bun run scripts/build.ts",
15
24
  "rebuild": "bun run scripts/clean.ts && bun run build",
@@ -18,6 +27,12 @@
18
27
  "tree": "bun run scripts/tree.ts",
19
28
  "format": "biome check --write --unsafe",
20
29
  "lint:mcp": "bun run scripts/lint-mcp.ts",
30
+ "lint:packaging": "bun run scripts/lint-packaging.ts",
31
+ "list-skills": "bun run scripts/list-skills.ts",
32
+ "bundle": "bun run build && bunx -y @anthropic-ai/mcpb pack . dist/openfec-mcp-server.mcpb",
33
+ "audit:refresh": "rm -f bun.lock && bun install && bun audit",
34
+ "changelog:build": "bun run scripts/build-changelog.ts",
35
+ "changelog:check": "bun run scripts/build-changelog.ts --check",
21
36
  "test": "bunx vitest run",
22
37
  "start": "node dist/index.js",
23
38
  "start:stdio": "MCP_TRANSPORT_TYPE=stdio bun ./dist/index.js",
@@ -77,17 +92,18 @@
77
92
  "lodash": ">=4.17.24"
78
93
  },
79
94
  "dependencies": {
80
- "@cyanheads/mcp-ts-core": "^0.8.19",
95
+ "@cyanheads/mcp-ts-core": "^0.9.6",
81
96
  "@opentelemetry/api": "^1.9.1",
82
- "pino-pretty": "^13.1.3"
97
+ "pino-pretty": "^13.1.3",
98
+ "zod": "^4.4.3"
83
99
  },
84
100
  "devDependencies": {
85
- "@biomejs/biome": "^2.4.14",
86
- "@types/node": "^25.6.2",
101
+ "@biomejs/biome": "^2.4.15",
102
+ "@types/node": "^25.9.1",
87
103
  "depcheck": "^1.4.7",
88
104
  "ignore": "^7.0.5",
89
105
  "tsc-alias": "^1.8.17",
90
106
  "typescript": "^6.0.3",
91
- "vitest": "^4.1.5"
107
+ "vitest": "^4.1.7"
92
108
  }
93
109
  }
package/server.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/cyanheads/openfec-mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.4.3",
9
+ "version": "0.4.5",
10
10
  "remotes": [
11
11
  {
12
12
  "type": "streamable-http",
@@ -19,17 +19,23 @@
19
19
  "registryBaseUrl": "https://registry.npmjs.org",
20
20
  "identifier": "@cyanheads/openfec-mcp-server",
21
21
  "runtimeHint": "bun",
22
- "version": "0.4.3",
22
+ "version": "0.4.5",
23
23
  "packageArguments": [
24
- { "type": "positional", "value": "run" },
25
- { "type": "positional", "value": "start:stdio" }
24
+ {
25
+ "type": "positional",
26
+ "value": "run"
27
+ },
28
+ {
29
+ "type": "positional",
30
+ "value": "start:stdio"
31
+ }
26
32
  ],
27
33
  "environmentVariables": [
28
34
  {
29
35
  "name": "FEC_API_KEY",
30
- "description": "OpenFEC API key. Get a free key at https://api.data.gov/signup/",
36
+ "description": "OpenFEC API key \u2014 optional (falls back to DEMO_KEY: 30 req/hr). Own key: 1000 req/hr. Free signup at api.data.gov.",
31
37
  "format": "string",
32
- "isRequired": true
38
+ "isRequired": false
33
39
  },
34
40
  {
35
41
  "name": "MCP_LOG_LEVEL",
@@ -39,24 +45,32 @@
39
45
  "default": "info"
40
46
  }
41
47
  ],
42
- "transport": { "type": "stdio" }
48
+ "transport": {
49
+ "type": "stdio"
50
+ }
43
51
  },
44
52
  {
45
53
  "registryType": "npm",
46
54
  "registryBaseUrl": "https://registry.npmjs.org",
47
55
  "identifier": "@cyanheads/openfec-mcp-server",
48
56
  "runtimeHint": "bun",
49
- "version": "0.4.3",
57
+ "version": "0.4.5",
50
58
  "packageArguments": [
51
- { "type": "positional", "value": "run" },
52
- { "type": "positional", "value": "start:http" }
59
+ {
60
+ "type": "positional",
61
+ "value": "run"
62
+ },
63
+ {
64
+ "type": "positional",
65
+ "value": "start:http"
66
+ }
53
67
  ],
54
68
  "environmentVariables": [
55
69
  {
56
70
  "name": "FEC_API_KEY",
57
- "description": "OpenFEC API key. Get a free key at https://api.data.gov/signup/",
71
+ "description": "OpenFEC API key \u2014 optional (falls back to DEMO_KEY: 30 req/hr). Own key: 1000 req/hr. Free signup at api.data.gov.",
58
72
  "format": "string",
59
- "isRequired": true
73
+ "isRequired": false
60
74
  },
61
75
  {
62
76
  "name": "MCP_HTTP_HOST",