@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # Agent Protocol
2
2
 
3
3
  **Server:** congressgov-mcp-server
4
- **Version:** 0.3.25
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
- ## Service
137
+ ## Services
134
138
 
135
- Single service: `CongressApiService`. Wraps the Congress.gov REST API v3.
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
- **Key concerns:**
138
- - API key via `?api_key=` query param (never logged)
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.25
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
- ## Service
137
+ ## Services
134
138
 
135
- Single service: `CongressApiService`. Wraps the Congress.gov REST API v3.
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
- **Key concerns:**
138
- - API key via `?api_key=` query param (never logged)
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
- [![Version](https://img.shields.io/badge/Version-0.3.25-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.3.26-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
 
@@ -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 vote data and individual member voting positions |
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 vote data and individual member voting positions.
81
+ Retrieve House and Senate roll call votes and individual member voting positions.
82
82
 
83
- - Browse roll call votes by congress and session
84
- - Retrieve individual member voting positions per roll call
85
- - `list` defaults to `order='recent'` (newest update-date first); pass `order='oldest'` for ascending
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, House 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.`,
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":"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"}
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 voting positions.
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;;;GAGG;AAGH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAYjD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgHxB,CAAC"}
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 voting positions.
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 House roll call vote data and individual member voting positions House-only, as Senate vote data is not yet in the Congress.gov API. Use 'list' to find votes by congress and session (defaults to most-recently-updated first), 'get' for vote details (question, result, associated bill), or 'members' for how each representative voted.`,
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', by vote update date. 'recent' (default) returns newest first; 'oldest' returns ascending. With 'recent', offset=0 always returns the strictly newest page. Ignored by 'get' and 'members'."),
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":"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"}
1
+ {"version":3,"file":"roll-votes.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/roll-votes.tool.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,YAAY,GACb,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAEpF,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,wBAAwB,EAAE;IAC1D,WAAW,EAAE,wbAAwb;IACrc,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IAC9E,MAAM,EAAE,sBAAsB;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACjF,OAAO,EAAE,CAAC;aACP,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;aACzB,OAAO,CAAC,OAAO,CAAC;aAChB,QAAQ,CACP,sNAAsN,CACvN;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAClE,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,CAAC,yEAAyE,CAAC;QACtF,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,GAAG,EAAE;aACL,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,CAAC;QACvE,KAAK,EAAE,CAAC;aACL,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;aAC1B,OAAO,CAAC,QAAQ,CAAC;aACjB,QAAQ,CACP,kQAAkQ,CACnQ;QACH,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACzF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;KAC1E,CAAC;IACF,MAAM,EAAE,YAAY,CAClB,MAAM,EACN,4GAA4G,CAC7G;IACD,UAAU,EAAE,cAAc;IAC1B,MAAM,EAAE,WAAW;IAEnB,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,IAAI,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;QAE7B,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;YAC/B,MAAM,cAAc,GAAG,mBAAmB,CAAC,iBAAiB,EAAE;gBAC5D,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC,CAAC;YACH,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,MAAM,gBAAgB,CACnC;oBACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;iBACrB,EACD,GAAG,CACJ,CAAC;gBACF,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAChC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;gBAC1C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAC1B,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,0DAA0D,CAAC,CAAC;gBAChF,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,CAChC;gBACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,EACD,GAAG,CACJ,CAAC;YACF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACnF,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAChC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC1C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAC1B,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,0DAA0D,CAAC,CAAC;YAChF,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,MAAM,eAAe,CACnB,QAAQ,KAAK,CAAC,SAAS,wEAAwE,EAC/F,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CACpD,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG;YACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC;QAEF,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAClC,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,cAAc,CAC5C,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAC3D,GAAG,CACJ,CAAC;YACF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;YAC9E,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,yBAAyB,KAAK,CAAC,UAAU,WAAW,KAAK,CAAC,QAAQ,wBAAwB,KAAK,CAAC,OAAO,EAAE,CAC1G,CAAC;YACF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBACjC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,yCAAyC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;YAClF,OAAO,aAAa,CAAC;QACvB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAClD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9E,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,aAAa,KAAK,CAAC,UAAU,WAAW,KAAK,CAAC,QAAQ,wBAAwB,KAAK,CAAC,OAAO,EAAE,CAC9F,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC,CAAC;AAYH;;;;;GAKG;AACH,KAAK,UAAU,iBAAiB,CAAC,KAAsB,EAAE,GAAY;IACnE,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IAEtC,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CACnC;YACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,KAAK,CAAC,MAAM;SACrB,EACD,GAAG,CACJ,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1F,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,mBAAmB,CAAC,wBAAwB,EAAE;YAC5C,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,CAAC,MAAM,CACf,sIAAsI,CACvI,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,eAAe,CACnB,QAAQ,KAAK,CAAC,SAAS,wEAAwE,EAC/F,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CACpD,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG;QACjB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC;IAEF,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CACxC,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAC3D,GAAG,CACJ,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;QACrF,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,gCAAgC,KAAK,CAAC,UAAU,WAAW,KAAK,CAAC,QAAQ,wBAAwB,KAAK,CAAC,OAAO,EAAE,CACjH,CAAC;QACF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,gDAAgD,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,GAAG,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;IACrF,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,oBAAoB,KAAK,CAAC,UAAU,WAAW,KAAK,CAAC,QAAQ,wBAAwB,KAAK,CAAC,OAAO,EAAE,CACrG,CAAC;IACF,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,KAAK,UAAU,gBAAgB,CAC7B,MAA4E,EAC5E,GAAY;IAEZ,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,GAAG,CAAC;IACtB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAC/B,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,EACnF,GAAG,CACJ,CAAC;IACF,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;IACrC,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;IACtE,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC9C,GAAG,CAAC,SAAS,CACX;QACE,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS;KAC5B,EACD,GAAG,CACJ,CACF,CACF,CAAC;IACF,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAE7D,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChB,MAAM,EAAE,GAAI,CAA6B,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3D,MAAM,EAAE,GAAI,CAA6B,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3D,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACrE,MAAM,UAAU,GACd,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,qCAAqC,EAAE;QAClD,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,GAAG,CAAC,MAAM;QACjB,QAAQ,EAAE,KAAK,CAAC,MAAM;QACtB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,gBAAgB,EAAE,CAAC,GAAG,cAAc;KACrC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC;AAClF,CAAC"}
@@ -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
- /** House roll call votes and member voting positions. */
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;AA0qChD,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,yDAAyD;AACzD,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAMxE;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,CAa9E"}
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
- /** House roll call votes and member voting positions. */
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(renderRollVoteDetail(result.vote));
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. */