canada-parliament-mcp-server

v0.1.2 pre-1.0

Track Canadian federal bills, MPs, House votes, and Hansard speeches via MCP. STDIO or Streamable HTTP.

canada-parliament.caseyjhand.com/mcp
claude mcp add --transport http canada-parliament-mcp-server https://canada-parliament.caseyjhand.com/mcp
codex mcp add canada-parliament-mcp-server --url https://canada-parliament.caseyjhand.com/mcp
{
  "mcpServers": {
    "canada-parliament-mcp-server": {
      "url": "https://canada-parliament.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http canada-parliament-mcp-server https://canada-parliament.caseyjhand.com/mcp
{
  "mcpServers": {
    "canada-parliament-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://canada-parliament.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "canada-parliament-mcp-server": {
      "type": "http",
      "url": "https://canada-parliament.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://canada-parliament.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

8

canparl_search_bills

open-world

Find House and Senate bills in one session by title, number, type, chamber, status, or indexed MP sponsor. Sponsor results are the OpenParliament-indexed subset; fetch a bill for its sponsor, stages, divisions, and statute citation. Omitted session means the verified current official session. Follow nextOffset with identical filters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_search_bills",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "session": {
      "description": "Parliamentary session; omitted means current.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d+-\\d+$",
          "description": "Parliament-session token, such as 45-1."
        },
        {
          "type": "object",
          "properties": {
            "parliament": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive parliament number."
            },
            "session": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive session number."
            }
          },
          "required": [
            "parliament",
            "session"
          ],
          "additionalProperties": false,
          "description": "Parliament and session numbers."
        }
      ]
    },
    "titleContains": {
      "description": "Literal case-insensitive substring of any English or French long or short title.",
      "type": "string"
    },
    "billCode": {
      "description": "Exact bill code, including a split-bill suffix letter such as C-15A; accepts bill s321, S321, S 321, or S-321.",
      "type": "string"
    },
    "originatingChamber": {
      "description": "House, House of Commons, or Senate; case-insensitive.",
      "type": "string"
    },
    "billType": {
      "description": "Official bill type from canparl_list_reference topic bill_types.",
      "type": "string"
    },
    "status": {
      "description": "Official bill status from canparl_list_reference topic bill_statuses.",
      "type": "string"
    },
    "sponsor": {
      "description": "MP OpenParliament slug or politician path/HTTPS URL (member.slug from canparl_get_member, or an includeFormer canparl_search_members row), or a current MP's official personId; Senators are not indexed. A digit-only value equal to a current personId, or its /politicians/<digits>/ path or profile URL, is read as that personId.",
      "type": "string"
    },
    "limit": {
      "default": 25,
      "description": "Maximum returned rows, 1–100 per call; larger values up to 10000 return 100 rows with a notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Zero-based offset in the selected ordering.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

canparl_get_bill

open-world

Read one House or Senate bill's official dossier. Large dossiers return an outline; re-call with one section and follow pagination.nextOffset for collections. Stages preserve nested records whole. Obtain billCode and session from canparl_search_bills; omitted session means the verified current official session.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_get_bill",
    "arguments": {
      "billCode": "<billCode>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "session": {
      "description": "Parliamentary session; omitted means current.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d+-\\d+$",
          "description": "Parliament-session token, such as 45-1."
        },
        {
          "type": "object",
          "properties": {
            "parliament": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive parliament number."
            },
            "session": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive session number."
            }
          },
          "required": [
            "parliament",
            "session"
          ],
          "additionalProperties": false,
          "description": "Parliament and session numbers."
        }
      ]
    },
    "billCode": {
      "type": "string",
      "description": "Bill code from canparl_search_bills, including a split-bill suffix letter such as C-15A; accepts bill s321, S321, S 321, or S-321."
    },
    "section": {
      "description": "One section from the returned outline; omit for full dossier or overflow outline.",
      "type": "string"
    },
    "offset": {
      "default": 0,
      "description": "Zero-based whole-record offset within the selected collection.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "limit": {
      "default": 20,
      "description": "Maximum whole records per selected collection page, 1–100 per call; larger values up to 10000 return 100 with a notice, and the byte budget may reduce it.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    }
  },
  "required": [
    "billCode",
    "offset",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

canparl_search_members

open-world

Find current House MPs by name, riding, province, or caucus. Set includeFormer for OpenParliament's historical name index; historical rows may contain only a name and slug. Follow nextOffset with identical filters and use detailLookup with canparl_get_member.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_search_members",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "includeFormer": {
      "default": false,
      "description": "Use the sparse historical name index instead of the complete current official roster.",
      "type": "boolean"
    },
    "name": {
      "description": "Current: literal name substring. Historical: one token is surname lookup; multiple tokens are full recorded name lookup, not substring search.",
      "type": "string"
    },
    "riding": {
      "description": "Literal riding substring; current roster only.",
      "type": "string"
    },
    "province": {
      "description": "Province postal code or full English name; current roster only.",
      "type": "string"
    },
    "party": {
      "description": "Official caucus name; Bloc and Green aliases accepted; current roster only.",
      "type": "string"
    },
    "limit": {
      "default": 25,
      "description": "Maximum returned rows, 1–100 per call; larger values up to 10000 return 100 rows with a notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Zero-based offset in the selected ordering.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "includeFormer",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

canparl_get_member

open-world

Read one House MP by a returned OpenParliament slug or official current personId. Pass exactly one identifier from canparl_search_members detailLookup. Official profiles survive unavailable OpenParliament enrichment. Recent ballots come newest first from the official House member-votes feed when the member has one official personId, filterable by votesSession (default: the member's latest session) and votesBillCode; otherwise from OpenParliament. Sponsored bills and recent ballots are independently pageable; set their limits to zero for profile-only lookup.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_get_member",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "slug": {
      "description": "Returned OpenParliament slug, politician path, or HTTPS OpenParliament profile URL; never a guessed name. A digit-only value equal to a current official personId, or its /politicians/<digits>/ path or profile URL, is read as that personId.",
      "type": "string"
    },
    "personId": {
      "description": "Decimal official current person ID; distinct from an OpenParliament slug.",
      "type": "string"
    },
    "sponsoredBills": {
      "default": 5,
      "description": "Sponsored bill rows to hydrate, 0–5 per call; zero disables, and larger values up to 10000 hydrate 5 with a notice.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000
    },
    "billsOffset": {
      "default": 0,
      "description": "Zero-based sponsored bill page offset.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "recentVotes": {
      "default": 10,
      "description": "Ballot rows to return, 0–10 per call; zero disables, and larger values up to 10000 return 10 with a notice.",
      "type": "integer",
      "minimum": 0,
      "maximum": 10000
    },
    "votesOffset": {
      "default": 0,
      "description": "Zero-based ballot page offset.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "votesSession": {
      "description": "Official ballot session such as 44-1; omitted means the member's latest session in the feed. Needs one official personId.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d+-\\d+$",
          "description": "Parliament-session token, such as 45-1."
        },
        {
          "type": "object",
          "properties": {
            "parliament": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive parliament number."
            },
            "session": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive session number."
            }
          },
          "required": [
            "parliament",
            "session"
          ],
          "additionalProperties": false,
          "description": "Parliament and session numbers."
        }
      ]
    },
    "votesBillCode": {
      "description": "Keep official ballots on this bill, including a split-bill suffix such as C-15A; accepts c15, C 15, or bill C-15. Needs one official personId.",
      "type": "string"
    }
  },
  "required": [
    "sponsoredBills",
    "billsOffset",
    "recentVotes",
    "votesOffset"
  ],
  "additionalProperties": false
}
view source ↗

canparl_search_votes

open-world

Find recorded House divisions in one session by bill, result, document type, date, or subject. Return newest first and pass session plus number to canparl_get_vote. Omitted session resolves from the current official bill feed. Follow nextOffset with identical filters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_search_votes",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "session": {
      "description": "Parliamentary session; omitted means current.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d+-\\d+$",
          "description": "Parliament-session token, such as 45-1."
        },
        {
          "type": "object",
          "properties": {
            "parliament": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive parliament number."
            },
            "session": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive session number."
            }
          },
          "required": [
            "parliament",
            "session"
          ],
          "additionalProperties": false,
          "description": "Parliament and session numbers."
        }
      ]
    },
    "billCode": {
      "description": "Exact bill code, including a split-bill suffix letter such as C-15A; accepts bill s321, S321, S 321, or S-321.",
      "type": "string"
    },
    "result": {
      "description": "Official result from vote_results; Passed and Failed are accepted aliases.",
      "type": "string"
    },
    "documentType": {
      "description": "Official category from canparl_list_reference topic vote_document_types.",
      "type": "string"
    },
    "dateFrom": {
      "description": "Inclusive Ottawa civil date YYYY-MM-DD; independently optional.",
      "type": "string"
    },
    "dateTo": {
      "description": "Inclusive Ottawa civil date YYYY-MM-DD; independently optional.",
      "type": "string"
    },
    "subjectContains": {
      "description": "Literal Unicode-normalized case-insensitive subject substring.",
      "type": "string"
    },
    "limit": {
      "default": 25,
      "description": "Maximum returned rows, 1–100 per call; larger values up to 10000 return 100 rows with a notice.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Zero-based offset in the selected ordering.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

canparl_get_vote

open-world

Read a recorded House division, its full official tally, party totals, and a page of individual ballots. Ballot, personId, party, and province filters affect the ballot page only; nonvoters are absent. Omitted session means the verified current official session. Follow nextOffset with identical filters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_get_vote",
    "arguments": {
      "number": "<number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "session": {
      "description": "Parliamentary session; omitted means current.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d+-\\d+$",
          "description": "Parliament-session token, such as 45-1."
        },
        {
          "type": "object",
          "properties": {
            "parliament": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive parliament number."
            },
            "session": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive session number."
            }
          },
          "required": [
            "parliament",
            "session"
          ],
          "additionalProperties": false,
          "description": "Parliament and session numbers."
        }
      ]
    },
    "number": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "Division number returned by canparl_search_votes or canparl_get_bill."
    },
    "party": {
      "description": "Canonical official caucus or certain Bloc/Green alias; historical observed caucuses are accepted.",
      "type": "string"
    },
    "province": {
      "description": "English province/territory name or one of the 13 postal codes.",
      "type": "string"
    },
    "ballot": {
      "description": "Recorded ballot Yea, Nay, or Paired, case-insensitive; Yes and No are accepted as Yea and Nay.",
      "type": "string"
    },
    "personId": {
      "description": "Decimal official person ID from canparl_search_members detailLookup or a ballot row; matches this division's recorded participants, including members no longer seated.",
      "type": "string"
    },
    "limit": {
      "default": 30,
      "description": "Maximum returned ballots, 1–400 per call, default 30; larger values up to 10000 clamp to 400 with a notice. A page ends early at the 24000-byte response budget; follow nextOffset.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Zero-based offset in the selected ordering.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "number",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

canparl_search_speeches

open-world

Find indexed House Hansard speeches by speaker, bill debated or mentioned, or date. contains scans at most 100 candidate speeches per call; follow nextOffset without changing filters until exhausted before drawing a negative conclusion.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_search_speeches",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "politician": {
      "description": "Speaker OpenParliament slug or exact politician path/HTTPS URL (member.slug from canparl_get_member, or an includeFormer canparl_search_members row), or a current MP's official personId. A digit-only value equal to a current personId, or its /politicians/<digits>/ path or profile URL, is read as that personId.",
      "type": "string"
    },
    "billDebated": {
      "description": "Bill debated; combined with all other scopes using AND.",
      "type": "object",
      "properties": {
        "session": {
          "description": "Required explicit parliament-session for this bill.",
          "anyOf": [
            {
              "type": "string",
              "pattern": "^\\d+-\\d+$",
              "description": "Parliament-session token, such as 45-1."
            },
            {
              "type": "object",
              "properties": {
                "parliament": {
                  "type": "integer",
                  "exclusiveMinimum": 0,
                  "maximum": 9007199254740991,
                  "description": "Positive parliament number."
                },
                "session": {
                  "type": "integer",
                  "exclusiveMinimum": 0,
                  "maximum": 9007199254740991,
                  "description": "Positive session number."
                }
              },
              "required": [
                "parliament",
                "session"
              ],
              "additionalProperties": false,
              "description": "Parliament and session numbers."
            }
          ]
        },
        "code": {
          "description": "Required bill code, including a split-bill suffix letter such as C-15A; accepts bill s321, S321, S 321, or S-321.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "mentionedBill": {
      "description": "Bill mentioned; combined with all other scopes using AND.",
      "type": "object",
      "properties": {
        "session": {
          "description": "Required explicit parliament-session for this bill.",
          "anyOf": [
            {
              "type": "string",
              "pattern": "^\\d+-\\d+$",
              "description": "Parliament-session token, such as 45-1."
            },
            {
              "type": "object",
              "properties": {
                "parliament": {
                  "type": "integer",
                  "exclusiveMinimum": 0,
                  "maximum": 9007199254740991,
                  "description": "Positive parliament number."
                },
                "session": {
                  "type": "integer",
                  "exclusiveMinimum": 0,
                  "maximum": 9007199254740991,
                  "description": "Positive session number."
                }
              },
              "required": [
                "parliament",
                "session"
              ],
              "additionalProperties": false,
              "description": "Parliament and session numbers."
            }
          ]
        },
        "code": {
          "description": "Required bill code, including a split-bill suffix letter such as C-15A; accepts bill s321, S321, S 321, or S-321.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "dateFrom": {
      "description": "Inclusive Ottawa civil date lower bound, YYYY-MM-DD; independently optional.",
      "type": "string"
    },
    "dateTo": {
      "description": "Inclusive Ottawa civil date upper bound, YYYY-MM-DD; independently optional.",
      "type": "string"
    },
    "substantiveOnly": {
      "default": true,
      "description": "Exclude procedural remarks when true; false includes substantive and procedural remarks.",
      "type": "boolean"
    },
    "contains": {
      "description": "Local case-insensitive Unicode-normalized literal English text substring; cannot be the only scope.",
      "type": "string"
    },
    "limit": {
      "default": 5,
      "description": "Maximum returned matches, 1–10 per call; larger values up to 10000 clamp to 10 with a notice. A page ends early at the 24000-byte response budget, returning at least one match whole. Candidate pages contain 20 rows.",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Raw candidate offset; keep every filter identical when continuing.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "substantiveOnly",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

canparl_list_reference

open-world

List canonical session coverage and bill, division, and caucus vocabulary. Use source-specific terms when constructing filters. Omitted session means the verified current session for vocabulary. For topic sessions omit session; the entire global index is returned.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "canparl_list_reference",
    "arguments": {
      "topic": "<topic>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "topic": {
      "type": "string",
      "enum": [
        "sessions",
        "bill_types",
        "bill_statuses",
        "vote_results",
        "vote_document_types",
        "parties"
      ],
      "description": "Reference topic used to construct source-specific filters."
    },
    "session": {
      "description": "Parliamentary session; omitted means current.",
      "anyOf": [
        {
          "type": "string",
          "pattern": "^\\d+-\\d+$",
          "description": "Parliament-session token, such as 45-1."
        },
        {
          "type": "object",
          "properties": {
            "parliament": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive parliament number."
            },
            "session": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 9007199254740991,
              "description": "Positive session number."
            }
          },
          "required": [
            "parliament",
            "session"
          ],
          "additionalProperties": false,
          "description": "Parliament and session numbers."
        }
      ]
    }
  },
  "required": [
    "topic"
  ],
  "additionalProperties": false
}
view source ↗