canada-parliament-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@canada-parliament-mcp-serverfind recent House bills about housing and show their latest stages"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Overview
Canadian federal parliamentary records from LEGISinfo, the House of Commons, and OpenParliament. Follow House and Senate bills through their stages, find current and former MPs, inspect recorded House divisions, and read indexed House Hansard speeches. Public sources require no API key.
Tools
Tool | Description |
| Search a session's official bills by title, number, chamber, type, status, or indexed MP sponsor |
| Read an official bill dossier, stages, divisions, publications, and enacted statute citation |
| Search the current House roster or OpenParliament's historical name index |
| Read a member profile, dated memberships, sponsored bills, and recent ballots |
| Search recorded House divisions by bill, result, document type, date, or subject |
| Read a division's official tally, party totals, and individual recorded ballots |
| Find indexed House speeches by speaker, bill debated or mentioned, date, and literal English text |
| Discover actual session coverage and source-specific filter vocabulary |
Related MCP server: @cyanheads/openfec-mcp-server
Capability reference
canparl_search_bills tool
Combine
titleContains,billCode,originatingChamber,billType,status, andsponsorwith AND;limit1–100 (default 25),offsetdefault 0Returns official bilingual titles, status, latest major stage, royal assent date, exact filtered
total, andpagination.nextOffsetsponsortakes a returned MP OpenParliament slug and restricts results to its index (sponsorCoverage: "openparliament_index"); Senators are outside that index. A scan exceeding ten 100-row pages fails withsponsor_scan_incompleterather than returning an incomplete set
canparl_get_bill tool
Supply
billCodefrom search and itssession; returns sponsor, House/Senate/royal-assent stages with nested records, House divisions, source-specific Senate vote records, publications, andstatutewhen availableDossiers above a 24,000-byte serialized response budget return
kind: "outline"with section selectors:sponsor,stages.house,stages.senate,stages.royalAssent,divisions,senateVoteDetails,publications,statute. Re-call withsection; collections acceptoffset(default 0) andlimit1–100 (default 20), continued throughpagination.nextOffsetSection pages preserve whole records and may contain fewer than
limitto fit the budget. An indivisible record or scalar section above the budget is returned whole withdisclosure;null, empty collections, and past-end offsets remain distinguishable
canparl_search_members tool
Current roster: literal
name/ridingsubstrings plusprovinceandparty;limit1–100 (default 25), offset pagination, and exact filteredtotalincludeFormer: trueselects the historical index: one name token searches a surname, multiple tokens a full recorded name; riding/province/party filters are unsupported. Historical rows can contain only name and slug, withtotal: nullPass a returned
detailLookupunchanged tocanparl_get_member; officialpersonIdand OpenParliamentslugare distinct identifiers
canparl_get_member tool
Supply exactly one
personIdorslugfromdetailLookup; returns a public profile and datedmembershipswhere availableIndependent
sponsoredBills(0–5, default 5) andrecentVotes(0–10, default 10) limits, withbillsOffset/votesOffsetand each section'snextOffset; set both limits to 0 for profile-only lookupOptional enrichment failures preserve the official profile. Activity sections distinguish
available,unavailable, andnot_requested, withfailuremetadata; unavailable history is never an empty-history claim
canparl_search_votes tool
Combine
billCode,result,documentType,dateFrom,dateTo, andsubjectContains; dates are inclusive Ottawa civil dates.limit1–100 (default 25), offset paginationReturns newest divisions first, official result wording and tallies, exact filtered
total, andpagination.nextOffset; use returnedsessionandnumberwithcanparl_get_vote
canparl_get_vote tool
Supply
numberand itssession; optionalparty/provincefilters affect only the ballot page.limit1–400 (default 100), offset paginationtally,byParty, andballotsTotaldescribe the full division;ballotsMatcheddescribes the filtered set.tallyMatchesBallotsflags discrepancies without rewriting either source countBallots are
Yea,Nay, orPaired; nonvoters are absent, and paired records are counted individually
canparl_search_speeches tool
Require at least one
politician,billDebated,mentionedBill,dateFrom, ordateTo; bill scopes require explicit{ session, code }. Filters combine with AND; optionalcontainsis a literal English-text substring and cannot be the sole scopelimit1–10 (default 5); scans at most 100 raw candidates per call. ContinuenextOffsetwith identical filters untilexhaustedbefore drawing a negative conclusion; even an exhausted search describes OpenParliament's index, not all parliamentary speechComplete English
contentand speech-date party/riding are returned when available, otherwisenull.substantiveOnlydefaults true; set false to include procedural remarks. Committee records are excluded and counted inexcludedCommittees
canparl_list_reference tool
Required
topic:sessions,bill_types,bill_statuses,vote_results,vote_document_types, orparties; returns the complete reference set without paginationFor
sessions, omitsession; entries distinguishbasic/fullbill coverage and advertised House division coverage. Other topics accept a session and mark whether vocabulary was actuallyobservedin its feed
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Canadian Parliament-specific:
Official bill coverage begins at session
35-1(1994); full dossiers begin at37-1(2001). House division coverage begins at38-1(2004). Discover supported sessions withcanparl_list_reference; OpenParliament's historical name index reaches 1994, with source-dependent activity coverageBills cover both chambers; member, division, and speech tools cover the House. Missing historical fields remain
nullA session accepts
"45-1"or{ "parliament": 45, "session": 1 }; omitted sessions resolve from the current official bill feed, except explicit speech bill scopesShared source pacing, short-lived in-memory caches, retries, and one 50-second tool deadline. OpenParliament requests are serialized with a two-second start gap; large member activity requests can take tens of seconds
Agent-friendly output:
Provenance —
source,url, originalretrievedAt, andcachedaccompany every successful retrievalExplicit coverage — normalized
appliedFilters, continuation fields, notices, and typed failure reasons distinguish no matches from unavailable or incomplete dataLossless client surfaces — Markdown
content[]andstructuredContentcarry the same values, including source text and nested stage records
Getting started
Add the following to your MCP client configuration file:
{
"mcpServers": {
"canada-parliament-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/canada-parliament-mcp-server@latest"],
"env": { "MCP_TRANSPORT_TYPE": "stdio", "MCP_LOG_LEVEL": "info" }
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"canada-parliament-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/canada-parliament-mcp-server@latest"],
"env": { "MCP_TRANSPORT_TYPE": "stdio", "MCP_LOG_LEVEL": "info" }
}
}
}Or with Docker:
{
"mcpServers": {
"canada-parliament-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/canada-parliament-mcp-server:latest"]
}
}
}For Streamable HTTP, start the built server from a local checkout:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.4.0 or higher, or Node.js v24+
Internet access to Parliament and OpenParliament; no upstream API key required
Installation
git clone https://github.com/cyanheads/canada-parliament-mcp-server.git
cd canada-parliament-mcp-server
bun install
cp .env.example .env
bun run rebuildConfiguration
Variable | Description | Default |
| Optional upstream HTTP identification; blank uses the default, CR/LF forbidden |
|
|
|
|
| HTTP bind address |
|
| HTTP port |
|
|
|
|
|
|
|
| Minimum log level |
|
| File log directory (Node.js only) |
|
| Framework storage backend |
|
| Enable OpenTelemetry |
|
See .env.example for common framework overrides.
Running the server
bun run rebuild # Clean and build
bun run start:stdio # Built server over stdio
bun run start:http # Built server over Streamable HTTPFor a local HTTP container:
docker build -t canada-parliament-mcp-server .
docker run --rm -p 127.0.0.1:3010:3010 canada-parliament-mcp-serverProject structure
Directory | Purpose |
| Eight tools and shared Markdown rendering |
| Official bill JSON, session discovery, pacing, and cache |
| Official current roster and division XML |
| Historical identities, activity, speeches, and memberships |
| Shared schemas, normalization, vocabulary, and request budgets |
| Server-specific environment parsing |
| Parser, service, tool, and integration tests with synthetic upstream fixtures |
See docs/tree.md for the full tree.
Development guide
See CLAUDE.md or AGENTS.md for development rules.
Register tools in
src/index.ts; keep source parsing and transport in their owning servicesValidate upstream data and preserve unavailable fields rather than inventing values
Declare typed errors and render every returned value on both client surfaces
Test real parsers and handlers through the fake HTTP boundary
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Code is licensed under Apache 2.0. Parliamentary data is an unofficial reproduction credited to Parliament and, where used, OpenParliament; Parliament retains copyright. Reuse is governed separately by Parliament notices, Speaker's Permission, Senate terms, and OpenParliament API terms. This free, noncommercial relay does not imply government endorsement or an open-data licence.
This server cannot be deployed
Maintenance
Related MCP Connectors
Search MPs and Lords, fetch profiles, synopses, and Westminster constituencies
Access U.S. congressional data (bills, votes, members, committees) via MCP.
Query SEC EDGAR filings, XBRL financials, and company data via MCP. STDIO or Streamable HTTP.
OpenParliament.ca MCP — civic-tech mirror of the Parliament of Canada
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceProvides access to Canadian federal parliamentary data (debates, bills, MPs, votes, Hansard transcripts) and legal information (case law and legislation through CanLII) for research and analysis.3MIT
- AlicenseNot gradedqualityAmaintenanceAccess FEC campaign finance data through MCP. Query data about candidates, money trails, and election filings. STDIO & Streamable HTTP.147 npm2Apache 2.0
- AlicenseNot gradedqualityBmaintenanceProvides access to Canadian parliamentary data including debates, bills, votes, politicians, and committees via the OpenParliament.ca civic-tech mirror.13 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables querying UK Parliament data including MPs, Lords, bills, Hansard debates, and divisions.7 npmMIT