{
  "markdown": "# canlii-mcp\n\nAn [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server for the [CanLII](https://www.canlii.org) Canadian legal information API. Gives AI assistants access to Canadian case law and legislation metadata across all federal, provincial, and territorial jurisdictions.\n\n> **Forked from** [tomilashy/canlii-mcp](https://github.com/tomilashy/canlii-mcp). This fork adds bring-your-own-key (BYOK) auth, a `/health` route, and a hosted endpoint at `canlii-mcp.vaquill.ai`. Tools are unchanged.\n\n> **Note:** The CanLII API provides metadata only — titles, citations, dates, keywords, and citation relationships. Full document text is not available through the API.\n\n[![Discord](https://img.shields.io/badge/Discord-Join%20the%20community-5865F2?logo=discord&logoColor=white)](https://discord.gg/GQtnwxf8nQ)\n\n## Use the hosted endpoint (no install)\n\n```\nhttps://canlii-mcp.vaquill.ai/mcp\n```\n\nThe hosted instance is public. No Vaquill token is required. Provide your own CanLII key one of two ways:\n\n- **Header (recommended, keeps the key out of the URL):** `X-CanLII-Token: <your_canlii_api_key>`\n- **URL parameter (simplest; works in header-less clients like the Claude Desktop connector UI and claude.ai web):** append `?token=<your_canlii_api_key>` to the URL:\n\n  ```\n  https://canlii-mcp.vaquill.ai/mcp?token=YOUR_CANLII_API_KEY\n  ```\n\nApply for a key at [canlii.org/en/api/](https://www.canlii.org/en/feedback/feedback.html). The server never stores your key, and there is no server-side fallback key, so every call counts against your own CanLII quota.\n\n### Claude Desktop / Claude Code\n\n```json\n{\n  \"mcpServers\": {\n    \"canlii\": {\n      \"url\": \"https://canlii-mcp.vaquill.ai/mcp\",\n      \"headers\": {\n        \"X-CanLII-Token\": \"YOUR_CANLII_API_KEY\"\n      }\n    }\n  }\n}\n```\n\n### Cursor / VS Code / Windsurf\n\nSame pattern: any client supporting MCP streamable HTTP with custom headers works. For stdio-only clients use `mcp-remote` to proxy.\n\n## Authentication\n\n| Mode | Header | When |\n|---|---|---|\n| BYOK header (preferred) | `X-CanLII-Token: <key>` | Hosted / shared deployments |\n| BYOK URL param | `?token=<key>` (or `?canlii_token=`) | Header-less clients: Claude Desktop connector UI, claude.ai web |\n| Server fallback | (env `CANLII_API`) | Self-hosted single-tenant. Required for stdio. |\n| MCP gate | `Authorization: Bearer <MCP_AUTH_TOKEN>` | Optional, self-host only. The public hosted endpoint at `canlii-mcp.vaquill.ai` does **not** use it, so no bearer token is required. |\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `list_case_databases` | List all courts and tribunals in the CanLII collection |\n| `list_cases` | Browse decisions from a specific court/tribunal database |\n| `get_case` | Get metadata for a specific case (title, citation, date, keywords) |\n| `get_case_citations` | Get cases cited by a case, cases citing it, or legislation it references |\n| `list_legislation_databases` | List all statute and regulation databases |\n| `list_legislation` | Browse statutes or regulations from a specific database |\n| `get_legislation` | Get metadata for a specific piece of legislation |\n\n## Requirements\n\n- Node.js 22+\n- A CanLII API key — [apply here](https://www.canlii.org/en/feedback/feedback.html)\n\n## Usage\n\n### stdio via npx (quickest)\n\n```json\n{\n  \"mcpServers\": {\n    \"canlii\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@tomilashy/canlii-mcp\"],\n      \"env\": {\n        \"CANLII_API\": \"your_api_key\"\n      }\n    }\n  }\n}\n```\n\n### stdio (from source)\n\n```bash\nnpm install\nnpm run build\nnode dist/index.js\n```\n\nAdd to your MCP config:\n\n```json\n{\n  \"mcpServers\": {\n    \"canlii\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/canlii-mcp/dist/index.js\"],\n      \"env\": {\n        \"CANLII_API\": \"your_api_key\"\n      }\n    }\n  }\n}\n```\n\n### HTTP server\n\n```bash\nPORT=3000 CANLII_API=your_api_key node dist/index.js --transport http\n```\n\nThe MCP endpoint is available at `http://localhost:3000/mcp`. The server runs in stateless mode — each request is self-contained, no session ID or initialize handshake required. Clients can call tools directly:\n\n```bash\ncurl -X POST http://localhost:3000/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/call\",\"params\":{\"name\":\"list_case_databases\",\"arguments\":{\"language\":\"en\"}}}'\n```\n\n### Docker\n\n```bash\ndocker run -e CANLII_API=your_api_key -e MCP_AUTH_TOKEN=your_secret -p 3000:3000 ghcr.io/tomilashy/canlii-mcp\n```\n\nOr with Docker Compose:\n\n```yaml\nservices:\n  canlii-mcp:\n    image: ghcr.io/tomilashy/canlii-mcp\n    environment:\n      CANLII_API: your_api_key\n      MCP_AUTH_TOKEN: your_secret  # optional\n    ports:\n      - \"3000:3000\"\n```\n\n### Cloudflare Workers\n\nThe server includes a Workers-compatible entry point (`src/worker.ts`).\n\n#### CLI deploy\n\n```bash\nnpx wrangler secret put CANLII_API\nnpx wrangler secret put MCP_AUTH_TOKEN  # optional\nnpx wrangler deploy\n```\n\n#### Dashboard deploy (Connect to Git)\n\n1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) → **Workers & Pages** → **Create** → **Connect to Git**\n2. Select your `tomilashy/canlii-mcp` repository\n3. On the **Set up your application** page:\n   - **Project name**: `canlii-mcp`\n   - **Build command**: `npm install && npm run build`\n   - **Deploy command**: `npx wrangler deploy` (pre-filled)\n4. Expand **Advanced settings**:\n   - **Variable name**: `CANLII_API`\n   - **Variable value**: your CanLII API key\n   - Check **Encrypt** to store it as a secret\n5. Click **Deploy**\n\nThe MCP endpoint will be at `https://canlii-mcp.<your-subdomain>.workers.dev/mcp`.\n\n## Configuration\n\n| Environment Variable | Required | Default | Description |\n|---------------------|----------|---------|-------------|\n| `CANLII_API` | Yes | — | Your CanLII API key |\n| `PORT` | No | `3000` | HTTP server port (HTTP mode only) |\n| `MCP_AUTH_TOKEN` | No | — | Bearer token for HTTP authentication. If set, all HTTP requests must include `Authorization: Bearer <token>`. If not set, the server runs without authentication. |\n\n## Rate Limits\n\nThe server enforces CanLII's API limits automatically, **per CanLII key**, so one caller's usage never throttles another's:\n\n- 1 request at a time\n- 2 requests per second\n- 5,000 requests per day\n\nThese mirror CanLII's own per-key limits. Each `X-CanLII-Token` gets its own independent budget (keyed by a hash of the key; raw keys are never retained). Requests that exceed the daily limit return an error rather than hitting the API.\n\n## Development\n\n```bash\nnpm install\nnpm run build      # compile TypeScript\nnpm run watch      # watch mode\n```\n\n## Release\n\nThis project uses [Semantic Versioning](https://semver.org) via [semantic-release](https://semantic-release.gitbook.io). Commit messages follow the [Conventional Commits](https://www.conventionalcommits.org) spec:\n\n| Commit prefix | Release type |\n|---------------|-------------|\n| `fix:` | Patch (`1.0.0` → `1.0.1`) |\n| `feat:` | Minor (`1.0.0` → `1.1.0`) |\n| `feat!:` or `BREAKING CHANGE` | Major (`1.0.0` → `2.0.0`) |\n\nPushing to `main` triggers the release workflow. If a release is cut, the Docker image is automatically built and published to `ghcr.io`.\n\n## License\n\nMIT\n\n## Community\n\nQuestions, ideas, or want to contribute? Join the Vaquill community on [Discord](https://discord.gg/GQtnwxf8nQ).\n",
  "bytes": 7396,
  "sha": "9452525fc360345e806ec62d7e9f0fded19a5b17d38b277eda0a55b2d47443c0",
  "repo_slug": "vaquill-ai/canlii-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_vaquill_ai_canlii_mcp_95183cbb/readme"
}