@cyanheads/congressgov-mcp-server 0.3.25 → 0.3.26
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/AGENTS.md +16 -6
- package/CLAUDE.md +16 -6
- package/README.md +7 -6
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/tools/definitions/roll-votes.tool.d.ts +7 -1
- package/dist/mcp-server/tools/definitions/roll-votes.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/roll-votes.tool.js +64 -3
- package/dist/mcp-server/tools/definitions/roll-votes.tool.js.map +1 -1
- package/dist/mcp-server/tools/format-helpers.d.ts +5 -1
- package/dist/mcp-server/tools/format-helpers.d.ts.map +1 -1
- package/dist/mcp-server/tools/format-helpers.js +176 -4
- package/dist/mcp-server/tools/format-helpers.js.map +1 -1
- package/dist/services/senate-lis/parse.d.ts +32 -0
- package/dist/services/senate-lis/parse.d.ts.map +1 -0
- package/dist/services/senate-lis/parse.js +229 -0
- package/dist/services/senate-lis/parse.js.map +1 -0
- package/dist/services/senate-lis/senate-vote-service.d.ts +73 -0
- package/dist/services/senate-lis/senate-vote-service.d.ts.map +1 -0
- package/dist/services/senate-lis/senate-vote-service.js +182 -0
- package/dist/services/senate-lis/senate-vote-service.js.map +1 -0
- package/dist/services/senate-lis/types.d.ts +122 -0
- package/dist/services/senate-lis/types.d.ts.map +1 -0
- package/dist/services/senate-lis/types.js +16 -0
- package/dist/services/senate-lis/types.js.map +1 -0
- package/package.json +2 -1
- 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.
|
|
4
|
+
**Version:** 0.3.26
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.9.16`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
|
@@ -68,7 +68,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
68
68
|
| `congressgov_enacted_laws` | Browse enacted public and private laws by congress |
|
|
69
69
|
| `congressgov_member_lookup` | Discover members by state/district/congress, retrieve legislative portfolios |
|
|
70
70
|
| `congressgov_committee_lookup` | Browse committees and retrieve legislation, reports, nominations |
|
|
71
|
-
| `congressgov_roll_votes` | Retrieve House roll call votes and member voting positions |
|
|
71
|
+
| `congressgov_roll_votes` | Retrieve House and Senate roll call votes and member voting positions |
|
|
72
72
|
| `congressgov_senate_nominations` | Browse presidential nominations, track Senate confirmation pipeline |
|
|
73
73
|
| `congressgov_bill_summaries` | Browse recent CRS bill summaries — the "what's happening" feed |
|
|
74
74
|
| `congressgov_crs_reports` | Browse and retrieve nonpartisan CRS policy analysis reports |
|
|
@@ -105,6 +105,10 @@ src/
|
|
|
105
105
|
congress-api/
|
|
106
106
|
congress-api-service.ts # API client — auth, pagination, rate limiting
|
|
107
107
|
types.ts # API response types
|
|
108
|
+
senate-lis/
|
|
109
|
+
senate-vote-service.ts # Senate LIS XML client — fetch, retry, not-found
|
|
110
|
+
parse.ts # pure XML → domain parsers (fast-xml-parser)
|
|
111
|
+
types.ts # Senate vote domain types
|
|
108
112
|
mcp-server/
|
|
109
113
|
tools/definitions/
|
|
110
114
|
bill-lookup.tool.ts # congressgov_bill_lookup
|
|
@@ -130,17 +134,23 @@ src/
|
|
|
130
134
|
|
|
131
135
|
---
|
|
132
136
|
|
|
133
|
-
##
|
|
137
|
+
## Services
|
|
134
138
|
|
|
135
|
-
|
|
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).
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
- API key via
|
|
141
|
+
**`CongressApiService`** — wraps the Congress.gov REST API v3:
|
|
142
|
+
- API key via `X-Api-Key` header (never logged; kept out of the URL so it can't leak in upstream error messages)
|
|
139
143
|
- Pagination: `offset` + `limit` query params, max 250 per request
|
|
140
144
|
- Rate limiting: 5,000 requests/hour per key
|
|
141
145
|
- Response normalization: request `format=json`, return typed data
|
|
142
146
|
- Native `fetch` — no SDK dependency
|
|
143
147
|
|
|
148
|
+
**`SenateVoteService`** — wraps the Senate's official LIS roll-call XML feed (`senate.gov/legislative/LIS`):
|
|
149
|
+
- No API key, no JSON. XML parsed via `fast-xml-parser` in `parse.ts` (pure, fixture-tested)
|
|
150
|
+
- The whole session menu is one file; each vote's roster ships inline — pagination is client-side
|
|
151
|
+
- 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
|
+
- Party totals are derived from the roster (the feed publishes none)
|
|
153
|
+
|
|
144
154
|
**Usage in tools:**
|
|
145
155
|
```ts
|
|
146
156
|
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.
|
|
4
|
+
**Version:** 0.3.26
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.9.16`
|
|
6
6
|
**Engines:** Bun ≥1.3.0, Node ≥24.0.0
|
|
7
7
|
**MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
|
|
@@ -68,7 +68,7 @@ Tailor suggestions to what's actually missing or stale — don't recite the full
|
|
|
68
68
|
| `congressgov_enacted_laws` | Browse enacted public and private laws by congress |
|
|
69
69
|
| `congressgov_member_lookup` | Discover members by state/district/congress, retrieve legislative portfolios |
|
|
70
70
|
| `congressgov_committee_lookup` | Browse committees and retrieve legislation, reports, nominations |
|
|
71
|
-
| `congressgov_roll_votes` | Retrieve House roll call votes and member voting positions |
|
|
71
|
+
| `congressgov_roll_votes` | Retrieve House and Senate roll call votes and member voting positions |
|
|
72
72
|
| `congressgov_senate_nominations` | Browse presidential nominations, track Senate confirmation pipeline |
|
|
73
73
|
| `congressgov_bill_summaries` | Browse recent CRS bill summaries — the "what's happening" feed |
|
|
74
74
|
| `congressgov_crs_reports` | Browse and retrieve nonpartisan CRS policy analysis reports |
|
|
@@ -105,6 +105,10 @@ src/
|
|
|
105
105
|
congress-api/
|
|
106
106
|
congress-api-service.ts # API client — auth, pagination, rate limiting
|
|
107
107
|
types.ts # API response types
|
|
108
|
+
senate-lis/
|
|
109
|
+
senate-vote-service.ts # Senate LIS XML client — fetch, retry, not-found
|
|
110
|
+
parse.ts # pure XML → domain parsers (fast-xml-parser)
|
|
111
|
+
types.ts # Senate vote domain types
|
|
108
112
|
mcp-server/
|
|
109
113
|
tools/definitions/
|
|
110
114
|
bill-lookup.tool.ts # congressgov_bill_lookup
|
|
@@ -130,17 +134,23 @@ src/
|
|
|
130
134
|
|
|
131
135
|
---
|
|
132
136
|
|
|
133
|
-
##
|
|
137
|
+
## Services
|
|
134
138
|
|
|
135
|
-
|
|
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).
|
|
136
140
|
|
|
137
|
-
|
|
138
|
-
- API key via
|
|
141
|
+
**`CongressApiService`** — wraps the Congress.gov REST API v3:
|
|
142
|
+
- API key via `X-Api-Key` header (never logged; kept out of the URL so it can't leak in upstream error messages)
|
|
139
143
|
- Pagination: `offset` + `limit` query params, max 250 per request
|
|
140
144
|
- Rate limiting: 5,000 requests/hour per key
|
|
141
145
|
- Response normalization: request `format=json`, return typed data
|
|
142
146
|
- Native `fetch` — no SDK dependency
|
|
143
147
|
|
|
148
|
+
**`SenateVoteService`** — wraps the Senate's official LIS roll-call XML feed (`senate.gov/legislative/LIS`):
|
|
149
|
+
- No API key, no JSON. XML parsed via `fast-xml-parser` in `parse.ts` (pure, fixture-tested)
|
|
150
|
+
- The whole session menu is one file; each vote's roster ships inline — pagination is client-side
|
|
151
|
+
- 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
|
+
- Party totals are derived from the roster (the feed publishes none)
|
|
153
|
+
|
|
144
154
|
**Usage in tools:**
|
|
145
155
|
```ts
|
|
146
156
|
import { getCongressApi } from '@/services/congress-api/congress-api-service.js';
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/users/cyanheads/packages/container/package/congressgov-mcp-server) [](https://modelcontextprotocol.io/) [](https://www.npmjs.com/package/@cyanheads/congressgov-mcp-server) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -37,7 +37,7 @@ Ten read-only tools for querying U.S. legislative data:
|
|
|
37
37
|
| `congressgov_enacted_laws` | Browse enacted public and private laws by congress |
|
|
38
38
|
| `congressgov_member_lookup` | Discover congressional members by state/district/congress, retrieve legislative portfolios |
|
|
39
39
|
| `congressgov_committee_lookup` | Browse congressional committees and their legislation, reports, and nominations |
|
|
40
|
-
| `congressgov_roll_votes` | Retrieve House roll call
|
|
40
|
+
| `congressgov_roll_votes` | Retrieve House and Senate roll call votes and individual member voting positions |
|
|
41
41
|
| `congressgov_senate_nominations` | Browse presidential nominations to federal positions and track the Senate confirmation process |
|
|
42
42
|
| `congressgov_bill_summaries` | Browse recent CRS bill summaries — the "what's happening" feed |
|
|
43
43
|
| `congressgov_crs_reports` | Browse and retrieve nonpartisan CRS policy analysis reports |
|
|
@@ -78,11 +78,12 @@ Browse congressional committees and their legislation, reports, and nominations.
|
|
|
78
78
|
|
|
79
79
|
### `congressgov_roll_votes`
|
|
80
80
|
|
|
81
|
-
Retrieve House roll call
|
|
81
|
+
Retrieve House and Senate roll call votes and individual member voting positions.
|
|
82
82
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
- `
|
|
83
|
+
- Set `chamber` to `house` (default, from the Congress.gov API) or `senate` (from the Senate's official LIS feed — the API exposes no Senate votes)
|
|
84
|
+
- `list` browses votes by congress and session, newest first; pass `order='oldest'` for ascending
|
|
85
|
+
- `get` returns the question, result, tallies, party breakdown, and associated bill/nomination/amendment
|
|
86
|
+
- `members` returns each member's recorded position
|
|
86
87
|
|
|
87
88
|
---
|
|
88
89
|
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import { memberLookupTool } from './mcp-server/tools/definitions/member-lookup.t
|
|
|
22
22
|
import { rollVotesTool } from './mcp-server/tools/definitions/roll-votes.tool.js';
|
|
23
23
|
import { senateNominationsTool } from './mcp-server/tools/definitions/senate-nominations.tool.js';
|
|
24
24
|
import { initCongressApi } from './services/congress-api/congress-api-service.js';
|
|
25
|
+
import { initSenateVoteService } from './services/senate-lis/senate-vote-service.js';
|
|
25
26
|
const REPO_ROOT = 'https://github.com/cyanheads/congressgov-mcp-server';
|
|
26
27
|
/**
|
|
27
28
|
* File names strip the `congressgov_` name prefix (e.g. `congressgov_bill_lookup` →
|
|
@@ -55,7 +56,7 @@ await createApp({
|
|
|
55
56
|
withSource(billAnalysisPrompt, 'prompts', 'bill-analysis.prompt.ts'),
|
|
56
57
|
withSource(legislativeResearchPrompt, 'prompts', 'legislative-research.prompt.ts'),
|
|
57
58
|
],
|
|
58
|
-
instructions: `Use the congressgov_* tools to access U.S. legislative data via the Congress.gov API v3: bills, enacted laws, members, committees,
|
|
59
|
+
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.`,
|
|
59
60
|
landing: {
|
|
60
61
|
repoRoot: REPO_ROOT,
|
|
61
62
|
tagline: 'U.S. legislative data — bills, votes, members, committees — via MCP.',
|
|
@@ -63,6 +64,7 @@ await createApp({
|
|
|
63
64
|
},
|
|
64
65
|
setup() {
|
|
65
66
|
initCongressApi();
|
|
67
|
+
initSenateVoteService();
|
|
66
68
|
},
|
|
67
69
|
});
|
|
68
70
|
//# 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":";AAEA;;;GAGG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0DAA0D,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,iEAAiE,CAAC;AAC5G,OAAO,EAAE,YAAY,EAAE,MAAM,qDAAqD,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,0DAA0D,CAAC;AAC7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,iEAAiE,CAAC;AAC1G,OAAO,EAAE,cAAc,EAAE,MAAM,uDAAuD,CAAC;AACvF,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,yDAAyD,CAAC;AAC9F,OAAO,EAAE,oBAAoB,EAAE,MAAM,0DAA0D,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,qDAAqD,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,mDAAmD,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2DAA2D,CAAC;AAClG,OAAO,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Tool for retrieving House roll call vote data and member
|
|
2
|
+
* @fileoverview Tool for retrieving House and Senate roll call vote data and member
|
|
3
|
+
* voting positions. House votes come from the Congress.gov API; Senate votes from the
|
|
4
|
+
* Senate's official LIS XML feed (the API exposes no Senate vote namespace).
|
|
3
5
|
* @module mcp-server/tools/definitions/roll-votes
|
|
4
6
|
*/
|
|
5
7
|
import { z } from '@cyanheads/mcp-ts-core';
|
|
@@ -9,6 +11,10 @@ export declare const rollVotesTool: import("@cyanheads/mcp-ts-core").ToolDefinit
|
|
|
9
11
|
get: "get";
|
|
10
12
|
list: "list";
|
|
11
13
|
}>;
|
|
14
|
+
chamber: z.ZodDefault<z.ZodEnum<{
|
|
15
|
+
house: "house";
|
|
16
|
+
senate: "senate";
|
|
17
|
+
}>>;
|
|
12
18
|
congress: z.ZodNumber;
|
|
13
19
|
session: z.ZodNumber;
|
|
14
20
|
voteNumber: z.ZodOptional<z.ZodNumber>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roll-votes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/roll-votes.tool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"roll-votes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/roll-votes.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAajD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0HxB,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Tool for retrieving House roll call vote data and member
|
|
2
|
+
* @fileoverview Tool for retrieving House and Senate roll call vote data and member
|
|
3
|
+
* voting positions. House votes come from the Congress.gov API; Senate votes from the
|
|
4
|
+
* Senate's official LIS XML feed (the API exposes no Senate vote namespace).
|
|
3
5
|
* @module mcp-server/tools/definitions/roll-votes
|
|
4
6
|
*/
|
|
5
7
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
@@ -7,12 +9,17 @@ import { validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
|
7
9
|
import { formatVotes } from '../../../mcp-server/tools/format-helpers.js';
|
|
8
10
|
import { buildEffectiveQuery, congressErrorContracts, listEnrichment, listOrDetail, } from '../../../mcp-server/tools/tool-helpers.js';
|
|
9
11
|
import { getCongressApi } from '../../../services/congress-api/congress-api-service.js';
|
|
12
|
+
import { getSenateVoteService } from '../../../services/senate-lis/senate-vote-service.js';
|
|
10
13
|
export const rollVotesTool = tool('congressgov_roll_votes', {
|
|
11
|
-
description: `Retrieve
|
|
14
|
+
description: `Retrieve U.S. congressional roll call votes and individual member voting positions for either chamber. Set 'chamber' to 'house' (default, from the Congress.gov API) or 'senate' (from the Senate's official LIS feed). Use 'list' to find votes by congress and session (newest first by default), 'get' for vote details (question, result, tallies, party breakdown, associated bill/nomination/amendment), or 'members' for how each member voted.`,
|
|
12
15
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
13
16
|
errors: congressErrorContracts,
|
|
14
17
|
input: z.object({
|
|
15
18
|
operation: z.enum(['list', 'get', 'members']).describe('Which data to retrieve.'),
|
|
19
|
+
chamber: z
|
|
20
|
+
.enum(['house', 'senate'])
|
|
21
|
+
.default('house')
|
|
22
|
+
.describe("Chamber whose votes to query. 'house' (default) draws from the Congress.gov API; 'senate' draws from the Senate's official LIS roll-call feed. Roll call numbers reset each session and are specific to one chamber."),
|
|
16
23
|
congress: z.number().int().positive().describe('Congress number.'),
|
|
17
24
|
session: z
|
|
18
25
|
.number()
|
|
@@ -29,7 +36,7 @@ export const rollVotesTool = tool('congressgov_roll_votes', {
|
|
|
29
36
|
order: z
|
|
30
37
|
.enum(['recent', 'oldest'])
|
|
31
38
|
.default('recent')
|
|
32
|
-
.describe("Sort order for 'list'
|
|
39
|
+
.describe("Sort order for 'list'. 'recent' (default) returns newest first; 'oldest' returns ascending. House sorts by vote update date (with 'recent', offset=0 always returns the strictly newest page); Senate sorts by roll call number. Ignored by 'get' and 'members'."),
|
|
33
40
|
limit: z.number().int().min(1).max(250).default(20).describe('Results per page (1-250).'),
|
|
34
41
|
offset: z.number().int().min(0).default(0).describe('Pagination offset.'),
|
|
35
42
|
}),
|
|
@@ -37,6 +44,9 @@ export const rollVotesTool = tool('congressgov_roll_votes', {
|
|
|
37
44
|
enrichment: listEnrichment,
|
|
38
45
|
format: formatVotes,
|
|
39
46
|
async handler(input, ctx) {
|
|
47
|
+
if (input.chamber === 'senate') {
|
|
48
|
+
return handleSenateVotes(input, ctx);
|
|
49
|
+
}
|
|
40
50
|
const api = getCongressApi();
|
|
41
51
|
if (input.operation === 'list') {
|
|
42
52
|
const effectiveQuery = buildEffectiveQuery('roll call votes', {
|
|
@@ -93,6 +103,57 @@ export const rollVotesTool = tool('congressgov_roll_votes', {
|
|
|
93
103
|
return result;
|
|
94
104
|
},
|
|
95
105
|
});
|
|
106
|
+
/**
|
|
107
|
+
* Senate branch of `congressgov_roll_votes`. Mirrors the House operation surface
|
|
108
|
+
* (`list` / `get` / `members`) but sources data from the Senate LIS XML feed via
|
|
109
|
+
* `SenateVoteService`. The feed serves a whole session's menu in one file and each
|
|
110
|
+
* vote's roster inline, so pagination is client-side (handled in the service).
|
|
111
|
+
*/
|
|
112
|
+
async function handleSenateVotes(input, ctx) {
|
|
113
|
+
const senate = getSenateVoteService();
|
|
114
|
+
if (input.operation === 'list') {
|
|
115
|
+
const result = await senate.listVotes({
|
|
116
|
+
congress: input.congress,
|
|
117
|
+
session: input.session,
|
|
118
|
+
order: input.order,
|
|
119
|
+
limit: input.limit,
|
|
120
|
+
offset: input.offset,
|
|
121
|
+
}, ctx);
|
|
122
|
+
ctx.log.info('Senate votes listed', { congress: input.congress, session: input.session });
|
|
123
|
+
ctx.enrich.echo(buildEffectiveQuery('Senate roll call votes', {
|
|
124
|
+
congress: input.congress,
|
|
125
|
+
session: input.session,
|
|
126
|
+
}));
|
|
127
|
+
ctx.enrich.total(result.pagination.count);
|
|
128
|
+
if (result.data.length === 0) {
|
|
129
|
+
ctx.enrich.notice('No Senate votes found. Verify the congress and session — the Senate publishes roll call votes from the 101st Congress (1989) onward.');
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
if (!input.voteNumber) {
|
|
134
|
+
throw validationError(`The '${input.operation}' operation requires voteNumber. Use 'list' to browse available votes.`, { field: 'voteNumber', operation: input.operation });
|
|
135
|
+
}
|
|
136
|
+
const voteParams = {
|
|
137
|
+
congress: input.congress,
|
|
138
|
+
session: input.session,
|
|
139
|
+
voteNumber: input.voteNumber,
|
|
140
|
+
};
|
|
141
|
+
if (input.operation === 'members') {
|
|
142
|
+
const result = await senate.getVoteMembers({ ...voteParams, limit: input.limit, offset: input.offset }, ctx);
|
|
143
|
+
ctx.log.info('Senate vote retrieved', { ...voteParams, operation: input.operation });
|
|
144
|
+
ctx.enrich.echo(`member votes for Senate roll ${input.voteNumber} in the ${input.congress}th Congress, session ${input.session}`);
|
|
145
|
+
ctx.enrich.total(result.pagination.count);
|
|
146
|
+
if (result.data.length === 0) {
|
|
147
|
+
ctx.enrich.notice(`No member vote records found for Senate roll ${input.voteNumber}.`);
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
const result = await senate.getVote(voteParams, ctx);
|
|
152
|
+
ctx.log.info('Senate vote retrieved', { ...voteParams, operation: input.operation });
|
|
153
|
+
ctx.enrich.echo(`Senate roll call ${input.voteNumber} in the ${input.congress}th Congress, session ${input.session}`);
|
|
154
|
+
ctx.enrich.total(1);
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
96
157
|
/**
|
|
97
158
|
* Fetch roll call votes in strict newest-first order. The /house-vote/{c}/{s}
|
|
98
159
|
* endpoint returns rows in opaque insertion order (loosely correlated with roll
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roll-votes.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/roll-votes.tool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"roll-votes.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/roll-votes.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,7 +30,11 @@ export declare function formatCrsReports(result: Record<string, unknown>): TextB
|
|
|
30
30
|
export declare function formatDailyRecord(result: Record<string, unknown>): TextBlock[];
|
|
31
31
|
/** Enacted public and private laws. Upstream /law mirrors /bill, so reuse bill formatters. */
|
|
32
32
|
export declare const formatLaws: (result: Record<string, unknown>) => TextBlock[];
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Roll call votes and member voting positions for both chambers. House payloads
|
|
35
|
+
* come from the Congress.gov JSON API; Senate payloads from the LIS XML feed and
|
|
36
|
+
* carry a `chamber: 'senate'` marker — dispatch to the matching renderer set.
|
|
37
|
+
*/
|
|
34
38
|
export declare function formatVotes(result: Record<string, unknown>): TextBlock[];
|
|
35
39
|
/** Presidential nominations and Senate confirmation pipeline. */
|
|
36
40
|
export declare function formatNominations(result: Record<string, unknown>): TextBlock[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-helpers.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/format-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"format-helpers.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/format-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAi3ChD,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAUxE;AAqCD,2DAA2D;AAC3D,eAAO,MAAM,eAAe,WAlEhB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,SAAS,EAkEkB,CAAC;AAEpE,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAoB1E;AAWD,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAkB7E;AAED,kDAAkD;AAClD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CASnF;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAK7E;AAED,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAY9E;AAED,8FAA8F;AAC9F,eAAO,MAAM,UAAU,WA7JX,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,SAAS,EA6JiC,CAAC;AAEnF;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAcxE;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAa9E"}
|
|
@@ -887,6 +887,171 @@ function renderVoteMembers(result) {
|
|
|
887
887
|
}
|
|
888
888
|
return lines.join('\n');
|
|
889
889
|
}
|
|
890
|
+
// ── Senate roll call votes (LIS feed) ───────────────────────────────
|
|
891
|
+
/**
|
|
892
|
+
* Senate vote payloads come from the LIS XML feed, not the Congress.gov JSON API,
|
|
893
|
+
* so they carry a distinct field set (and a `chamber: 'senate'` marker). These
|
|
894
|
+
* renderers handle that shape; `formatVotes` routes to them via `isSenateResult`.
|
|
895
|
+
*/
|
|
896
|
+
/** Senate vote list row (from the session menu). */
|
|
897
|
+
function renderSenateVoteItem(item, i) {
|
|
898
|
+
const num = s(item, 'voteNumber');
|
|
899
|
+
const issue = s(item, 'issue');
|
|
900
|
+
const result = s(item, 'result');
|
|
901
|
+
const question = s(item, 'question');
|
|
902
|
+
const measure = s(item, 'measure');
|
|
903
|
+
const left = num ? `Vote ${num}` : 'Senate vote';
|
|
904
|
+
const headingLeft = issue ? `${left}: ${issue}` : left;
|
|
905
|
+
const heading = result ? `${headingLeft} — ${result}` : headingLeft;
|
|
906
|
+
const lines = [`### ${i + 1}. ${heading}`];
|
|
907
|
+
if (question)
|
|
908
|
+
lines.push(`**Question:** ${measure ? `${question} (${measure})` : question}`);
|
|
909
|
+
const meta = join([
|
|
910
|
+
f('Date', s(item, 'voteDate')),
|
|
911
|
+
f('Yeas', s(item, 'yeas')),
|
|
912
|
+
f('Nays', s(item, 'nays')),
|
|
913
|
+
]);
|
|
914
|
+
if (meta)
|
|
915
|
+
lines.push(meta);
|
|
916
|
+
const title = s(item, 'title');
|
|
917
|
+
if (title)
|
|
918
|
+
lines.push(title);
|
|
919
|
+
return lines.join('\n');
|
|
920
|
+
}
|
|
921
|
+
/** One Senate member's position — uses the feed's pre-formatted "Baldwin (D-WI)" label. */
|
|
922
|
+
function renderSenateMemberRow(r) {
|
|
923
|
+
const cast = s(r, 'voteCast');
|
|
924
|
+
const full = s(r, 'memberFull');
|
|
925
|
+
if (full)
|
|
926
|
+
return `- ${full}${cast ? ` → ${cast}` : ''}`;
|
|
927
|
+
const first = s(r, 'firstName');
|
|
928
|
+
const last = s(r, 'lastName');
|
|
929
|
+
const name = first && last ? `${first} ${last}` : (last ?? first ?? s(r, 'lisMemberId') ?? '?');
|
|
930
|
+
const party = s(r, 'party');
|
|
931
|
+
const state = s(r, 'state');
|
|
932
|
+
const loc = party && state
|
|
933
|
+
? `(${party}-${state})`
|
|
934
|
+
: party
|
|
935
|
+
? `(${party})`
|
|
936
|
+
: state
|
|
937
|
+
? `(${state})`
|
|
938
|
+
: undefined;
|
|
939
|
+
return `- ${[name, loc, cast ? `→ ${cast}` : undefined].filter(Boolean).join(' ')}`;
|
|
940
|
+
}
|
|
941
|
+
/** Senate vote detail — question, result, tally, derived party totals, document/amendment. */
|
|
942
|
+
function renderSenateVoteDetail(item) {
|
|
943
|
+
const num = s(item, 'voteNumber');
|
|
944
|
+
const resultText = s(item, 'voteResultText') ?? s(item, 'voteResult');
|
|
945
|
+
const headingLeft = num ? `Senate Vote ${num}` : 'Senate roll call';
|
|
946
|
+
const heading = resultText ? `${headingLeft} — ${resultText}` : headingLeft;
|
|
947
|
+
const lines = [`# ${heading}`];
|
|
948
|
+
const questionText = s(item, 'voteQuestionText') ?? s(item, 'question');
|
|
949
|
+
if (questionText)
|
|
950
|
+
lines.push(`**Question:** ${questionText}`);
|
|
951
|
+
const voteTitle = s(item, 'voteTitle');
|
|
952
|
+
if (voteTitle)
|
|
953
|
+
lines.push(`**Title:** ${voteTitle}`);
|
|
954
|
+
const meta = join([
|
|
955
|
+
f('Congress', s(item, 'congress')),
|
|
956
|
+
f('Session', s(item, 'session')),
|
|
957
|
+
f('Date', s(item, 'voteDate')),
|
|
958
|
+
f('Majority Required', s(item, 'majorityRequirement')),
|
|
959
|
+
]);
|
|
960
|
+
if (meta)
|
|
961
|
+
lines.push(meta);
|
|
962
|
+
const count = item.count;
|
|
963
|
+
if (count) {
|
|
964
|
+
lines.push(`\n**Tally:** ${join([
|
|
965
|
+
`Yea ${s(count, 'yeas') ?? 0}`,
|
|
966
|
+
`Nay ${s(count, 'nays') ?? 0}`,
|
|
967
|
+
`Present ${s(count, 'present') ?? 0}`,
|
|
968
|
+
`Not Voting ${s(count, 'absent') ?? 0}`,
|
|
969
|
+
], ' · ')}`);
|
|
970
|
+
}
|
|
971
|
+
const totals = item.partyTotals;
|
|
972
|
+
if (Array.isArray(totals) && totals.length > 0) {
|
|
973
|
+
lines.push('\n**Party Totals** _(derived from the roster)_:');
|
|
974
|
+
for (const t of totals) {
|
|
975
|
+
const party = s(t, 'party') ?? '?';
|
|
976
|
+
lines.push(`- **${party}:** Yea ${s(t, 'yea') ?? 0}, Nay ${s(t, 'nay') ?? 0}, Present ${s(t, 'present') ?? 0}, Not Voting ${s(t, 'notVoting') ?? 0}`);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
const doc = item.document;
|
|
980
|
+
const docTitle = doc ? (s(doc, 'title') ?? s(doc, 'shortTitle')) : undefined;
|
|
981
|
+
if (doc) {
|
|
982
|
+
const parts = [s(doc, 'type'), s(doc, 'name') ?? s(doc, 'number'), docTitle].filter(Boolean);
|
|
983
|
+
if (parts.length)
|
|
984
|
+
lines.push(`\n**Document:** ${parts.join(' — ')}`);
|
|
985
|
+
}
|
|
986
|
+
const amd = item.amendment;
|
|
987
|
+
let amendmentPurpose;
|
|
988
|
+
if (amd) {
|
|
989
|
+
const amdNum = s(amd, 'number');
|
|
990
|
+
const to = s(amd, 'toDocumentNumber');
|
|
991
|
+
amendmentPurpose = s(amd, 'purpose');
|
|
992
|
+
const head = [amdNum, to ? `to ${to}` : undefined].filter(Boolean).join(' ');
|
|
993
|
+
if (head)
|
|
994
|
+
lines.push(`\n**Amendment:** ${head}`);
|
|
995
|
+
if (amendmentPurpose)
|
|
996
|
+
lines.push(`**Purpose:** ${amendmentPurpose}`);
|
|
997
|
+
}
|
|
998
|
+
/** Surface the matter narrative only when it adds something the document title and
|
|
999
|
+
* amendment purpose haven't already shown. */
|
|
1000
|
+
const docText = s(item, 'voteDocumentText');
|
|
1001
|
+
if (docText && docText !== amendmentPurpose && docText !== docTitle)
|
|
1002
|
+
lines.push(`\n${docText}`);
|
|
1003
|
+
return lines.join('\n');
|
|
1004
|
+
}
|
|
1005
|
+
/** Senate member voting positions for one roll call — mirrors the House members view. */
|
|
1006
|
+
function renderSenateVoteMembers(result) {
|
|
1007
|
+
const vote = (result.vote ?? {});
|
|
1008
|
+
const rows = (result.data ?? []);
|
|
1009
|
+
const pagination = result.pagination;
|
|
1010
|
+
const total = pagination?.count ?? rows.length;
|
|
1011
|
+
const nextOffset = pagination?.nextOffset;
|
|
1012
|
+
const num = s(vote, 'voteNumber');
|
|
1013
|
+
const congress = s(vote, 'congress');
|
|
1014
|
+
const session = s(vote, 'session');
|
|
1015
|
+
const label = num ? `Senate Vote ${num}` : 'Senate roll call';
|
|
1016
|
+
const scope = join([congress ? `${congress}th Congress` : undefined, session ? `session ${session}` : undefined], ', ');
|
|
1017
|
+
const lines = [`# ${scope ? `${label} — ${scope}` : label}`];
|
|
1018
|
+
const context = join([
|
|
1019
|
+
s(vote, 'voteQuestionText')
|
|
1020
|
+
? `**${s(vote, 'voteQuestionText')}**`
|
|
1021
|
+
: s(vote, 'question')
|
|
1022
|
+
? `**${s(vote, 'question')}**`
|
|
1023
|
+
: undefined,
|
|
1024
|
+
s(vote, 'voteResultText') ?? s(vote, 'voteResult'),
|
|
1025
|
+
], ' — ');
|
|
1026
|
+
if (context)
|
|
1027
|
+
lines.push(context);
|
|
1028
|
+
if (rows.length === 0) {
|
|
1029
|
+
lines.push('', total > 0
|
|
1030
|
+
? `_Page is empty — offset is past the end of ${total} member position${total !== 1 ? 's' : ''}._`
|
|
1031
|
+
: '_No member positions recorded for this roll call._');
|
|
1032
|
+
return lines.join('\n');
|
|
1033
|
+
}
|
|
1034
|
+
const end = nextOffset ?? total;
|
|
1035
|
+
const start = end - rows.length + 1;
|
|
1036
|
+
lines.push('', `**Members ${start}–${end} of ${total}**${nextOffset != null ? ` · next offset: ${nextOffset}` : ''}`, '');
|
|
1037
|
+
for (const r of rows) {
|
|
1038
|
+
if (typeof r === 'object' && r !== null)
|
|
1039
|
+
lines.push(renderSenateMemberRow(r));
|
|
1040
|
+
}
|
|
1041
|
+
return lines.join('\n');
|
|
1042
|
+
}
|
|
1043
|
+
/** Senate payloads carry a `chamber: 'senate'` marker on the envelope, vote, and items. */
|
|
1044
|
+
function isSenateResult(result) {
|
|
1045
|
+
if (result.chamber === 'senate')
|
|
1046
|
+
return true;
|
|
1047
|
+
const vote = result.vote;
|
|
1048
|
+
if (vote?.chamber === 'senate')
|
|
1049
|
+
return true;
|
|
1050
|
+
const first = Array.isArray(result.data) ? result.data[0] : undefined;
|
|
1051
|
+
return !!(first &&
|
|
1052
|
+
typeof first === 'object' &&
|
|
1053
|
+
first.chamber === 'senate');
|
|
1054
|
+
}
|
|
890
1055
|
/** Bill / law detail — title-first header, then the rest of the structured fields. */
|
|
891
1056
|
function renderBillDetail(item) {
|
|
892
1057
|
const type = s(item, 'type')?.toUpperCase() ?? '';
|
|
@@ -1256,15 +1421,22 @@ export function formatDailyRecord(result) {
|
|
|
1256
1421
|
}
|
|
1257
1422
|
/** Enacted public and private laws. Upstream /law mirrors /bill, so reuse bill formatters. */
|
|
1258
1423
|
export const formatLaws = makeFormatter(['law'], renderBillItem, renderBillDetail);
|
|
1259
|
-
/**
|
|
1424
|
+
/**
|
|
1425
|
+
* Roll call votes and member voting positions for both chambers. House payloads
|
|
1426
|
+
* come from the Congress.gov JSON API; Senate payloads from the LIS XML feed and
|
|
1427
|
+
* carry a `chamber: 'senate'` marker — dispatch to the matching renderer set.
|
|
1428
|
+
*/
|
|
1260
1429
|
export function formatVotes(result) {
|
|
1430
|
+
const senate = isSenateResult(result);
|
|
1261
1431
|
/** `members`: roster in `data[]` with the vote record as a sibling context object. */
|
|
1262
1432
|
if (Array.isArray(result.data) && result.vote != null)
|
|
1263
|
-
return tb(renderVoteMembers(result));
|
|
1433
|
+
return tb(senate ? renderSenateVoteMembers(result) : renderVoteMembers(result));
|
|
1264
1434
|
if (Array.isArray(result.data))
|
|
1265
|
-
return tb(renderList(result, renderRollVoteItem));
|
|
1435
|
+
return tb(renderList(result, senate ? renderSenateVoteItem : renderRollVoteItem));
|
|
1266
1436
|
if (result.vote != null)
|
|
1267
|
-
return tb(
|
|
1437
|
+
return tb(senate
|
|
1438
|
+
? renderSenateVoteDetail(result.vote)
|
|
1439
|
+
: renderRollVoteDetail(result.vote));
|
|
1268
1440
|
return tb(renderDetail(result));
|
|
1269
1441
|
}
|
|
1270
1442
|
/** Presidential nominations and Senate confirmation pipeline. */
|