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.
- uk_parliament_mcp/__init__.py +3 -0
- uk_parliament_mcp/__main__.py +23 -0
- uk_parliament_mcp/config.py +20 -0
- uk_parliament_mcp/http_client.py +237 -0
- uk_parliament_mcp/server.py +49 -0
- uk_parliament_mcp/tools/__init__.py +1 -0
- uk_parliament_mcp/tools/bills.py +385 -0
- uk_parliament_mcp/tools/committees.py +385 -0
- uk_parliament_mcp/tools/commons_votes.py +138 -0
- uk_parliament_mcp/tools/composite.py +293 -0
- uk_parliament_mcp/tools/core.py +880 -0
- uk_parliament_mcp/tools/erskine_may.py +25 -0
- uk_parliament_mcp/tools/hansard.py +39 -0
- uk_parliament_mcp/tools/interests.py +43 -0
- uk_parliament_mcp/tools/lords_votes.py +149 -0
- uk_parliament_mcp/tools/members.py +439 -0
- uk_parliament_mcp/tools/now.py +30 -0
- uk_parliament_mcp/tools/oral_questions.py +55 -0
- uk_parliament_mcp/tools/statutory_instruments.py +38 -0
- uk_parliament_mcp/tools/treaties.py +25 -0
- uk_parliament_mcp/tools/whatson.py +72 -0
- uk_parliament_mcp/validators.py +58 -0
- uk_parliament_mcp-1.1.0.dist-info/METADATA +408 -0
- uk_parliament_mcp-1.1.0.dist-info/RECORD +26 -0
- uk_parliament_mcp-1.1.0.dist-info/WHEEL +4 -0
- uk_parliament_mcp-1.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,880 @@
|
|
|
1
|
+
"""Core tools for Parliament data assistant session management and guidance."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from mcp.server.fastmcp import FastMCP
|
|
6
|
+
|
|
7
|
+
SYSTEM_PROMPT = """You are a helpful assistant that answers questions using only data from UK Parliament MCP servers.
|
|
8
|
+
When the session begins, introduce yourself with a brief message such as:
|
|
9
|
+
"Hello! I'm a parliamentary data assistant. I can help answer questions using official data from the UK Parliament MCP APIs. Just ask me something, and I'll fetch what I can - and I'll always show you which sources I used."
|
|
10
|
+
When responding to user queries, you must:
|
|
11
|
+
Only retrieve and use data from the MCP API endpoints this server provides.
|
|
12
|
+
Avoid using any external sources or inferred knowledge.
|
|
13
|
+
After every response, append a list of all MCP API URLs used to generate the answer.
|
|
14
|
+
If no relevant data is available via the MCP API, state that clearly and do not attempt to fabricate a response.
|
|
15
|
+
Convert raw data into human-readable summaries while preserving accuracy, but always list the raw URLs used."""
|
|
16
|
+
|
|
17
|
+
GOODBYE_PROMPT = """You are now interacting as a normal assistant. There are no special restrictions or requirements for using UK Parliament MCP data. You may answer questions using any available data or knowledge, and you do not need to append MCP API URLs or limit yourself to MCP sources. Resume normal assistant behavior."""
|
|
18
|
+
|
|
19
|
+
QUICK_REFERENCE = """## Quick Reference: UK Parliament MCP Tools (92 tools)
|
|
20
|
+
|
|
21
|
+
### Composite Tools (Start Here for Common Queries!)
|
|
22
|
+
These tools combine multiple API calls - use them first for efficiency:
|
|
23
|
+
- get_mp_profile(name) - Complete MP profile in one call
|
|
24
|
+
- check_mp_vote(mp_name, topic) - Check how an MP voted on a topic
|
|
25
|
+
- get_bill_overview(search_term) - Full bill info with stages
|
|
26
|
+
- get_committee_summary(topic) - Committee with evidence and publications
|
|
27
|
+
|
|
28
|
+
### Key Conventions
|
|
29
|
+
- House IDs: 1 = Commons, 2 = Lords (for some tools: 'Commons' or 'Lords' as strings)
|
|
30
|
+
- Dates: YYYY-MM-DD format
|
|
31
|
+
- Pagination: skip/take parameters (typical defaults: 20-30)
|
|
32
|
+
- IDs: Use search tools first to get member_id, bill_id, etc.
|
|
33
|
+
|
|
34
|
+
### Tool Categories & Entry Points
|
|
35
|
+
| Module | Tools | Start With |
|
|
36
|
+
|--------|-------|------------|
|
|
37
|
+
| composite | 4 | get_mp_profile(name) |
|
|
38
|
+
| members | 25 | get_member_by_name(name) |
|
|
39
|
+
| bills | 21 | search_bills(search_term) |
|
|
40
|
+
| committees | 12 | search_committees(search_term) |
|
|
41
|
+
| commons_votes | 5 | search_commons_divisions(search_term) |
|
|
42
|
+
| lords_votes | 5 | search_lords_divisions(search_term) |
|
|
43
|
+
| hansard | 1 | search_hansard(house, start_date, end_date, search_term) |
|
|
44
|
+
| oral_questions | 3 | search_early_day_motions(search_term) |
|
|
45
|
+
| interests | 3 | search_roi(member_id) |
|
|
46
|
+
| now | 2 | happening_now_in_commons() |
|
|
47
|
+
| whatson | 3 | search_calendar(house, start_date, end_date) |
|
|
48
|
+
| statutory_instruments | 2 | search_statutory_instruments() |
|
|
49
|
+
| treaties | 1 | search_treaties(search_text) |
|
|
50
|
+
| erskine_may | 1 | search_erskine_may(search_term) |
|
|
51
|
+
|
|
52
|
+
### Common Patterns
|
|
53
|
+
1. Use composite tools first for common queries (saves multiple calls)
|
|
54
|
+
2. For detailed data: Search by name/term -> Get by ID -> Get related data
|
|
55
|
+
3. For MP voting: check_mp_vote() OR get_member_by_name() -> get_commons_voting_record_for_member()
|
|
56
|
+
4. For bill progress: get_bill_overview() OR search_bills() -> get_bill_stages()
|
|
57
|
+
|
|
58
|
+
Use parliament_guide(topic) for detailed tool information.
|
|
59
|
+
Use parliament_workflow(query) for step-by-step research planning."""
|
|
60
|
+
|
|
61
|
+
GUIDANCE_CONTENT = {
|
|
62
|
+
"composite": """## Composite Tools (4 tools)
|
|
63
|
+
|
|
64
|
+
High-level tools that combine multiple API calls for common research tasks.
|
|
65
|
+
Use these FIRST for common queries to reduce tool calls and improve efficiency.
|
|
66
|
+
|
|
67
|
+
### MP/Lord Research
|
|
68
|
+
- get_mp_profile(name) - Complete profile in one call
|
|
69
|
+
- Combines: member search + details + biography + interests + voting
|
|
70
|
+
- Returns: Basic info, biography, registered interests, recent votes
|
|
71
|
+
- Example: get_mp_profile("Keir Starmer")
|
|
72
|
+
|
|
73
|
+
- check_mp_vote(mp_name, topic) - Check voting stance on a topic
|
|
74
|
+
- Combines: member search + division search with member filter
|
|
75
|
+
- Returns: MP info and divisions on the topic where they voted
|
|
76
|
+
- Example: check_mp_vote("Boris Johnson", "climate")
|
|
77
|
+
|
|
78
|
+
### Bill Research
|
|
79
|
+
- get_bill_overview(search_term) - Full bill information
|
|
80
|
+
- Combines: bill search + details + stages + publications
|
|
81
|
+
- Returns: Bill details, legislative stages, associated documents
|
|
82
|
+
- Example: get_bill_overview("Online Safety")
|
|
83
|
+
|
|
84
|
+
### Committee Research
|
|
85
|
+
- get_committee_summary(topic) - Committee with evidence and reports
|
|
86
|
+
- Combines: committee search + details + oral evidence + written evidence + publications
|
|
87
|
+
- Returns: Committee info, witness testimonies, written submissions, reports
|
|
88
|
+
- Example: get_committee_summary("Treasury")
|
|
89
|
+
|
|
90
|
+
### When to Use Individual Tools Instead
|
|
91
|
+
Use the individual tools (in members, bills, etc.) when you need:
|
|
92
|
+
- Specific filtering options not available in composite tools
|
|
93
|
+
- Pagination through large result sets
|
|
94
|
+
- Access to specific endpoints not covered by composite tools
|
|
95
|
+
- More control over which data is fetched""",
|
|
96
|
+
"members": """## Members Tools (25 tools)
|
|
97
|
+
|
|
98
|
+
### Primary Search Tools
|
|
99
|
+
- search_members(name, location, party_id, house, is_current_member, skip, take) - Comprehensive member search with filters
|
|
100
|
+
- get_member_by_name(name) - Simple name search for MPs and Lords
|
|
101
|
+
- search_members_historical(name, date_to_search_for) - Find historical members at a point in time
|
|
102
|
+
|
|
103
|
+
### Member Details (require member_id from search)
|
|
104
|
+
- get_member_by_id(member_id) - Full member profile with party, constituency, status
|
|
105
|
+
- get_members_biography(member_id) - Education, career, background
|
|
106
|
+
- get_members_contact(member_id) - Phone, email, office addresses
|
|
107
|
+
- get_member_synopsis(member_id) - Brief summary
|
|
108
|
+
- get_member_experience(member_id) - Professional background
|
|
109
|
+
- get_member_focus(member_id) - Policy interests and expertise
|
|
110
|
+
|
|
111
|
+
### Member Activity
|
|
112
|
+
- get_member_voting(member_id, house) - Recent voting records (house: 1=Commons, 2=Lords)
|
|
113
|
+
- get_commons_voting_record_for_member(member_id) - All Commons votes by member
|
|
114
|
+
- get_lords_voting_record_for_member(member_id) - All Lords votes by member
|
|
115
|
+
- get_member_written_questions(member_id, skip, take) - Written questions submitted
|
|
116
|
+
- get_contributions(member_id, skip, take) - Speeches, questions, interventions
|
|
117
|
+
- edms_for_member_id(member_id) - Early Day Motions signed/sponsored
|
|
118
|
+
|
|
119
|
+
### Interests & Staff
|
|
120
|
+
- get_member_registered_interests(member_id, house) - Declared financial interests
|
|
121
|
+
- get_member_staff(member_id) - Office staff details
|
|
122
|
+
|
|
123
|
+
### Electoral Data
|
|
124
|
+
- get_member_latest_election_result(member_id) - Last election result
|
|
125
|
+
- get_constituencies(skip, take) - List all constituencies
|
|
126
|
+
- get_election_results_for_constituency(constituency_id, skip, take) - Historical results
|
|
127
|
+
|
|
128
|
+
### Reference Data
|
|
129
|
+
- parties_list_by_house(house) - Active parties (house: 1=Commons, 2=Lords)
|
|
130
|
+
- get_departments() - Government departments
|
|
131
|
+
- get_answering_bodies() - Which dept answers which questions
|
|
132
|
+
|
|
133
|
+
### Typical Workflow
|
|
134
|
+
1. Search: get_member_by_name("Keir Starmer") -> extract member_id
|
|
135
|
+
2. Profile: get_member_by_id(member_id) -> basic info
|
|
136
|
+
3. Details: get_members_biography(member_id) -> background
|
|
137
|
+
4. Activity: get_commons_voting_record_for_member(member_id) -> voting history""",
|
|
138
|
+
"bills": """## Bills Tools (21 tools)
|
|
139
|
+
|
|
140
|
+
### Search & Discovery
|
|
141
|
+
- search_bills(search_term, skip, take) - Find bills by keyword
|
|
142
|
+
- get_recently_updated_bills(take) - Latest legislative activity
|
|
143
|
+
- get_bill_by_id(bill_id) - Full bill details with current stage
|
|
144
|
+
- bill_types() - Types of bills (Public, Private, Hybrid, etc.)
|
|
145
|
+
|
|
146
|
+
### Bill Progress & Stages
|
|
147
|
+
- get_bill_stages(bill_id) - Track legislative journey through Parliament
|
|
148
|
+
- bill_stages() - Stage definitions (1st Reading, 2nd Reading, Committee, etc.)
|
|
149
|
+
- get_bill_stage_sittings(bill_id, stage_id) - When stage was debated
|
|
150
|
+
|
|
151
|
+
### Amendments
|
|
152
|
+
- get_bill_stage_amendments(bill_id, stage_id) - Amendments at specific stage
|
|
153
|
+
- get_amendment_by_id(bill_id, bill_stage_id, amendment_id) - Detailed amendment info
|
|
154
|
+
|
|
155
|
+
### Publications & News
|
|
156
|
+
- get_bill_publications(bill_id) - Associated documents and papers
|
|
157
|
+
- get_publication_types() - Types of parliamentary publications
|
|
158
|
+
- get_bill_news_articles(bill_id) - News articles about the bill
|
|
159
|
+
|
|
160
|
+
### RSS Feeds
|
|
161
|
+
- get_all_bills_rss() - RSS feed of all bills
|
|
162
|
+
- get_public_bills_rss() - RSS feed of public bills
|
|
163
|
+
- get_private_bills_rss() - RSS feed of private bills
|
|
164
|
+
- get_bill_rss(bill_id) - RSS feed for a specific bill
|
|
165
|
+
|
|
166
|
+
### Typical Workflow
|
|
167
|
+
1. Search: search_bills("climate") -> find bill_id
|
|
168
|
+
2. Overview: get_bill_by_id(bill_id) -> current status
|
|
169
|
+
3. Progress: get_bill_stages(bill_id) -> legislative journey
|
|
170
|
+
4. Details: get_bill_stage_amendments(bill_id, stage_id) -> proposed changes""",
|
|
171
|
+
"votes": """## Voting Tools (10 tools: 5 Commons + 5 Lords)
|
|
172
|
+
|
|
173
|
+
### Commons Divisions
|
|
174
|
+
- search_commons_divisions(search_term) - Find Commons votes by keyword
|
|
175
|
+
- get_commons_division_by_id(division_id) - Full voting details with lists
|
|
176
|
+
- get_commons_voting_record_for_member(member_id) - All votes by MP
|
|
177
|
+
- get_commons_divisions_grouped_by_party(search_term, member_id) - Votes grouped by party alignment
|
|
178
|
+
- get_commons_divisions_search_count(search_term) - Count of matching divisions
|
|
179
|
+
|
|
180
|
+
### Lords Divisions
|
|
181
|
+
- search_lords_divisions(search_term) - Find Lords votes by keyword
|
|
182
|
+
- get_lords_division_by_id(division_id) - Full voting details with lists
|
|
183
|
+
- get_lords_voting_record_for_member(member_id) - All votes by Lord
|
|
184
|
+
- get_lords_divisions_grouped_by_party(member_id) - Votes grouped by party alignment
|
|
185
|
+
- get_lords_divisions_search_count(search_term) - Count of matching divisions
|
|
186
|
+
|
|
187
|
+
### Key Concepts
|
|
188
|
+
- Division: A formal recorded vote in Parliament
|
|
189
|
+
- Aye/Content: Voting yes (Commons uses Aye, Lords uses Content)
|
|
190
|
+
- No/Not Content: Voting no (Commons uses No, Lords uses Not Content)
|
|
191
|
+
- Teller: Member who counts votes
|
|
192
|
+
|
|
193
|
+
### Typical Workflow
|
|
194
|
+
1. Find division: search_commons_divisions("Rwanda") -> get division_id
|
|
195
|
+
2. Full results: get_commons_division_by_id(division_id) -> see all votes
|
|
196
|
+
3. Member record: get_commons_voting_record_for_member(member_id) -> voting history""",
|
|
197
|
+
"committees": """## Committee Tools (12 tools)
|
|
198
|
+
|
|
199
|
+
### Search & Discovery
|
|
200
|
+
- search_committees(search_term) - Find committees by topic
|
|
201
|
+
- get_committee_by_id(committee_id) - Full committee details
|
|
202
|
+
- get_committee_types() - Select Committee, Joint Committee, etc.
|
|
203
|
+
|
|
204
|
+
### Meetings & Events
|
|
205
|
+
- get_committee_meetings(from_date, to_date) - Find meetings by date range (YYYY-MM-DD)
|
|
206
|
+
- get_events(...) - Search events with flexible filtering
|
|
207
|
+
- get_event_by_id(event_id) - Specific event details
|
|
208
|
+
- get_committee_events(committee_id, ...) - Events for a specific committee
|
|
209
|
+
|
|
210
|
+
### Members
|
|
211
|
+
- get_committee_members(committee_id) - Current committee members
|
|
212
|
+
|
|
213
|
+
### Evidence & Publications
|
|
214
|
+
- get_oral_evidence(committee_id) - Oral evidence transcripts
|
|
215
|
+
- get_written_evidence(committee_id) - Written submissions
|
|
216
|
+
- get_publications(committee_id) - Reports and documents
|
|
217
|
+
- get_publication_by_id(publication_id) - Specific publication details
|
|
218
|
+
|
|
219
|
+
### Typical Workflow
|
|
220
|
+
1. Search: search_committees("health") -> find committee_id
|
|
221
|
+
2. Details: get_committee_by_id(committee_id) -> scope and membership
|
|
222
|
+
3. Activity: get_committee_meetings("2024-01-01", "2024-12-31") -> recent meetings
|
|
223
|
+
4. Evidence: get_oral_evidence(committee_id=committee_id) -> witness testimonies
|
|
224
|
+
5. Reports: get_publications(committee_id=committee_id) -> published reports""",
|
|
225
|
+
"hansard": """## Hansard Tools (1 tool)
|
|
226
|
+
|
|
227
|
+
### Search
|
|
228
|
+
- search_hansard(search_term, house, skip, take) - Search parliamentary record
|
|
229
|
+
|
|
230
|
+
### About Hansard
|
|
231
|
+
Hansard is the official verbatim record of everything said in Parliament:
|
|
232
|
+
- Debates in the Commons and Lords chambers
|
|
233
|
+
- Questions to ministers
|
|
234
|
+
- Statements and announcements
|
|
235
|
+
- Interventions and points of order
|
|
236
|
+
|
|
237
|
+
### Parameters
|
|
238
|
+
- search_term: Keywords to search for
|
|
239
|
+
- house: 1 = Commons, 2 = Lords (optional)
|
|
240
|
+
- skip/take: Pagination
|
|
241
|
+
|
|
242
|
+
### Tips
|
|
243
|
+
- Search for specific topics, MP names, or phrases
|
|
244
|
+
- Results include date, speaker, and context
|
|
245
|
+
- Use date ranges to narrow results
|
|
246
|
+
- Combine with member tools to find who said what""",
|
|
247
|
+
"questions": """## Questions & Motions Tools (4 tools)
|
|
248
|
+
|
|
249
|
+
### Early Day Motions (EDMs)
|
|
250
|
+
- get_recently_tabled_edms(take) - Get recently tabled EDMs
|
|
251
|
+
- search_early_day_motions(search_term) - Find EDMs by topic
|
|
252
|
+
- edms_for_member_id(member_id) - EDMs signed/sponsored by a member
|
|
253
|
+
|
|
254
|
+
### Oral Questions
|
|
255
|
+
- search_oral_question_times(answering_date_start, answering_date_end) - Find question sessions
|
|
256
|
+
|
|
257
|
+
### About EDMs
|
|
258
|
+
Early Day Motions are formal notices of a motion:
|
|
259
|
+
- Used to draw attention to issues
|
|
260
|
+
- MPs can sign EDMs to show support
|
|
261
|
+
- Rarely debated but show parliamentary sentiment
|
|
262
|
+
|
|
263
|
+
### About Oral Questions
|
|
264
|
+
Question Time sessions where MPs/Lords ask ministers:
|
|
265
|
+
- Prime Minister's Questions (PMQs) - Wednesdays
|
|
266
|
+
- Departmental questions - rotating schedule
|
|
267
|
+
- Urgent Questions - same-day topical issues""",
|
|
268
|
+
"interests": """## Register of Interests Tools (3 tools)
|
|
269
|
+
|
|
270
|
+
### Search & Browse
|
|
271
|
+
- search_roi(member_id) - Get member's registered interests
|
|
272
|
+
- interests_categories() - List interest categories
|
|
273
|
+
- get_registers_of_interests() - Available registers
|
|
274
|
+
|
|
275
|
+
### About Register of Interests
|
|
276
|
+
MPs and Lords must declare:
|
|
277
|
+
- Employment and earnings
|
|
278
|
+
- Donations and gifts
|
|
279
|
+
- Shareholdings
|
|
280
|
+
- Property
|
|
281
|
+
- Family members' interests
|
|
282
|
+
|
|
283
|
+
### Interest Categories
|
|
284
|
+
1. Employment and earnings
|
|
285
|
+
2. Donations (property, goods, services)
|
|
286
|
+
3. Gifts, benefits, hospitality
|
|
287
|
+
4. Visits outside UK
|
|
288
|
+
5. Gifts and benefits from UK sources
|
|
289
|
+
6. Land and property
|
|
290
|
+
7. Shareholdings
|
|
291
|
+
8. Miscellaneous
|
|
292
|
+
9. Family members employed
|
|
293
|
+
10. Family members with interests
|
|
294
|
+
|
|
295
|
+
### Typical Workflow
|
|
296
|
+
1. Find member: get_member_by_name("Name") -> member_id
|
|
297
|
+
2. Get interests: search_roi(member_id) -> declared interests
|
|
298
|
+
3. Understand categories: interests_categories() -> what each means""",
|
|
299
|
+
"live": """## Live Activity & Calendar Tools (5 tools)
|
|
300
|
+
|
|
301
|
+
### What's Happening Now
|
|
302
|
+
- happening_now_in_commons() - Current Commons chamber activity
|
|
303
|
+
- happening_now_in_lords() - Current Lords chamber activity
|
|
304
|
+
|
|
305
|
+
### Calendar & Schedule
|
|
306
|
+
- search_calendar(house, start_date, end_date) - Find scheduled events (house: 'Commons' or 'Lords')
|
|
307
|
+
- get_sessions() - List of parliamentary sessions
|
|
308
|
+
- get_non_sitting_days(house, start_date, end_date) - Recesses, bank holidays, etc.
|
|
309
|
+
|
|
310
|
+
### Parameters
|
|
311
|
+
- Dates: YYYY-MM-DD format
|
|
312
|
+
- house: 1 = Commons, 2 = Lords (optional)
|
|
313
|
+
|
|
314
|
+
### What "Now" Tools Return
|
|
315
|
+
- Current business being debated
|
|
316
|
+
- Speaker/chair information
|
|
317
|
+
- Estimated timing
|
|
318
|
+
- Link to live stream
|
|
319
|
+
|
|
320
|
+
### Tips
|
|
321
|
+
- "Now" tools only work when Parliament is sitting
|
|
322
|
+
- Check get_non_sitting_days() for recess periods
|
|
323
|
+
- Calendar includes debates, questions, legislation""",
|
|
324
|
+
"legislation": """## Legislation Tools (3 tools)
|
|
325
|
+
|
|
326
|
+
### Statutory Instruments
|
|
327
|
+
- search_statutory_instruments(search_term, skip, take) - Find SIs
|
|
328
|
+
- get_statutory_instruments_business_items(statutory_instrument_id) - SI progress
|
|
329
|
+
|
|
330
|
+
### Treaties
|
|
331
|
+
- search_treaties(search_text, skip, take) - Find international treaties
|
|
332
|
+
|
|
333
|
+
### About Statutory Instruments
|
|
334
|
+
SIs are secondary/delegated legislation:
|
|
335
|
+
- Made under powers in primary Acts
|
|
336
|
+
- Subject to affirmative or negative procedure
|
|
337
|
+
- Cover detailed regulations
|
|
338
|
+
|
|
339
|
+
### About Treaties
|
|
340
|
+
International agreements requiring parliamentary scrutiny:
|
|
341
|
+
- Trade agreements
|
|
342
|
+
- Extradition treaties
|
|
343
|
+
- Mutual legal assistance
|
|
344
|
+
- Environmental agreements
|
|
345
|
+
|
|
346
|
+
### Typical Workflow
|
|
347
|
+
1. Search: search_statutory_instruments("environment")
|
|
348
|
+
2. Details: get_statutory_instruments_business_items(si_id) -> parliamentary progress""",
|
|
349
|
+
"procedures": """## Procedure Tools (3 tools)
|
|
350
|
+
|
|
351
|
+
### Erskine May
|
|
352
|
+
- search_erskine_may(search_term) - Search parliamentary procedure manual
|
|
353
|
+
|
|
354
|
+
### Bill Reference
|
|
355
|
+
- bill_types() - Types of bills (from bills module)
|
|
356
|
+
- bill_stages() - Stage definitions (from bills module)
|
|
357
|
+
|
|
358
|
+
### About Erskine May
|
|
359
|
+
"Parliamentary Practice" - the authoritative guide to:
|
|
360
|
+
- House procedures and rules
|
|
361
|
+
- Precedents and conventions
|
|
362
|
+
- Powers and privileges
|
|
363
|
+
- Committee procedures
|
|
364
|
+
|
|
365
|
+
### Bill Types
|
|
366
|
+
- Public Bills: Change general law
|
|
367
|
+
- Private Bills: Affect specific individuals/organizations
|
|
368
|
+
- Hybrid Bills: Mix of public and private
|
|
369
|
+
- Private Members' Bills: Introduced by backbenchers
|
|
370
|
+
|
|
371
|
+
### Bill Stages
|
|
372
|
+
1. First Reading: Formal introduction
|
|
373
|
+
2. Second Reading: Debate on principles
|
|
374
|
+
3. Committee Stage: Line-by-line scrutiny
|
|
375
|
+
4. Report Stage: House considers amendments
|
|
376
|
+
5. Third Reading: Final debate
|
|
377
|
+
6. Lords/Commons stages: Mirror process in other House
|
|
378
|
+
7. Royal Assent: Becomes law""",
|
|
379
|
+
"all": """## All UK Parliament MCP Tools (92 tools)
|
|
380
|
+
|
|
381
|
+
### Composite (4 tools) - Use These First!
|
|
382
|
+
get_mp_profile, check_mp_vote, get_bill_overview, get_committee_summary
|
|
383
|
+
|
|
384
|
+
### Members (25 tools)
|
|
385
|
+
Search: search_members, get_member_by_name, search_members_historical
|
|
386
|
+
Details: get_member_by_id, get_members_biography, get_members_contact, get_member_synopsis, get_member_experience, get_member_focus
|
|
387
|
+
Activity: get_member_voting, get_commons_voting_record_for_member, get_lords_voting_record_for_member, get_member_written_questions, get_contributions, edms_for_member_id
|
|
388
|
+
Interests: get_member_registered_interests, get_member_staff, get_lords_interests_staff
|
|
389
|
+
Electoral: get_member_latest_election_result, get_constituencies, get_election_results_for_constituency
|
|
390
|
+
Reference: parties_list_by_house, get_departments, get_answering_bodies
|
|
391
|
+
History: get_members_history
|
|
392
|
+
Images: get_member_portrait_url, get_member_thumbnail_url
|
|
393
|
+
|
|
394
|
+
### Bills (21 tools)
|
|
395
|
+
Search: search_bills, get_recently_updated_bills, get_bill_by_id, bill_types
|
|
396
|
+
Stages: get_bill_stages, bill_stages, get_bill_stage_details, get_sittings
|
|
397
|
+
Amendments: get_bill_stage_amendments, get_amendment_by_id
|
|
398
|
+
Ping-pong: get_bill_stage_ping_pong_items, get_ping_pong_item_by_id
|
|
399
|
+
Publications: get_bill_publications, get_bill_stage_publications, get_publication_document, get_publication_types, get_bill_news_articles
|
|
400
|
+
RSS: get_all_bills_rss, get_public_bills_rss, get_private_bills_rss, get_bill_rss
|
|
401
|
+
|
|
402
|
+
### Votes (10 tools)
|
|
403
|
+
Commons: search_commons_divisions, get_commons_division_by_id, get_commons_voting_record_for_member, get_commons_divisions_grouped_by_party, get_commons_divisions_search_count
|
|
404
|
+
Lords: search_lords_divisions, get_lords_division_by_id, get_lords_voting_record_for_member, get_lords_divisions_grouped_by_party, get_lords_divisions_search_count
|
|
405
|
+
|
|
406
|
+
### Committees (12 tools)
|
|
407
|
+
Search: search_committees, get_committee_by_id, get_committee_types
|
|
408
|
+
Meetings: get_committee_meetings, get_events, get_event_by_id, get_committee_events
|
|
409
|
+
Members: get_committee_members
|
|
410
|
+
Evidence: get_oral_evidence, get_written_evidence
|
|
411
|
+
Publications: get_publications, get_publication_by_id
|
|
412
|
+
|
|
413
|
+
### Other Tools (22 tools)
|
|
414
|
+
Hansard: search_hansard
|
|
415
|
+
Questions: get_recently_tabled_edms, search_early_day_motions, search_oral_question_times
|
|
416
|
+
Interests: search_roi, interests_categories, get_registers_of_interests
|
|
417
|
+
Live: happening_now_in_commons, happening_now_in_lords
|
|
418
|
+
Calendar: search_calendar, get_sessions, get_non_sitting_days
|
|
419
|
+
Legislation: search_statutory_instruments, get_statutory_instruments_business_items, search_treaties
|
|
420
|
+
Procedures: search_erskine_may
|
|
421
|
+
Session: hello_parliament, goodbye_parliament, parliament_guide, parliament_workflow""",
|
|
422
|
+
"conventions": """## UK Parliament MCP Conventions
|
|
423
|
+
|
|
424
|
+
### House Identification
|
|
425
|
+
- House 1 = House of Commons (MPs)
|
|
426
|
+
- House 2 = House of Lords (Lords/Peers)
|
|
427
|
+
- Some tools accept house as integer, others as string ("Commons"/"Lords")
|
|
428
|
+
|
|
429
|
+
### Date Format
|
|
430
|
+
- Always use YYYY-MM-DD (e.g., "2024-03-15")
|
|
431
|
+
- Date ranges: from_date/start_date and to_date/end_date
|
|
432
|
+
|
|
433
|
+
### Pagination
|
|
434
|
+
- skip: Number of records to skip (default: 0)
|
|
435
|
+
- take: Number of records to return (typical: 20-30, max: 100)
|
|
436
|
+
- Use skip/take for paging through large result sets
|
|
437
|
+
|
|
438
|
+
### IDs
|
|
439
|
+
- member_id: Unique identifier for MPs and Lords
|
|
440
|
+
- bill_id: Unique identifier for legislation
|
|
441
|
+
- division_id: Unique identifier for votes
|
|
442
|
+
- committee_id: Unique identifier for committees
|
|
443
|
+
- Always get IDs from search results first, then use in detail tools
|
|
444
|
+
|
|
445
|
+
### Response Format
|
|
446
|
+
- All tools return JSON from Parliament APIs
|
|
447
|
+
- Successful: {"url": "...", "data": {...}}
|
|
448
|
+
- Error: {"url": "...", "error": "...", "statusCode": N}
|
|
449
|
+
|
|
450
|
+
### Naming Conventions
|
|
451
|
+
- search_* : Search/discovery tools
|
|
452
|
+
- get_* : Retrieve specific item by ID or parameters
|
|
453
|
+
- *_by_id : Requires specific ID parameter
|
|
454
|
+
- *_for_member : Requires member_id parameter""",
|
|
455
|
+
"workflows": """## Common Research Workflows
|
|
456
|
+
|
|
457
|
+
### MP Voting Research
|
|
458
|
+
Goal: Find how an MP voted on a topic
|
|
459
|
+
1. get_member_by_name(name) -> member_id
|
|
460
|
+
2. search_commons_divisions(topic) -> find relevant division_id
|
|
461
|
+
3. get_commons_division_by_id(division_id) -> check Ayes/Noes lists
|
|
462
|
+
|
|
463
|
+
### Bill Tracking
|
|
464
|
+
Goal: Track a bill's progress through Parliament
|
|
465
|
+
1. search_bills(topic) -> bill_id
|
|
466
|
+
2. get_bill_by_id(bill_id) -> current status
|
|
467
|
+
3. get_bill_stages(bill_id) -> full journey
|
|
468
|
+
4. get_bill_amendments(bill_id) -> proposed changes
|
|
469
|
+
|
|
470
|
+
### Committee Investigation
|
|
471
|
+
Goal: Find what a committee examined
|
|
472
|
+
1. search_committees(topic) -> committee_id
|
|
473
|
+
2. get_committee_by_id(committee_id) -> scope
|
|
474
|
+
3. get_oral_evidence(committee_id) -> witness testimony
|
|
475
|
+
4. get_committee_publications(committee_id) -> reports
|
|
476
|
+
|
|
477
|
+
### Conflict of Interest Research
|
|
478
|
+
Goal: Check MP's financial interests
|
|
479
|
+
1. get_member_by_name(name) -> member_id
|
|
480
|
+
2. search_roi(member_id) -> declared interests
|
|
481
|
+
3. interests_categories() -> understand categories
|
|
482
|
+
|
|
483
|
+
### Live Parliament Activity
|
|
484
|
+
Goal: See what's happening now
|
|
485
|
+
1. happening_now_in_commons() or happening_now_in_lords()
|
|
486
|
+
2. search_calendar(today, today) -> today's schedule
|
|
487
|
+
|
|
488
|
+
### Historical Voting
|
|
489
|
+
Goal: Research past votes on topic
|
|
490
|
+
1. search_commons_divisions(topic) -> list of votes
|
|
491
|
+
2. get_commons_division_by_id(division_id) -> full results
|
|
492
|
+
3. Repeat for key divisions
|
|
493
|
+
|
|
494
|
+
### MP Background Research
|
|
495
|
+
Goal: Full profile of an MP
|
|
496
|
+
1. get_member_by_name(name) -> member_id
|
|
497
|
+
2. get_member_by_id(member_id) -> basic info
|
|
498
|
+
3. get_members_biography(member_id) -> background
|
|
499
|
+
4. get_member_registered_interests(member_id, 1) -> interests
|
|
500
|
+
5. get_commons_voting_record_for_member(member_id) -> votes
|
|
501
|
+
|
|
502
|
+
### Hansard Search
|
|
503
|
+
Goal: Find what was said in Parliament
|
|
504
|
+
1. search_hansard(topic, house) -> speeches and debates
|
|
505
|
+
2. Filter by date, speaker, or house
|
|
506
|
+
|
|
507
|
+
### Electoral Research
|
|
508
|
+
Goal: Constituency election history
|
|
509
|
+
1. get_constituencies() -> find constituency_id
|
|
510
|
+
2. get_election_results_for_constituency(constituency_id) -> all results
|
|
511
|
+
|
|
512
|
+
### Legislation Search
|
|
513
|
+
Goal: Find regulations and treaties
|
|
514
|
+
1. search_statutory_instruments(topic) -> SIs
|
|
515
|
+
2. search_treaties(topic) -> international agreements""",
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
WORKFLOW_PATTERNS: list[dict[str, Any]] = [
|
|
519
|
+
{
|
|
520
|
+
"keywords": ["vote", "voted", "voting", "division", "aye", "noes"],
|
|
521
|
+
"name": "MP Voting Research",
|
|
522
|
+
"description": "Find how an MP voted on a specific topic or bill",
|
|
523
|
+
"steps": [
|
|
524
|
+
{
|
|
525
|
+
"step": 1,
|
|
526
|
+
"tool": "get_member_by_name(name)",
|
|
527
|
+
"purpose": "Get the member_id for the MP",
|
|
528
|
+
"output": "member_id (integer)",
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
"step": 2,
|
|
532
|
+
"tool": "search_commons_divisions(search_term)",
|
|
533
|
+
"purpose": "Find divisions (votes) on the topic",
|
|
534
|
+
"output": "List of divisions with division_id",
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
"step": 3,
|
|
538
|
+
"tool": "get_commons_division_by_id(division_id)",
|
|
539
|
+
"purpose": "Get full voting list including how members voted",
|
|
540
|
+
"output": "Aye and No lists with member names",
|
|
541
|
+
},
|
|
542
|
+
],
|
|
543
|
+
"alternative": "Use get_commons_voting_record_for_member(member_id) for all votes by an MP",
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
"keywords": ["bill", "legislation", "law", "act", "progress", "stage"],
|
|
547
|
+
"name": "Bill Tracking",
|
|
548
|
+
"description": "Track a bill's progress through Parliament",
|
|
549
|
+
"steps": [
|
|
550
|
+
{
|
|
551
|
+
"step": 1,
|
|
552
|
+
"tool": "search_bills(search_term)",
|
|
553
|
+
"purpose": "Find the bill by keyword",
|
|
554
|
+
"output": "bill_id and current status",
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
"step": 2,
|
|
558
|
+
"tool": "get_bill_by_id(bill_id)",
|
|
559
|
+
"purpose": "Get full bill details",
|
|
560
|
+
"output": "Title, summary, sponsors, current stage",
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"step": 3,
|
|
564
|
+
"tool": "get_bill_stages(bill_id)",
|
|
565
|
+
"purpose": "See the legislative journey",
|
|
566
|
+
"output": "All stages with dates and houses",
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
"step": 4,
|
|
570
|
+
"tool": "get_bill_amendments(bill_id)",
|
|
571
|
+
"purpose": "See proposed changes",
|
|
572
|
+
"output": "List of amendments with sponsors",
|
|
573
|
+
},
|
|
574
|
+
],
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
"keywords": ["committee", "inquiry", "evidence", "witness", "hearing"],
|
|
578
|
+
"name": "Committee Research",
|
|
579
|
+
"description": "Find what a committee examined on a topic",
|
|
580
|
+
"steps": [
|
|
581
|
+
{
|
|
582
|
+
"step": 1,
|
|
583
|
+
"tool": "search_committees(search_term)",
|
|
584
|
+
"purpose": "Find relevant committee",
|
|
585
|
+
"output": "committee_id",
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"step": 2,
|
|
589
|
+
"tool": "get_committee_by_id(committee_id)",
|
|
590
|
+
"purpose": "Get committee details and scope",
|
|
591
|
+
"output": "Committee info and current inquiries",
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
"step": 3,
|
|
595
|
+
"tool": "get_oral_evidence(committee_id)",
|
|
596
|
+
"purpose": "Find witness testimonies",
|
|
597
|
+
"output": "Oral evidence transcripts",
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
"step": 4,
|
|
601
|
+
"tool": "get_committee_publications(committee_id)",
|
|
602
|
+
"purpose": "Find reports and conclusions",
|
|
603
|
+
"output": "Published reports",
|
|
604
|
+
},
|
|
605
|
+
],
|
|
606
|
+
},
|
|
607
|
+
{
|
|
608
|
+
"keywords": ["interest", "conflict", "financial", "donation", "declare"],
|
|
609
|
+
"name": "Interests/Conflicts Research",
|
|
610
|
+
"description": "Check an MP's declared financial interests",
|
|
611
|
+
"steps": [
|
|
612
|
+
{
|
|
613
|
+
"step": 1,
|
|
614
|
+
"tool": "get_member_by_name(name)",
|
|
615
|
+
"purpose": "Get the member_id",
|
|
616
|
+
"output": "member_id",
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
"step": 2,
|
|
620
|
+
"tool": "search_roi(member_id)",
|
|
621
|
+
"purpose": "Get all declared interests",
|
|
622
|
+
"output": "List of registered interests",
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
"step": 3,
|
|
626
|
+
"tool": "interests_categories()",
|
|
627
|
+
"purpose": "Understand what each category means",
|
|
628
|
+
"output": "Category definitions",
|
|
629
|
+
},
|
|
630
|
+
],
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
"keywords": ["now", "today", "happening", "live", "current", "sitting"],
|
|
634
|
+
"name": "Live Parliament Activity",
|
|
635
|
+
"description": "See what's happening in Parliament right now",
|
|
636
|
+
"steps": [
|
|
637
|
+
{
|
|
638
|
+
"step": 1,
|
|
639
|
+
"tool": "happening_now_in_commons() or happening_now_in_lords()",
|
|
640
|
+
"purpose": "Get current chamber activity",
|
|
641
|
+
"output": "Current business, speaker, timing",
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
"step": 2,
|
|
645
|
+
"tool": "search_calendar(today_date, today_date)",
|
|
646
|
+
"purpose": "See full day's schedule",
|
|
647
|
+
"output": "All scheduled events for today",
|
|
648
|
+
},
|
|
649
|
+
],
|
|
650
|
+
"note": "Only works when Parliament is sitting - check get_non_sitting_days() for recesses",
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
"keywords": ["background", "biography", "profile", "who is", "about"],
|
|
654
|
+
"name": "MP Background Research",
|
|
655
|
+
"description": "Get comprehensive information about an MP",
|
|
656
|
+
"steps": [
|
|
657
|
+
{
|
|
658
|
+
"step": 1,
|
|
659
|
+
"tool": "get_member_by_name(name)",
|
|
660
|
+
"purpose": "Find the member",
|
|
661
|
+
"output": "member_id and basic info",
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
"step": 2,
|
|
665
|
+
"tool": "get_member_by_id(member_id)",
|
|
666
|
+
"purpose": "Get full profile",
|
|
667
|
+
"output": "Party, constituency, status",
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
"step": 3,
|
|
671
|
+
"tool": "get_members_biography(member_id)",
|
|
672
|
+
"purpose": "Get background",
|
|
673
|
+
"output": "Education, career, personal",
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
"step": 4,
|
|
677
|
+
"tool": "get_member_registered_interests(member_id, house=1)",
|
|
678
|
+
"purpose": "Get declared interests",
|
|
679
|
+
"output": "Financial interests",
|
|
680
|
+
},
|
|
681
|
+
],
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
"keywords": ["said", "speech", "debate", "hansard", "parliament said"],
|
|
685
|
+
"name": "Hansard Search",
|
|
686
|
+
"description": "Find what was said in Parliament about a topic",
|
|
687
|
+
"steps": [
|
|
688
|
+
{
|
|
689
|
+
"step": 1,
|
|
690
|
+
"tool": "search_hansard(search_term, house)",
|
|
691
|
+
"purpose": "Search parliamentary record",
|
|
692
|
+
"output": "Speeches and debates matching topic",
|
|
693
|
+
},
|
|
694
|
+
],
|
|
695
|
+
"tips": [
|
|
696
|
+
"Use specific phrases for better results",
|
|
697
|
+
"Filter by house (1=Commons, 2=Lords) if needed",
|
|
698
|
+
"Results include speaker, date, and context",
|
|
699
|
+
],
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
"keywords": ["election", "constituency", "result", "majority", "swing"],
|
|
703
|
+
"name": "Electoral Research",
|
|
704
|
+
"description": "Find election results for a constituency",
|
|
705
|
+
"steps": [
|
|
706
|
+
{
|
|
707
|
+
"step": 1,
|
|
708
|
+
"tool": "get_constituencies()",
|
|
709
|
+
"purpose": "Find constituency ID",
|
|
710
|
+
"output": "List of constituencies with IDs",
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"step": 2,
|
|
714
|
+
"tool": "get_election_results_for_constituency(constituency_id)",
|
|
715
|
+
"purpose": "Get historical results",
|
|
716
|
+
"output": "All election results with votes and majorities",
|
|
717
|
+
},
|
|
718
|
+
],
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
"keywords": ["edm", "early day motion", "support", "signed"],
|
|
722
|
+
"name": "Early Day Motion Research",
|
|
723
|
+
"description": "Find EDMs on a topic or signed by an MP",
|
|
724
|
+
"steps": [
|
|
725
|
+
{
|
|
726
|
+
"step": 1,
|
|
727
|
+
"tool": "search_early_day_motions(search_term)",
|
|
728
|
+
"purpose": "Find EDMs by topic",
|
|
729
|
+
"output": "List of EDMs with signatories",
|
|
730
|
+
},
|
|
731
|
+
],
|
|
732
|
+
"alternative": "Use edms_for_member_id(member_id) to find EDMs signed by a specific MP",
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
"keywords": ["treaty", "international", "agreement", "trade deal"],
|
|
736
|
+
"name": "Treaty Research",
|
|
737
|
+
"description": "Find international treaties and agreements",
|
|
738
|
+
"steps": [
|
|
739
|
+
{
|
|
740
|
+
"step": 1,
|
|
741
|
+
"tool": "search_treaties(search_text)",
|
|
742
|
+
"purpose": "Find treaties by keyword",
|
|
743
|
+
"output": "Treaty details and status",
|
|
744
|
+
},
|
|
745
|
+
],
|
|
746
|
+
},
|
|
747
|
+
]
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def _format_workflow(pattern: dict[str, Any]) -> str:
|
|
751
|
+
"""Format a workflow pattern into readable text."""
|
|
752
|
+
lines = [
|
|
753
|
+
f"## Workflow: {pattern['name']}",
|
|
754
|
+
"",
|
|
755
|
+
pattern["description"],
|
|
756
|
+
"",
|
|
757
|
+
"### Steps",
|
|
758
|
+
]
|
|
759
|
+
|
|
760
|
+
for step in pattern["steps"]:
|
|
761
|
+
lines.append(f"**Step {step['step']}**: `{step['tool']}`")
|
|
762
|
+
lines.append(f"- Purpose: {step['purpose']}")
|
|
763
|
+
lines.append(f"- Output: {step['output']}")
|
|
764
|
+
lines.append("")
|
|
765
|
+
|
|
766
|
+
if "alternative" in pattern:
|
|
767
|
+
lines.append(f"**Alternative**: {pattern['alternative']}")
|
|
768
|
+
lines.append("")
|
|
769
|
+
|
|
770
|
+
if "note" in pattern:
|
|
771
|
+
lines.append(f"**Note**: {pattern['note']}")
|
|
772
|
+
lines.append("")
|
|
773
|
+
|
|
774
|
+
if "tips" in pattern:
|
|
775
|
+
lines.append("**Tips**:")
|
|
776
|
+
for tip in pattern["tips"]:
|
|
777
|
+
lines.append(f"- {tip}")
|
|
778
|
+
lines.append("")
|
|
779
|
+
|
|
780
|
+
return "\n".join(lines)
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
def _suggest_general_approach(query: str) -> str:
|
|
784
|
+
"""Suggest a general approach when no specific workflow matches."""
|
|
785
|
+
return f"""## Research Approach for: "{query}"
|
|
786
|
+
|
|
787
|
+
No specific workflow pattern matched. Here's a general approach:
|
|
788
|
+
|
|
789
|
+
### Step 1: Identify What You Need
|
|
790
|
+
- **People**: Use get_member_by_name() to find MPs/Lords
|
|
791
|
+
- **Legislation**: Use search_bills() to find bills
|
|
792
|
+
- **Votes**: Use search_commons_divisions() or search_lords_divisions()
|
|
793
|
+
- **Committees**: Use search_committees()
|
|
794
|
+
- **Debates**: Use search_hansard()
|
|
795
|
+
|
|
796
|
+
### Step 2: Get IDs from Search Results
|
|
797
|
+
Most detail tools require an ID (member_id, bill_id, etc.) from search results.
|
|
798
|
+
|
|
799
|
+
### Step 3: Drill Down
|
|
800
|
+
Use specific tools like get_member_by_id(), get_bill_stages(), etc.
|
|
801
|
+
|
|
802
|
+
### Available Topics for Detailed Guidance
|
|
803
|
+
Use parliament_guide(topic) with one of:
|
|
804
|
+
- members, bills, votes, committees, hansard
|
|
805
|
+
- questions, interests, live, legislation, procedures
|
|
806
|
+
- all, conventions, workflows"""
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
def register_tools(mcp: FastMCP) -> None:
|
|
810
|
+
"""Register core tools with the MCP server."""
|
|
811
|
+
|
|
812
|
+
@mcp.tool()
|
|
813
|
+
async def hello_parliament() -> str:
|
|
814
|
+
"""Initialize Parliament data assistant with system prompt | setup, configuration, start session, getting started, how to use, instructions | Use FIRST when beginning parliamentary research to get proper assistant behavior and data handling guidelines | Returns system prompt for optimal parliamentary data interaction"""
|
|
815
|
+
return f"{SYSTEM_PROMPT}\n\n---\n\n{QUICK_REFERENCE}"
|
|
816
|
+
|
|
817
|
+
@mcp.tool()
|
|
818
|
+
async def goodbye_parliament() -> str:
|
|
819
|
+
"""End Parliament session and restore normal assistant behavior | exit, quit, finish session, reset, normal mode, end parliamentary mode | Use when finished with parliamentary research to return to standard assistant behavior | Removes parliamentary data restrictions and requirements"""
|
|
820
|
+
return GOODBYE_PROMPT
|
|
821
|
+
|
|
822
|
+
@mcp.tool()
|
|
823
|
+
async def parliament_guide(topic: str) -> str:
|
|
824
|
+
"""Get detailed guidance for a specific Parliament data domain | tool help, API reference, how to use tools, available tools | Use when you need detailed information about tools in a specific area | Returns comprehensive guidance including tool names, parameters, and typical workflows
|
|
825
|
+
|
|
826
|
+
Args:
|
|
827
|
+
topic: Domain to get guidance for. Options: members, bills, votes, committees, hansard, questions, interests, live, legislation, procedures, all, conventions, workflows
|
|
828
|
+
"""
|
|
829
|
+
topic_lower = topic.lower().strip()
|
|
830
|
+
|
|
831
|
+
if topic_lower not in GUIDANCE_CONTENT:
|
|
832
|
+
available = ", ".join(sorted(GUIDANCE_CONTENT.keys()))
|
|
833
|
+
return f"Topic '{topic}' not recognized.\n\nAvailable topics: {available}"
|
|
834
|
+
|
|
835
|
+
return GUIDANCE_CONTENT[topic_lower]
|
|
836
|
+
|
|
837
|
+
@mcp.tool()
|
|
838
|
+
async def parliament_workflow(query: str) -> str:
|
|
839
|
+
"""Get step-by-step workflow guidance for a parliamentary research task | workflow planning, multi-step tasks, research planning, how to find | Use when you have a specific research question and need to plan which tools to use in sequence | Returns recommended sequence of tools with parameters and expected data flow
|
|
840
|
+
|
|
841
|
+
Args:
|
|
842
|
+
query: Research question or task description. Examples: "How did my MP vote on climate?", "Track a bill's progress", "Find committee evidence on NHS"
|
|
843
|
+
"""
|
|
844
|
+
query_lower = query.lower()
|
|
845
|
+
|
|
846
|
+
# Find matching workflow pattern
|
|
847
|
+
for pattern in WORKFLOW_PATTERNS:
|
|
848
|
+
if any(keyword in query_lower for keyword in pattern["keywords"]):
|
|
849
|
+
return _format_workflow(pattern)
|
|
850
|
+
|
|
851
|
+
# No match - provide general guidance
|
|
852
|
+
return _suggest_general_approach(query)
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
def register_prompts(mcp: FastMCP) -> None:
|
|
856
|
+
"""Register MCP prompts (agent skills) with the server."""
|
|
857
|
+
|
|
858
|
+
@mcp.prompt()
|
|
859
|
+
async def parliament(topic: str | None = None) -> str:
|
|
860
|
+
"""Initialize UK Parliament research session with guidance on 86 available tools.
|
|
861
|
+
|
|
862
|
+
Provides system instructions for parliamentary data queries, quick reference
|
|
863
|
+
of tool categories, and guidance on common research workflows.
|
|
864
|
+
|
|
865
|
+
Use this prompt to start a parliamentary research session. Optionally specify
|
|
866
|
+
a topic to get detailed guidance for that domain.
|
|
867
|
+
|
|
868
|
+
Args:
|
|
869
|
+
topic: Optional topic for detailed guidance (members, bills, votes,
|
|
870
|
+
committees, hansard, questions, interests, live, legislation,
|
|
871
|
+
procedures, all, conventions, workflows)
|
|
872
|
+
"""
|
|
873
|
+
base_content = f"{SYSTEM_PROMPT}\n\n---\n\n{QUICK_REFERENCE}"
|
|
874
|
+
|
|
875
|
+
if topic:
|
|
876
|
+
topic_lower = topic.lower().strip()
|
|
877
|
+
if topic_lower in GUIDANCE_CONTENT:
|
|
878
|
+
return f"{base_content}\n\n---\n\n{GUIDANCE_CONTENT[topic_lower]}"
|
|
879
|
+
|
|
880
|
+
return base_content
|