@cyanheads/congressgov-mcp-server 0.3.32 → 0.4.0

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 (44) hide show
  1. package/AGENTS.md +24 -3
  2. package/CLAUDE.md +24 -3
  3. package/Dockerfile +13 -0
  4. package/README.md +15 -4
  5. package/dist/config/server-config.d.ts +15 -0
  6. package/dist/config/server-config.d.ts.map +1 -1
  7. package/dist/config/server-config.js +65 -0
  8. package/dist/config/server-config.js.map +1 -1
  9. package/dist/index.js +30 -2
  10. package/dist/index.js.map +1 -1
  11. package/dist/mcp-server/tools/definitions/search-bills.tool.d.ts +47 -0
  12. package/dist/mcp-server/tools/definitions/search-bills.tool.d.ts.map +1 -0
  13. package/dist/mcp-server/tools/definitions/search-bills.tool.js +99 -0
  14. package/dist/mcp-server/tools/definitions/search-bills.tool.js.map +1 -0
  15. package/dist/mcp-server/tools/format-helpers.d.ts +2 -0
  16. package/dist/mcp-server/tools/format-helpers.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/format-helpers.js +31 -0
  18. package/dist/mcp-server/tools/format-helpers.js.map +1 -1
  19. package/dist/services/congress-mirror/congress-mirror-service.d.ts +45 -0
  20. package/dist/services/congress-mirror/congress-mirror-service.d.ts.map +1 -0
  21. package/dist/services/congress-mirror/congress-mirror-service.js +116 -0
  22. package/dist/services/congress-mirror/congress-mirror-service.js.map +1 -0
  23. package/dist/services/congress-mirror/ingest.d.ts +33 -0
  24. package/dist/services/congress-mirror/ingest.d.ts.map +1 -0
  25. package/dist/services/congress-mirror/ingest.js +179 -0
  26. package/dist/services/congress-mirror/ingest.js.map +1 -0
  27. package/dist/services/congress-mirror/normalize.d.ts +25 -0
  28. package/dist/services/congress-mirror/normalize.d.ts.map +1 -0
  29. package/dist/services/congress-mirror/normalize.js +47 -0
  30. package/dist/services/congress-mirror/normalize.js.map +1 -0
  31. package/dist/services/congress-mirror/schema.d.ts +19 -0
  32. package/dist/services/congress-mirror/schema.d.ts.map +1 -0
  33. package/dist/services/congress-mirror/schema.js +44 -0
  34. package/dist/services/congress-mirror/schema.js.map +1 -0
  35. package/dist/services/congress-mirror/types.d.ts +55 -0
  36. package/dist/services/congress-mirror/types.d.ts.map +1 -0
  37. package/dist/services/congress-mirror/types.js +9 -0
  38. package/dist/services/congress-mirror/types.js.map +1 -0
  39. package/package.json +30 -4
  40. package/scripts/_mirror-context.ts +30 -0
  41. package/scripts/congress-mirror-init.ts +23 -0
  42. package/scripts/congress-mirror-refresh.ts +24 -0
  43. package/scripts/congress-mirror-verify.ts +36 -0
  44. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** congressgov-mcp-server
4
- **Version:** 0.3.32
4
+ **Version:** 0.4.0
5
5
  **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.10`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
@@ -42,6 +42,10 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
42
42
  |:--------|:---------|:------------|
43
43
  | `CONGRESS_API_KEY` | No | Optional. Defaults to `DEMO_KEY` (30 req/hr). Own key from [api.data.gov](https://api.data.gov/signup/): 5,000 req/hr. |
44
44
  | `CONGRESS_API_BASE_URL` | No | Defaults to `https://api.congress.gov/v3` |
45
+ | `CONGRESS_MIRROR_ENABLED` | No | Enable the local bill search mirror and `congressgov_search_bills`. Defaults to `false`. |
46
+ | `CONGRESS_MIRROR_PATH` | No | Filesystem path to the SQLite mirror index. Defaults to `.mirror/bills.sqlite3`. |
47
+ | `CONGRESS_MIRROR_REFRESH_CRON` | No | Cron schedule for the in-process mirror refresh (HTTP transport only). Unset runs `mirror:refresh` manually. |
48
+ | `CONGRESS_MIRROR_CONGRESSES` | No | Comma-separated congress numbers to mirror (e.g. `118,119`). Defaults to the current congress plus the prior one. |
45
49
 
46
50
  ---
47
51
 
@@ -60,7 +64,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
60
64
 
61
65
  ## MCP Surface
62
66
 
63
- ### Tools (10)
67
+ ### Tools (11)
64
68
 
65
69
  | Name | Description |
66
70
  |:-----|:------------|
@@ -74,6 +78,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
74
78
  | `congressgov_crs_reports` | Browse and retrieve nonpartisan CRS policy analysis reports |
75
79
  | `congressgov_committee_reports` | Browse and retrieve committee reports accompanying legislation |
76
80
  | `congressgov_daily_record` | Browse daily Congressional Record — floor speeches, debates, proceedings |
81
+ | `congressgov_search_bills` | Keyword-search bill titles/summaries via the opt-in local FTS mirror — off by default |
77
82
 
78
83
  ### Resources (5)
79
84
 
@@ -105,6 +110,12 @@ src/
105
110
  congress-api/
106
111
  congress-api-service.ts # API client — auth, pagination, rate limiting
107
112
  types.ts # API response types
113
+ congress-mirror/
114
+ congress-mirror-service.ts # Mirror read path — FTS5 search, ready(), sync accessor
115
+ ingest.ts # Bill list + CRS summaries sync generator
116
+ normalize.ts # HTML→plain-text, FTS5 MATCH escaping
117
+ schema.ts # SQLite mirror store spec (bills table, FTS index)
118
+ types.ts # Mirror row, search filters, search page types
108
119
  senate-lis/
109
120
  senate-vote-service.ts # Senate LIS XML client — fetch, retry, not-found
110
121
  parse.ts # pure XML → domain parsers (fast-xml-parser)
@@ -121,6 +132,7 @@ src/
121
132
  crs-reports.tool.ts # congressgov_crs_reports
122
133
  committee-reports.tool.ts # congressgov_committee_reports
123
134
  daily-record.tool.ts # congressgov_daily_record
135
+ search-bills.tool.ts # congressgov_search_bills (opt-in — disabledTool() when the mirror is off)
124
136
  resources/definitions/
125
137
  current-congress.resource.ts # congress://current
126
138
  bill-types.resource.ts # congress://bill-types
@@ -130,13 +142,18 @@ src/
130
142
  prompts/definitions/
131
143
  bill-analysis.prompt.ts # congressgov_bill_analysis
132
144
  legislative-research.prompt.ts # congressgov_legislative_research
145
+ scripts/
146
+ _mirror-context.ts # Shared bootstrap for the mirror lifecycle CLI scripts
147
+ congress-mirror-init.ts # mirror:init — full out-of-band mirror build
148
+ congress-mirror-refresh.ts # mirror:refresh — incremental mirror refresh
149
+ congress-mirror-verify.ts # mirror:verify — readiness + integrity check
133
150
  ```
134
151
 
135
152
  ---
136
153
 
137
154
  ## Services
138
155
 
139
- Two services. `CongressApiService` backs nine tools and the House branch of `congressgov_roll_votes`; `SenateVoteService` backs only the Senate branch of `congressgov_roll_votes` (the Congress.gov API exposes no Senate vote namespace).
156
+ Three services. `CongressApiService` backs nine tools and the House branch of `congressgov_roll_votes`; `SenateVoteService` backs only the Senate branch of `congressgov_roll_votes` (the Congress.gov API exposes no Senate vote namespace); `CongressMirrorService` backs `congressgov_search_bills` only.
140
157
 
141
158
  **`CongressApiService`** — wraps the Congress.gov REST API v3:
142
159
  - API key via `X-Api-Key` header (never logged; kept out of the URL so it can't leak in upstream error messages)
@@ -151,6 +168,10 @@ Two services. `CongressApiService` backs nine tools and the House branch of `con
151
168
  - The host returns HTTP 200 with an HTML page for unknown congress/session/vote, so "not found" is detected from the body, not the status code
152
169
  - Party totals are derived from the roster (the feed publishes none)
153
170
 
171
+ **`CongressMirrorService`** — local SQLite FTS5 mirror of bill title + CRS summary text, backing `congressgov_search_bills` only:
172
+ - Opt-in via `CONGRESS_MIRROR_ENABLED` (off by default); built out-of-band via the `mirror:init`/`mirror:refresh` scripts, never on server startup
173
+ - No live-API fallback — ingests through the existing `CongressApiService`, and a mirror that hasn't finished its initial build returns an empty result with a notice, not an error
174
+
154
175
  **Usage in tools:**
155
176
  ```ts
156
177
  import { getCongressApi } from '@/services/congress-api/congress-api-service.js';
package/CLAUDE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** congressgov-mcp-server
4
- **Version:** 0.3.32
4
+ **Version:** 0.4.0
5
5
  **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.10.10`
6
6
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
@@ -42,6 +42,10 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
42
42
  |:--------|:---------|:------------|
43
43
  | `CONGRESS_API_KEY` | No | Optional. Defaults to `DEMO_KEY` (30 req/hr). Own key from [api.data.gov](https://api.data.gov/signup/): 5,000 req/hr. |
44
44
  | `CONGRESS_API_BASE_URL` | No | Defaults to `https://api.congress.gov/v3` |
45
+ | `CONGRESS_MIRROR_ENABLED` | No | Enable the local bill search mirror and `congressgov_search_bills`. Defaults to `false`. |
46
+ | `CONGRESS_MIRROR_PATH` | No | Filesystem path to the SQLite mirror index. Defaults to `.mirror/bills.sqlite3`. |
47
+ | `CONGRESS_MIRROR_REFRESH_CRON` | No | Cron schedule for the in-process mirror refresh (HTTP transport only). Unset runs `mirror:refresh` manually. |
48
+ | `CONGRESS_MIRROR_CONGRESSES` | No | Comma-separated congress numbers to mirror (e.g. `118,119`). Defaults to the current congress plus the prior one. |
45
49
 
46
50
  ---
47
51
 
@@ -60,7 +64,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
60
64
 
61
65
  ## MCP Surface
62
66
 
63
- ### Tools (10)
67
+ ### Tools (11)
64
68
 
65
69
  | Name | Description |
66
70
  |:-----|:------------|
@@ -74,6 +78,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
74
78
  | `congressgov_crs_reports` | Browse and retrieve nonpartisan CRS policy analysis reports |
75
79
  | `congressgov_committee_reports` | Browse and retrieve committee reports accompanying legislation |
76
80
  | `congressgov_daily_record` | Browse daily Congressional Record — floor speeches, debates, proceedings |
81
+ | `congressgov_search_bills` | Keyword-search bill titles/summaries via the opt-in local FTS mirror — off by default |
77
82
 
78
83
  ### Resources (5)
79
84
 
@@ -105,6 +110,12 @@ src/
105
110
  congress-api/
106
111
  congress-api-service.ts # API client — auth, pagination, rate limiting
107
112
  types.ts # API response types
113
+ congress-mirror/
114
+ congress-mirror-service.ts # Mirror read path — FTS5 search, ready(), sync accessor
115
+ ingest.ts # Bill list + CRS summaries sync generator
116
+ normalize.ts # HTML→plain-text, FTS5 MATCH escaping
117
+ schema.ts # SQLite mirror store spec (bills table, FTS index)
118
+ types.ts # Mirror row, search filters, search page types
108
119
  senate-lis/
109
120
  senate-vote-service.ts # Senate LIS XML client — fetch, retry, not-found
110
121
  parse.ts # pure XML → domain parsers (fast-xml-parser)
@@ -121,6 +132,7 @@ src/
121
132
  crs-reports.tool.ts # congressgov_crs_reports
122
133
  committee-reports.tool.ts # congressgov_committee_reports
123
134
  daily-record.tool.ts # congressgov_daily_record
135
+ search-bills.tool.ts # congressgov_search_bills (opt-in — disabledTool() when the mirror is off)
124
136
  resources/definitions/
125
137
  current-congress.resource.ts # congress://current
126
138
  bill-types.resource.ts # congress://bill-types
@@ -130,13 +142,18 @@ src/
130
142
  prompts/definitions/
131
143
  bill-analysis.prompt.ts # congressgov_bill_analysis
132
144
  legislative-research.prompt.ts # congressgov_legislative_research
145
+ scripts/
146
+ _mirror-context.ts # Shared bootstrap for the mirror lifecycle CLI scripts
147
+ congress-mirror-init.ts # mirror:init — full out-of-band mirror build
148
+ congress-mirror-refresh.ts # mirror:refresh — incremental mirror refresh
149
+ congress-mirror-verify.ts # mirror:verify — readiness + integrity check
133
150
  ```
134
151
 
135
152
  ---
136
153
 
137
154
  ## Services
138
155
 
139
- Two services. `CongressApiService` backs nine tools and the House branch of `congressgov_roll_votes`; `SenateVoteService` backs only the Senate branch of `congressgov_roll_votes` (the Congress.gov API exposes no Senate vote namespace).
156
+ Three services. `CongressApiService` backs nine tools and the House branch of `congressgov_roll_votes`; `SenateVoteService` backs only the Senate branch of `congressgov_roll_votes` (the Congress.gov API exposes no Senate vote namespace); `CongressMirrorService` backs `congressgov_search_bills` only.
140
157
 
141
158
  **`CongressApiService`** — wraps the Congress.gov REST API v3:
142
159
  - API key via `X-Api-Key` header (never logged; kept out of the URL so it can't leak in upstream error messages)
@@ -151,6 +168,10 @@ Two services. `CongressApiService` backs nine tools and the House branch of `con
151
168
  - The host returns HTTP 200 with an HTML page for unknown congress/session/vote, so "not found" is detected from the body, not the status code
152
169
  - Party totals are derived from the roster (the feed publishes none)
153
170
 
171
+ **`CongressMirrorService`** — local SQLite FTS5 mirror of bill title + CRS summary text, backing `congressgov_search_bills` only:
172
+ - Opt-in via `CONGRESS_MIRROR_ENABLED` (off by default); built out-of-band via the `mirror:init`/`mirror:refresh` scripts, never on server startup
173
+ - No live-API fallback — ingests through the existing `CongressApiService`, and a mirror that hasn't finished its initial build returns an empty result with a notice, not an error
174
+
154
175
  **Usage in tools:**
155
176
  ```ts
156
177
  import { getCongressApi } from '@/services/congress-api/congress-api-service.js';
package/Dockerfile CHANGED
@@ -71,6 +71,19 @@ RUN if [ "$OTEL_ENABLED" = "true" ]; then \
71
71
  # Copy the compiled application code from the build stage
72
72
  COPY --from=build /usr/src/app/dist ./dist
73
73
 
74
+ # Copy the mirror lifecycle scripts (mirror:init / mirror:refresh / mirror:verify)
75
+ # and the shared context shim they import, then emit a runtime tsconfig so Bun
76
+ # resolves the @/ path alias against the compiled ./dist (the source ./src never
77
+ # reaches the runtime image). Same `bun run mirror:*` commands work in dev and the
78
+ # image; run `docker exec <container> bun run mirror:init` to build the index.
79
+ # See the api-mirror skill for the full recipe.
80
+ COPY --from=build /usr/src/app/scripts/congress-mirror-init.ts \
81
+ /usr/src/app/scripts/congress-mirror-refresh.ts \
82
+ /usr/src/app/scripts/congress-mirror-verify.ts \
83
+ /usr/src/app/scripts/_mirror-context.ts \
84
+ ./scripts/
85
+ RUN echo '{"compilerOptions":{"baseUrl":".","paths":{"@/*":["./dist/*"]}}}' > tsconfig.json
86
+
74
87
  # The 'oven/bun' image already provides a non-root user named 'bun'.
75
88
  # We will use this existing user for enhanced security.
76
89
 
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  <div align="center">
2
2
  <h1>@cyanheads/congressgov-mcp-server</h1>
3
3
  <p><b>Access U.S. congressional data - bills, votes, members, committees - through MCP. STDIO & Streamable HTTP.</b>
4
- <div>10 Tools • 5 Resources • 2 Prompts</div>
4
+ <div>11 Tools • 5 Resources • 2 Prompts</div>
5
5
  </p>
6
6
  </div>
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.3.32-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![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/congressgov-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/congressgov-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/congressgov-mcp-server) [![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-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.4.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![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/congressgov-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/congressgov-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/congressgov-mcp-server) [![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-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -29,7 +29,7 @@
29
29
 
30
30
  ## Tools
31
31
 
32
- Ten read-only tools for querying U.S. legislative data:
32
+ Eleven read-only tools for querying U.S. legislative data:
33
33
 
34
34
  | Tool | Description |
35
35
  |:---|:---|
@@ -43,6 +43,7 @@ Ten read-only tools for querying U.S. legislative data:
43
43
  | `congressgov_crs_reports` | Browse and retrieve nonpartisan CRS policy analysis reports |
44
44
  | `congressgov_committee_reports` | Browse and retrieve committee reports accompanying legislation |
45
45
  | `congressgov_daily_record` | Browse the daily Congressional Record — floor speeches, debates, and proceedings |
46
+ | `congressgov_search_bills` | Keyword-search bill titles and CRS summaries via a local full-text mirror (opt-in, off by default) |
46
47
 
47
48
  ### `congressgov_bill_lookup`
48
49
 
@@ -112,6 +113,16 @@ Browse the daily Congressional Record — floor speeches, debates, and legislati
112
113
  - Browse volumes by congress number
113
114
  - Retrieve specific issue articles
114
115
 
116
+ ---
117
+
118
+ ### `congressgov_search_bills`
119
+
120
+ Keyword-search bill titles and CRS summaries against a local full-text mirror — the discovery path the Congress.gov API itself lacks.
121
+
122
+ - **Opt-in:** off by default. Requires `CONGRESS_MIRROR_ENABLED=true` and a locally built index (`bun run mirror:init`) — until then the tool is visible but not callable
123
+ - Narrow with `congress`, `billType`, and `originChamber` filters
124
+ - Returns BM25-ranked matches with each bill's derived id, ready for a follow-up `congressgov_bill_lookup` call
125
+
115
126
  ## Resources
116
127
 
117
128
  | URI Pattern | Description |
@@ -271,7 +282,7 @@ docker run -e CONGRESS_API_KEY=your-api-key -p 3010:3010 congressgov-mcp-server
271
282
 
272
283
  | Directory | Purpose |
273
284
  |:---|:---|
274
- | `src/mcp-server/tools/definitions/` | Tool definitions (`*.tool.ts`). Ten Congress.gov tools. |
285
+ | `src/mcp-server/tools/definitions/` | Tool definitions (`*.tool.ts`). Eleven Congress.gov tools. |
275
286
  | `src/mcp-server/resources/definitions/` | Resource definitions. Congress, bill, member, and committee resources. |
276
287
  | `src/mcp-server/prompts/definitions/` | Prompt definitions. Bill analysis and legislative research prompts. |
277
288
  | `src/services/congress-api/` | Congress.gov API client — auth, pagination, rate limiting. |
@@ -3,11 +3,26 @@
3
3
  * @module config/server-config
4
4
  */
5
5
  import { z } from '@cyanheads/mcp-ts-core';
6
+ /** Default on-disk location of the SQLite bill FTS mirror. */
7
+ export declare const DEFAULT_MIRROR_PATH = ".mirror/bills.sqlite3";
8
+ /**
9
+ * Congress number covering a given date. The 1st U.S. Congress convened in 1789
10
+ * and each Congress spans two years, so `floor((year - 1789) / 2) + 1` yields the
11
+ * ordinal (2025–2026 → 119). Used to seed the default mirror window when
12
+ * `CONGRESS_MIRROR_CONGRESSES` is unset.
13
+ */
14
+ export declare function currentCongressNumber(date?: Date): number;
6
15
  declare const ServerConfigSchema: z.ZodObject<{
7
16
  apiKey: z.ZodDefault<z.ZodString>;
8
17
  baseUrl: z.ZodDefault<z.ZodString>;
18
+ mirrorEnabled: z.ZodPreprocess<z.ZodCodec<z.ZodString, z.ZodBoolean>>;
19
+ mirrorPath: z.ZodDefault<z.ZodString>;
20
+ mirrorRefreshCron: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
21
+ congresses: z.ZodPreprocess<z.ZodArray<z.ZodNumber>>;
9
22
  }, z.core.$strip>;
10
23
  export type ServerConfig = z.infer<typeof ServerConfigSchema>;
11
24
  export declare function getServerConfig(): ServerConfig;
25
+ /** Reset the cached config — test-only. */
26
+ export declare function resetServerConfig(): void;
12
27
  export {};
13
28
  //# sourceMappingURL=server-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;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,wBAAgB,eAAe,IAAI,YAAY,CAM9C"}
1
+ {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAG3C,8DAA8D;AAC9D,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,GAAE,IAAiB,GAAG,MAAM,CAErE;AAoBD,QAAA,MAAM,kBAAkB;;;;;;;iBA0CtB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,wBAAgB,eAAe,IAAI,YAAY,CAU9C;AAED,2CAA2C;AAC3C,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -4,6 +4,34 @@
4
4
  */
5
5
  import { z } from '@cyanheads/mcp-ts-core';
6
6
  import { parseEnvConfig } from '@cyanheads/mcp-ts-core/config';
7
+ /** Default on-disk location of the SQLite bill FTS mirror. */
8
+ export const DEFAULT_MIRROR_PATH = '.mirror/bills.sqlite3';
9
+ /**
10
+ * Congress number covering a given date. The 1st U.S. Congress convened in 1789
11
+ * and each Congress spans two years, so `floor((year - 1789) / 2) + 1` yields the
12
+ * ordinal (2025–2026 → 119). Used to seed the default mirror window when
13
+ * `CONGRESS_MIRROR_CONGRESSES` is unset.
14
+ */
15
+ export function currentCongressNumber(date = new Date()) {
16
+ return Math.floor((date.getUTCFullYear() - 1789) / 2) + 1;
17
+ }
18
+ /**
19
+ * Parse `CONGRESS_MIRROR_CONGRESSES` — a comma-separated list of congress numbers
20
+ * ("118,119") — into a positive-integer array. Unset/empty falls back to the
21
+ * current congress plus the one prior (the realistic "what's this recent bill
22
+ * about" search window); a fully malformed value resolves to an empty array,
23
+ * which the `.min(1)` guard rejects loudly at startup.
24
+ */
25
+ function parseCongresses(value) {
26
+ if (typeof value === 'string' && value.trim() !== '') {
27
+ return value
28
+ .split(',')
29
+ .map((s) => Number.parseInt(s.trim(), 10))
30
+ .filter((n) => Number.isInteger(n) && n > 0);
31
+ }
32
+ const current = currentCongressNumber();
33
+ return [current, current - 1];
34
+ }
7
35
  const ServerConfigSchema = z.object({
8
36
  apiKey: z
9
37
  .string()
@@ -14,13 +42,50 @@ const ServerConfigSchema = z.object({
14
42
  .url()
15
43
  .default('https://api.congress.gov/v3')
16
44
  .describe('Congress.gov API base URL'),
45
+ /**
46
+ * Master switch for the local bill FTS mirror + `congressgov_search_bills`.
47
+ * Off by default so the standard deploy stays config-free and the live-API
48
+ * tools are unaffected. Unset/empty/malformed resolves to `false`.
49
+ */
50
+ mirrorEnabled: z
51
+ .preprocess((v) => (v === undefined || v === null || v === '' ? 'false' : v), z.stringbool())
52
+ .describe('Enable the local bill search mirror and the congressgov_search_bills tool.'),
53
+ /** Filesystem path to the SQLite mirror index file (matches the Dockerfile `.mirror` dir). */
54
+ mirrorPath: z
55
+ .string()
56
+ .min(1)
57
+ .default(DEFAULT_MIRROR_PATH)
58
+ .describe('Filesystem path to the SQLite bill mirror index.'),
59
+ /**
60
+ * Cron expression for the in-process incremental refresh (HTTP transport only).
61
+ * Unset means no in-process schedule — run `bun run mirror:refresh` out-of-band.
62
+ */
63
+ mirrorRefreshCron: z
64
+ .preprocess((v) => (v === '' || v === null ? undefined : v), z.string().min(1).optional())
65
+ .describe('Cron schedule for the in-process mirror refresh (HTTP only; omit to run manually).'),
66
+ /**
67
+ * Congresses to mirror. Defaults to the current congress plus the one prior.
68
+ * Comma-separated env value (e.g. "118,119"); widening the window is a config
69
+ * change, not a redesign.
70
+ */
71
+ congresses: z
72
+ .preprocess(parseCongresses, z.array(z.number().int().positive()).min(1))
73
+ .describe('Congress numbers included in the mirror (default: current + 1 prior).'),
17
74
  });
18
75
  let _config;
19
76
  export function getServerConfig() {
20
77
  _config ??= parseEnvConfig(ServerConfigSchema, {
21
78
  apiKey: 'CONGRESS_API_KEY',
22
79
  baseUrl: 'CONGRESS_API_BASE_URL',
80
+ mirrorEnabled: 'CONGRESS_MIRROR_ENABLED',
81
+ mirrorPath: 'CONGRESS_MIRROR_PATH',
82
+ mirrorRefreshCron: 'CONGRESS_MIRROR_REFRESH_CRON',
83
+ congresses: 'CONGRESS_MIRROR_CONGRESSES',
23
84
  });
24
85
  return _config;
25
86
  }
87
+ /** Reset the cached config — test-only. */
88
+ export function resetServerConfig() {
89
+ _config = undefined;
90
+ }
26
91
  //# sourceMappingURL=server-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;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,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CACP,+FAA+F,CAChG;IACH,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,EAAE;SACL,OAAO,CAAC,6BAA6B,CAAC;SACtC,QAAQ,CAAC,2BAA2B,CAAC;CACzC,CAAC,CAAC;AAIH,IAAI,OAAiC,CAAC;AAEtC,MAAM,UAAU,eAAe;IAC7B,OAAO,KAAK,cAAc,CAAC,kBAAkB,EAAE;QAC7C,MAAM,EAAE,kBAAkB;QAC1B,OAAO,EAAE,uBAAuB;KACjC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"server-config.js","sourceRoot":"","sources":["../../src/config/server-config.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,6 +4,8 @@
4
4
  * @module index
5
5
  */
6
6
  import { createApp } from '@cyanheads/mcp-ts-core';
7
+ import { logger, schedulerService } from '@cyanheads/mcp-ts-core/utils';
8
+ import { getServerConfig } from './config/server-config.js';
7
9
  import { billAnalysisPrompt } from './mcp-server/prompts/definitions/bill-analysis.prompt.js';
8
10
  import { legislativeResearchPrompt } from './mcp-server/prompts/definitions/legislative-research.prompt.js';
9
11
  import { billResource } from './mcp-server/resources/definitions/bill.resource.js';
@@ -20,8 +22,10 @@ import { dailyRecordTool } from './mcp-server/tools/definitions/daily-record.too
20
22
  import { enactedLawsTool } from './mcp-server/tools/definitions/enacted-laws.tool.js';
21
23
  import { memberLookupTool } from './mcp-server/tools/definitions/member-lookup.tool.js';
22
24
  import { rollVotesTool } from './mcp-server/tools/definitions/roll-votes.tool.js';
25
+ import { searchBillsTool } from './mcp-server/tools/definitions/search-bills.tool.js';
23
26
  import { senateNominationsTool } from './mcp-server/tools/definitions/senate-nominations.tool.js';
24
27
  import { initCongressApi } from './services/congress-api/congress-api-service.js';
28
+ import { getCongressMirror, initCongressMirror, } from './services/congress-mirror/congress-mirror-service.js';
25
29
  import { initSenateVoteService } from './services/senate-lis/senate-vote-service.js';
26
30
  const REPO_ROOT = 'https://github.com/cyanheads/congressgov-mcp-server';
27
31
  /**
@@ -46,6 +50,7 @@ await createApp({
46
50
  withSource(crsReportsTool, 'tools', 'crs-reports.tool.ts'),
47
51
  withSource(committeeReportsTool, 'tools', 'committee-reports.tool.ts'),
48
52
  withSource(dailyRecordTool, 'tools', 'daily-record.tool.ts'),
53
+ withSource(searchBillsTool, 'tools', 'search-bills.tool.ts'),
49
54
  ],
50
55
  resources: [
51
56
  withSource(currentCongressResource, 'resources', 'current-congress.resource.ts'),
@@ -58,15 +63,38 @@ await createApp({
58
63
  withSource(billAnalysisPrompt, 'prompts', 'bill-analysis.prompt.ts'),
59
64
  withSource(legislativeResearchPrompt, 'prompts', 'legislative-research.prompt.ts'),
60
65
  ],
61
- instructions: `Use the congressgov_* tools to access U.S. legislative data via the Congress.gov API v3: bills, enacted laws, members, committees, roll call votes, presidential nominations, CRS reports, and the daily Congressional Record. There is no keyword search — browse by congress number, bill/report type, date range, chamber, state, and district. Bills are addressed by congress + billType + billNumber (e.g. 118/hr/1234), members by bioguideId, committees by chamber-prefix codes. congressgov_roll_votes serves both chambers via its 'chamber' parameter — House votes come from the Congress.gov API, Senate votes from the Senate's official LIS feed.`,
66
+ instructions: `Use the congressgov_* tools to access U.S. legislative data via the Congress.gov API v3: bills, enacted laws, members, committees, roll call votes, presidential nominations, CRS reports, and the daily Congressional Record. The Congress.gov API itself has no keyword search — browse by congress number, bill/report type, date range, chamber, state, and district. An optional local FTS mirror adds congressgov_search_bills (keyword search over bill titles and summaries) when CONGRESS_MIRROR_ENABLED is set; off by default, the tool is visible but not callable. Bills are addressed by congress + billType + billNumber (e.g. 118/hr/1234), members by bioguideId, committees by chamber-prefix codes. congressgov_roll_votes serves both chambers via its 'chamber' parameter — House votes come from the Congress.gov API, Senate votes from the Senate's official LIS feed.`,
62
67
  landing: {
63
68
  repoRoot: REPO_ROOT,
64
69
  tagline: 'U.S. legislative data — bills, votes, members, committees — via MCP.',
65
70
  requireAuth: false,
66
71
  },
67
- setup() {
72
+ setup(core) {
68
73
  initCongressApi();
69
74
  initSenateVoteService();
75
+ /**
76
+ * The bill FTS mirror is opt-in (off by default). When enabled, wire the
77
+ * service; a full init runs out-of-band via `mirror:init` (never on startup).
78
+ * The in-process incremental refresh is scheduled only under HTTP transport
79
+ * (a long-lived process owns the cron) and only when a cron is configured —
80
+ * stdio operators run `mirror:refresh` out-of-band.
81
+ */
82
+ const config = getServerConfig();
83
+ if (config.mirrorEnabled) {
84
+ initCongressMirror({ mirrorPath: config.mirrorPath, congresses: config.congresses });
85
+ if (core.config.mcpTransportType === 'http' && config.mirrorRefreshCron) {
86
+ void scheduleMirrorRefresh(config.mirrorRefreshCron);
87
+ }
88
+ }
70
89
  },
71
90
  });
91
+ /** Register and start the in-process incremental mirror refresh job. */
92
+ async function scheduleMirrorRefresh(cron) {
93
+ await schedulerService.schedule('congress-bills-refresh', cron, async (jobCtx) => {
94
+ logger.info('Starting scheduled Congress bill mirror refresh', jobCtx);
95
+ const result = await getCongressMirror().mirrorInstance.runSync({ mode: 'refresh' });
96
+ logger.info(`Scheduled Congress bill mirror refresh complete: ${result.recordsApplied} records applied (total ${result.total})`, jobCtx);
97
+ }, 'Incremental refresh of the local Congress bill FTS mirror from Congress.gov.');
98
+ schedulerService.start('congress-bills-refresh');
99
+ }
72
100
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @fileoverview congressgov_search_bills — keyword search over the local bill FTS
3
+ * mirror, the discovery path the Congress.gov API structurally lacks. Queries the
4
+ * embedded SQLite + FTS5 index (title + summary), not the live API, so it has no
5
+ * live fallback: a mirror that has not finished its initial build returns an empty
6
+ * result with an enrichment notice rather than a thrown error. Gated behind
7
+ * CONGRESS_MIRROR_ENABLED via disabledTool() — visible-but-uncallable when the
8
+ * mirror is off (the default).
9
+ * @module mcp-server/tools/definitions/search-bills
10
+ */
11
+ import { z } from '@cyanheads/mcp-ts-core';
12
+ /**
13
+ * Gated behind the mirror master switch. When the mirror is off (the default) the
14
+ * tool renders on the landing page as present-but-uncallable with a hint, and is
15
+ * skipped during MCP registration so clients can't call a guaranteed-empty search.
16
+ */
17
+ export declare const searchBillsTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
18
+ query: z.ZodString;
19
+ congress: z.ZodOptional<z.ZodNumber>;
20
+ billType: z.ZodOptional<z.ZodEnum<{
21
+ hr: "hr";
22
+ s: "s";
23
+ hjres: "hjres";
24
+ sjres: "sjres";
25
+ hconres: "hconres";
26
+ sconres: "sconres";
27
+ hres: "hres";
28
+ sres: "sres";
29
+ }>>;
30
+ originChamber: z.ZodOptional<z.ZodEnum<{
31
+ House: "House";
32
+ Senate: "Senate";
33
+ }>>;
34
+ limit: z.ZodDefault<z.ZodNumber>;
35
+ offset: z.ZodDefault<z.ZodNumber>;
36
+ }, z.core.$strip>, z.ZodObject<{
37
+ data: z.ZodArray<z.ZodObject<{}, z.core.$loose>>;
38
+ pagination: z.ZodObject<{
39
+ count: z.ZodNumber;
40
+ nextOffset: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
41
+ }, z.core.$strip>;
42
+ }, z.core.$loose>, undefined, {
43
+ effectiveQuery: z.ZodString;
44
+ totalCount: z.ZodNumber;
45
+ notice: z.ZodOptional<z.ZodString>;
46
+ }>;
47
+ //# sourceMappingURL=search-bills.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-bills.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-bills.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAsG/D;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKtB,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * @fileoverview congressgov_search_bills — keyword search over the local bill FTS
3
+ * mirror, the discovery path the Congress.gov API structurally lacks. Queries the
4
+ * embedded SQLite + FTS5 index (title + summary), not the live API, so it has no
5
+ * live fallback: a mirror that has not finished its initial build returns an empty
6
+ * result with an enrichment notice rather than a thrown error. Gated behind
7
+ * CONGRESS_MIRROR_ENABLED via disabledTool() — visible-but-uncallable when the
8
+ * mirror is off (the default).
9
+ * @module mcp-server/tools/definitions/search-bills
10
+ */
11
+ import { disabledTool, tool, z } from '@cyanheads/mcp-ts-core';
12
+ import { getServerConfig } from '../../../config/server-config.js';
13
+ import { formatSearchBills } from '../../../mcp-server/tools/format-helpers.js';
14
+ import { buildEffectiveQuery, listEnrichment, listOutput, } from '../../../mcp-server/tools/tool-helpers.js';
15
+ import { BILL_TYPE_CODES } from '../../../services/congress-api/types.js';
16
+ import { getCongressMirror } from '../../../services/congress-mirror/congress-mirror-service.js';
17
+ const searchBillsDef = tool('congressgov_search_bills', {
18
+ description: `Keyword-search U.S. bills by title and CRS summary text — the discovery path the Congress.gov API itself lacks (it has no keyword search). Backed by a local full-text index over a bounded congress window; title and summary are indexed, but policy area and full bill text are not. Returns BM25-ranked matches, each with the bill's derived id (congress/billType/billNumber) for follow-up congressgov_bill_lookup calls and a truncated summary preview. Narrow with the optional congress, billType, and originChamber filters. Searches the local mirror, not the live API — if the mirror has not finished its initial build it returns an empty result with a notice, not an error.`,
19
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
20
+ input: z.object({
21
+ query: z
22
+ .string()
23
+ .min(1)
24
+ .describe('Free-text keywords matched against bill titles and summaries (e.g. "semiconductor export controls"). Tokens are AND-combined.'),
25
+ congress: z
26
+ .number()
27
+ .int()
28
+ .positive()
29
+ .optional()
30
+ .describe('Restrict to a single congress (e.g. 119). Omit to search the whole mirrored window.'),
31
+ billType: z
32
+ .enum(BILL_TYPE_CODES)
33
+ .optional()
34
+ .describe('Restrict to a bill type (hr, s, hjres, sjres, hconres, sconres, hres, sres).'),
35
+ originChamber: z
36
+ .enum(['House', 'Senate'])
37
+ .optional()
38
+ .describe('Restrict to the originating chamber.'),
39
+ limit: z
40
+ .number()
41
+ .int()
42
+ .min(1)
43
+ .max(100)
44
+ .default(20)
45
+ .describe('Results per page (1–100, default 20).'),
46
+ offset: z.number().int().min(0).default(0).describe('Pagination offset.'),
47
+ }),
48
+ output: listOutput,
49
+ enrichment: listEnrichment,
50
+ format: formatSearchBills,
51
+ async handler(input, ctx) {
52
+ const service = getCongressMirror();
53
+ ctx.enrich.echo(buildEffectiveQuery('bill search', {
54
+ query: input.query,
55
+ congress: input.congress,
56
+ billType: input.billType,
57
+ originChamber: input.originChamber,
58
+ }));
59
+ /** No live-API fallback — a mirror that never completed an initial sync is an
60
+ * empty result plus a notice pointing at the refresh, never a throw. */
61
+ if (!(await service.ready())) {
62
+ ctx.enrich.total(0);
63
+ ctx.enrich.notice('The bill search mirror has not finished its initial build yet, so no results are available. Build it with the mirror:init script (or wait for the scheduled refresh) and retry.');
64
+ return { data: [], pagination: { count: 0, nextOffset: null } };
65
+ }
66
+ const page = await service.search({
67
+ query: input.query,
68
+ congress: input.congress,
69
+ billType: input.billType,
70
+ originChamber: input.originChamber,
71
+ limit: input.limit,
72
+ offset: input.offset,
73
+ }, ctx);
74
+ ctx.log.info('Bill search complete', { query: input.query, matches: page.total });
75
+ ctx.enrich.total(page.total);
76
+ if (page.items.length === 0) {
77
+ ctx.enrich.notice(`No bills matched "${input.query}". Try broader or fewer keywords, or remove the congress/billType/originChamber filters.`);
78
+ }
79
+ const nextOffset = page.offset + page.items.length < page.total ? page.offset + page.items.length : null;
80
+ /** The shared list envelope carries `data` as passthrough records; the typed
81
+ * search results widen cleanly to that shape. */
82
+ return {
83
+ data: page.items,
84
+ pagination: { count: page.total, nextOffset },
85
+ };
86
+ },
87
+ });
88
+ /**
89
+ * Gated behind the mirror master switch. When the mirror is off (the default) the
90
+ * tool renders on the landing page as present-but-uncallable with a hint, and is
91
+ * skipped during MCP registration so clients can't call a guaranteed-empty search.
92
+ */
93
+ export const searchBillsTool = getServerConfig().mirrorEnabled
94
+ ? searchBillsDef
95
+ : disabledTool(searchBillsDef, {
96
+ reason: 'The local bill search mirror is turned off in this deployment.',
97
+ hint: 'CONGRESS_MIRROR_ENABLED=true',
98
+ });
99
+ //# sourceMappingURL=search-bills.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-bills.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-bills.tool.ts"],"names":[],"mappings":"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"}