uk-parliament-mcp 1.1.0__py3-none-any.whl

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.
@@ -0,0 +1,385 @@
1
+ """Bills API tools for legislation, amendments, and stages."""
2
+
3
+ from urllib.parse import quote
4
+
5
+ from mcp.server.fastmcp import FastMCP
6
+
7
+ from uk_parliament_mcp.config import BILLS_API_BASE
8
+ from uk_parliament_mcp.http_client import build_url, get_result
9
+
10
+
11
+ def register_tools(mcp: FastMCP) -> None:
12
+ """Register bills tools with the MCP server."""
13
+
14
+ @mcp.tool()
15
+ async def get_recently_updated_bills(take: int = 10) -> str:
16
+ """Get most recently updated bills and current legislative activity | recent bills, new legislation, latest laws, parliamentary bills, legislative updates, current proposals | Use for tracking new legislation, monitoring bill progress, or finding recently introduced/updated laws | Returns bill titles, stages, sponsors, dates, and current status | Data freshness: updated frequently
17
+
18
+ Args:
19
+ take: Number of bills to return. Default: 10, recommended max: 50. Higher numbers may slow response.
20
+
21
+ Returns:
22
+ Bill titles, stages, sponsors, dates, and current status.
23
+ """
24
+ url = f"{BILLS_API_BASE}/Bills?SortOrder=DateUpdatedDescending&skip=0&take={take}"
25
+ return await get_result(url)
26
+
27
+ @mcp.tool()
28
+ async def search_bills(
29
+ search_term: str,
30
+ member_id: int | None = None,
31
+ ) -> str:
32
+ """Search for parliamentary bills by title, subject, or keyword. Use when researching proposed legislation, finding bills on specific topics, or tracking legislative progress.
33
+
34
+ Args:
35
+ search_term: Search term for bill titles or content (e.g. 'environment', 'health', 'finance').
36
+ member_id: Optional: member ID to filter bills sponsored by specific member.
37
+
38
+ Returns:
39
+ Matching bills with titles, stages, and sponsors.
40
+ """
41
+ url = f"{BILLS_API_BASE}/Bills?SearchTerm={quote(search_term)}"
42
+ return await get_result(url)
43
+
44
+ @mcp.tool()
45
+ async def bill_types() -> str:
46
+ """Get all types of bills that can be introduced in Parliament (e.g., Government Bill, Private Member's Bill). Use when you need to understand different categories of legislation.
47
+
48
+ Returns:
49
+ All bill types with descriptions.
50
+ """
51
+ url = f"{BILLS_API_BASE}/BillTypes"
52
+ return await get_result(url)
53
+
54
+ @mcp.tool()
55
+ async def bill_stages() -> str:
56
+ """Get all possible stages a bill can go through in its legislative journey. Use when tracking bill progress or understanding the legislative process (e.g., First Reading, Committee Stage, Royal Assent).
57
+
58
+ Returns:
59
+ All bill stages with descriptions.
60
+ """
61
+ url = f"{BILLS_API_BASE}/Stages"
62
+ return await get_result(url)
63
+
64
+ @mcp.tool()
65
+ async def get_bill_by_id(bill_id: int) -> str:
66
+ """Get detailed information about a specific bill by ID. Use when you need comprehensive bill details including title, sponsors, stages, summary, and current status.
67
+
68
+ Args:
69
+ bill_id: Unique bill ID number.
70
+
71
+ Returns:
72
+ Comprehensive bill details.
73
+ """
74
+ url = f"{BILLS_API_BASE}/Bills/{bill_id}"
75
+ return await get_result(url)
76
+
77
+ @mcp.tool()
78
+ async def get_bill_stages(
79
+ bill_id: int,
80
+ skip: int | None = None,
81
+ take: int | None = None,
82
+ ) -> str:
83
+ """Get all stages of a specific bill by bill ID. Use when tracking a bill's progress through Parliament, understanding its legislative journey, or finding specific stages like Committee Stage or Third Reading.
84
+
85
+ Args:
86
+ bill_id: Bill ID to get stages for.
87
+ skip: Optional: number of records to skip (for pagination).
88
+ take: Optional: number of records to return.
89
+
90
+ Returns:
91
+ All stages for the specified bill.
92
+ """
93
+ url = build_url(
94
+ f"{BILLS_API_BASE}/Bills/{bill_id}/Stages",
95
+ {"Skip": skip, "Take": take},
96
+ )
97
+ return await get_result(url)
98
+
99
+ @mcp.tool()
100
+ async def get_bill_stage_details(bill_id: int, bill_stage_id: int) -> str:
101
+ """Get detailed information about a specific stage of a bill. Use when you need complete details about a particular stage including timings, committee involvement, and related activities.
102
+
103
+ Args:
104
+ bill_id: Bill ID.
105
+ bill_stage_id: Bill stage ID to get details for.
106
+
107
+ Returns:
108
+ Detailed information about the bill stage.
109
+ """
110
+ url = f"{BILLS_API_BASE}/Bills/{bill_id}/Stages/{bill_stage_id}"
111
+ return await get_result(url)
112
+
113
+ @mcp.tool()
114
+ async def get_bill_stage_amendments(
115
+ bill_id: int,
116
+ bill_stage_id: int,
117
+ search_term: str | None = None,
118
+ amendment_number: str | None = None,
119
+ decision: str | None = None,
120
+ member_id: int | None = None,
121
+ skip: int | None = None,
122
+ take: int | None = None,
123
+ ) -> str:
124
+ """Get all amendments for a specific bill stage. Use when researching proposed changes to legislation, tracking amendment activity, or understanding what modifications are being suggested to a bill.
125
+
126
+ Args:
127
+ bill_id: Bill ID.
128
+ bill_stage_id: Bill stage ID to get amendments for.
129
+ search_term: Optional: search term for amendment content.
130
+ amendment_number: Optional: specific amendment number.
131
+ decision: Optional: amendment decision status.
132
+ member_id: Optional: member ID who proposed amendment.
133
+ skip: Optional: number of records to skip (for pagination).
134
+ take: Optional: number of records to return.
135
+
136
+ Returns:
137
+ Amendments for the specified bill stage.
138
+ """
139
+ url = build_url(
140
+ f"{BILLS_API_BASE}/Bills/{bill_id}/Stages/{bill_stage_id}/Amendments",
141
+ {
142
+ "SearchTerm": search_term,
143
+ "AmendmentNumber": amendment_number,
144
+ "Decision": decision,
145
+ "MemberId": member_id,
146
+ "Skip": skip,
147
+ "Take": take,
148
+ },
149
+ )
150
+ return await get_result(url)
151
+
152
+ @mcp.tool()
153
+ async def get_amendment_by_id(
154
+ bill_id: int,
155
+ bill_stage_id: int,
156
+ amendment_id: int,
157
+ ) -> str:
158
+ """Get detailed information about a specific amendment. Use when you need complete amendment details including text, sponsors, decision, and explanatory notes.
159
+
160
+ Args:
161
+ bill_id: Bill ID.
162
+ bill_stage_id: Bill stage ID.
163
+ amendment_id: Amendment ID to get details for.
164
+
165
+ Returns:
166
+ Detailed information about the amendment.
167
+ """
168
+ url = f"{BILLS_API_BASE}/Bills/{bill_id}/Stages/{bill_stage_id}/Amendments/{amendment_id}"
169
+ return await get_result(url)
170
+
171
+ @mcp.tool()
172
+ async def get_bill_stage_ping_pong_items(
173
+ bill_id: int,
174
+ bill_stage_id: int,
175
+ search_term: str | None = None,
176
+ amendment_number: str | None = None,
177
+ decision: str | None = None,
178
+ member_id: int | None = None,
179
+ skip: int | None = None,
180
+ take: int | None = None,
181
+ ) -> str:
182
+ """Get ping pong items (amendments and motions) for a bill stage. Use when researching the final stages of bills passing between Commons and Lords, including disagreements and agreements on amendments.
183
+
184
+ Args:
185
+ bill_id: Bill ID.
186
+ bill_stage_id: Bill stage ID to get ping pong items for.
187
+ search_term: Optional: search term for ping pong item content.
188
+ amendment_number: Optional: specific amendment number.
189
+ decision: Optional: ping pong item decision status.
190
+ member_id: Optional: member ID who proposed item.
191
+ skip: Optional: number of records to skip (for pagination).
192
+ take: Optional: number of records to return.
193
+
194
+ Returns:
195
+ Ping pong items for the specified bill stage.
196
+ """
197
+ url = build_url(
198
+ f"{BILLS_API_BASE}/Bills/{bill_id}/Stages/{bill_stage_id}/PingPongItems",
199
+ {
200
+ "SearchTerm": search_term,
201
+ "AmendmentNumber": amendment_number,
202
+ "Decision": decision,
203
+ "MemberId": member_id,
204
+ "Skip": skip,
205
+ "Take": take,
206
+ },
207
+ )
208
+ return await get_result(url)
209
+
210
+ @mcp.tool()
211
+ async def get_ping_pong_item_by_id(
212
+ bill_id: int,
213
+ bill_stage_id: int,
214
+ ping_pong_item_id: int,
215
+ ) -> str:
216
+ """Get detailed information about a specific ping pong item (amendment or motion). Use when you need complete details about final stage amendments or motions in the legislative process.
217
+
218
+ Args:
219
+ bill_id: Bill ID.
220
+ bill_stage_id: Bill stage ID.
221
+ ping_pong_item_id: Ping pong item ID to get details for.
222
+
223
+ Returns:
224
+ Detailed information about the ping pong item.
225
+ """
226
+ url = f"{BILLS_API_BASE}/Bills/{bill_id}/Stages/{bill_stage_id}/PingPongItems/{ping_pong_item_id}"
227
+ return await get_result(url)
228
+
229
+ @mcp.tool()
230
+ async def get_bill_publications(bill_id: int) -> str:
231
+ """Get all publications for a specific bill. Use when researching bill documents, impact assessments, explanatory notes, or tracking document versions throughout the legislative process.
232
+
233
+ Args:
234
+ bill_id: Bill ID to get publications for.
235
+
236
+ Returns:
237
+ Publications for the specified bill.
238
+ """
239
+ url = f"{BILLS_API_BASE}/Bills/{bill_id}/Publications"
240
+ return await get_result(url)
241
+
242
+ @mcp.tool()
243
+ async def get_bill_stage_publications(bill_id: int, stage_id: int) -> str:
244
+ """Get publications for a specific bill stage. Use when you need documents related to a particular stage of legislation, such as committee reports or stage-specific amendments.
245
+
246
+ Args:
247
+ bill_id: Bill ID.
248
+ stage_id: Stage ID to get publications for.
249
+
250
+ Returns:
251
+ Publications for the specified bill stage.
252
+ """
253
+ url = f"{BILLS_API_BASE}/Bills/{bill_id}/Stages/{stage_id}/Publications"
254
+ return await get_result(url)
255
+
256
+ @mcp.tool()
257
+ async def get_publication_document(publication_id: int, document_id: int) -> str:
258
+ """Get information about a specific publication document. Use when you need metadata about bill documents including filename, content type, and size.
259
+
260
+ Args:
261
+ publication_id: Publication ID.
262
+ document_id: Document ID to get details for.
263
+
264
+ Returns:
265
+ Metadata about the publication document.
266
+ """
267
+ url = f"{BILLS_API_BASE}/Publications/{publication_id}/Documents/{document_id}"
268
+ return await get_result(url)
269
+
270
+ @mcp.tool()
271
+ async def get_bill_news_articles(
272
+ bill_id: int,
273
+ skip: int | None = None,
274
+ take: int | None = None,
275
+ ) -> str:
276
+ """Get news articles related to a specific bill. Use when researching media coverage, press releases, or official communications about legislation.
277
+
278
+ Args:
279
+ bill_id: Bill ID to get news articles for.
280
+ skip: Optional: number of records to skip (for pagination).
281
+ take: Optional: number of records to return.
282
+
283
+ Returns:
284
+ News articles related to the bill.
285
+ """
286
+ url = build_url(
287
+ f"{BILLS_API_BASE}/Bills/{bill_id}/NewsArticles",
288
+ {"Skip": skip, "Take": take},
289
+ )
290
+ return await get_result(url)
291
+
292
+ @mcp.tool()
293
+ async def get_all_bills_rss() -> str:
294
+ """Get RSS feed of all bills. Use when you want to stay updated on all legislative activity through RSS feeds.
295
+
296
+ Returns:
297
+ RSS feed of all bills.
298
+ """
299
+ url = f"{BILLS_API_BASE}/Rss/allbills.rss"
300
+ return await get_result(url)
301
+
302
+ @mcp.tool()
303
+ async def get_public_bills_rss() -> str:
304
+ """Get RSS feed of public bills only. Use when you want to monitor government and public bills through RSS feeds, excluding private bills.
305
+
306
+ Returns:
307
+ RSS feed of public bills.
308
+ """
309
+ url = f"{BILLS_API_BASE}/Rss/publicbills.rss"
310
+ return await get_result(url)
311
+
312
+ @mcp.tool()
313
+ async def get_private_bills_rss() -> str:
314
+ """Get RSS feed of private bills only. Use when you want to monitor private member bills and private bills through RSS feeds.
315
+
316
+ Returns:
317
+ RSS feed of private bills.
318
+ """
319
+ url = f"{BILLS_API_BASE}/Rss/privatebills.rss"
320
+ return await get_result(url)
321
+
322
+ @mcp.tool()
323
+ async def get_bill_rss(bill_id: int) -> str:
324
+ """Get RSS feed for a specific bill by ID. Use when you want to track updates and changes to a particular piece of legislation through RSS feeds.
325
+
326
+ Args:
327
+ bill_id: Bill ID to get RSS feed for.
328
+
329
+ Returns:
330
+ RSS feed for the specified bill.
331
+ """
332
+ url = f"{BILLS_API_BASE}/Rss/Bills/{bill_id}.rss"
333
+ return await get_result(url)
334
+
335
+ @mcp.tool()
336
+ async def get_publication_types(
337
+ skip: int | None = None,
338
+ take: int | None = None,
339
+ ) -> str:
340
+ """Get all publication types available for bills. Use when you need to understand the different types of documents that can be associated with legislation.
341
+
342
+ Args:
343
+ skip: Optional: number of records to skip (for pagination).
344
+ take: Optional: number of records to return.
345
+
346
+ Returns:
347
+ All publication types with descriptions.
348
+ """
349
+ url = build_url(
350
+ f"{BILLS_API_BASE}/PublicationTypes",
351
+ {"Skip": skip, "Take": take},
352
+ )
353
+ return await get_result(url)
354
+
355
+ @mcp.tool()
356
+ async def get_sittings(
357
+ house: str | None = None,
358
+ date_from: str | None = None,
359
+ date_to: str | None = None,
360
+ skip: int | None = None,
361
+ take: int | None = None,
362
+ ) -> str:
363
+ """Get parliamentary sittings with optional filtering by house and date range. Use when researching when Parliament was in session, finding specific sitting dates, or tracking parliamentary activity.
364
+
365
+ Args:
366
+ house: Optional: house name ('Commons' or 'Lords').
367
+ date_from: Optional: start date in YYYY-MM-DD format.
368
+ date_to: Optional: end date in YYYY-MM-DD format.
369
+ skip: Optional: number of records to skip (for pagination).
370
+ take: Optional: number of records to return.
371
+
372
+ Returns:
373
+ Parliamentary sittings matching the criteria.
374
+ """
375
+ url = build_url(
376
+ f"{BILLS_API_BASE}/Sittings",
377
+ {
378
+ "House": house,
379
+ "DateFrom": date_from,
380
+ "DateTo": date_to,
381
+ "Skip": skip,
382
+ "Take": take,
383
+ },
384
+ )
385
+ return await get_result(url)