Back to the catalog

CanLII

MCP for CanLII: Canadian case law and legislation metadata (federal, provincial, territorial).

Open source Repository Open in the app JSON README (API)

About

MCP for CanLII: Canadian case law and legislation metadata (federal, provincial, territorial).

Details

Kind
MCP servers
Topic
Government & public data
Publisher
vaquill-ai
Origin
official
Category
ferramentas
Transport
http
Version
0.1.0
Stars
5
Forks
1
Last push
2026-07-09T04:40:52Z
Repository state
ativo
Language
TypeScript
License
MIT
Added
2026-08-29 03:02:18
Updated
2026-08-29 03:02:18
Origin id
io.github.Vaquill-AI/canlii-mcp

README

# canlii-mcp

An [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.

> **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.

> **Note:** The CanLII API provides metadata only — titles, citations, dates, keywords, and citation relationships. Full document text is not available through the API.

## Use the hosted endpoint (no install)

```
https://canlii-mcp.vaquill.ai/mcp
```

The hosted instance is public. No Vaquill token is required. Provide your own CanLII key one of two ways:

- **Header (recommended, keeps the key out of the URL):** `X-CanLII-Token: <your_canlii_api_key>`
- **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:

  ```
  https://canlii-mcp.vaquill.ai/mcp?token=YOUR_CANLII_API_KEY
  ```

Apply 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.

### Claude Desktop / Claude Code

```json
{
  "mcpServers": {
    "canlii": {
      "url": "https://canlii-mcp.vaquill.ai/mcp",
      "headers": {
        "X-CanLII-Token": "YOUR_CANLII_API_KEY"
      }
    }
  }
}
```

### Cursor / VS Code / Windsurf

Same pattern: any client supporting MCP streamable HTTP with custom headers works. For stdio-only clients use `mcp-remote` to proxy.

## Authentication

| Mode | Header | When |
|---|---|---|
| BYOK header (preferred) | `X-CanLII-Token: <key>` | Hosted / shared deployments |
| BYOK URL param | `?token=<key>` (or `?canlii_token=`) | Header-less clients: Claude Desktop connector UI, claude.ai web |
| Server fallback | (env `CANLII_API`) | Self-hosted single-tenant. Required for stdio. |
| 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. |

## Tools

| Tool | Description |
|------|-------------|
| `list_case_databases` | List all courts and tribunals in the CanLII collection |
| `list_cases` | Browse decisions from a specific court/tribunal database |
| `get_case` | Get metadata for a specific case (title, citation, date, keywords) |
| `get_case_citations` | Get cases cited by a case, cases citing it, or legislation it references |
| `list_legislation_databases` | List all statute and regulation databases |
| `list_legislation` | Browse statutes or regulations from a specific database |
| `get_legislation` | Get metadata for a specific piece of legislation |

## Requirements

- Node.js 22+
- A CanLII API key — [apply here](https://www.canlii.org/en/feedback/feedback.html)

## Usage

### stdio via npx (quickest)

```json
{
  "mcpServers": {
    "canlii": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@tomilashy/canlii-mcp"],
      "env": {
        "CANLII_API": "your_api_key"
      }
    }
  }
}
```

### stdio (from source)

```bash
npm install
npm run build
node dist/index.js
```

Add to your MCP config:

```json
{
  "mcpServers": {
    "canlii": {
      "command": "node",
      "args": ["/path/to/canlii-mcp/dist/index.js"],
      "env": {
        "CANLII_API": "your_api_key"
      }
    }
  }
}
```

### HTTP server

```bash
PORT=3000 CANLII_API=your_api_key node dist/index.js --transport http
```

The 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:

```bash
curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_case_databases","arguments":{"language":"en"}}}'
```

### Docker

```bash
docker run -e CANLII_API=your_api_key -e MCP_AUTH_TOKEN=your_secret -p 3000:3000 ghcr.io/tomilashy/canlii-mcp
```

Or with Docker Compose:

```yaml
services:
  canlii-mcp:
    image: ghcr.io/tomilashy/canlii-mcp
    environment:
      CANLII_API: your_api_key
      MCP_AUTH_TOKEN: your_secret  # optional
    ports:
      - "3000:3000"
```

### Cloudflare Workers

The server includes a Workers-compatible entry point (`src/worker.ts`).

#### CLI deploy

```bash
npx wrangler secret put CANLII_API
npx wrangler secret put MCP_AUTH_TOKEN  # optional
npx wrangler deploy
```

#### Dashboard deploy (Connect to Git)

1. Go to [Cloudflare Dashboard](https://dash.cloudflare.com) → **Workers & Pages** → **Create** → **Connect to Git**
2. Select your `tomilashy/canlii-mcp` repository
3. On the **Set up your application** page:
   - **Project name**: `canlii-mcp`
   - **Build command**: `npm install && npm run build`
   - **Deploy command**: `npx wrangler deploy` (pre-filled)
4. Expand **Advanced settings**:
   - **Variable name**: `CANLII_API`
   - **Variable value**: your CanLII API key
   - Check **Encrypt** to store it as a secret
5. Click **Deploy**

The MCP endpoint will be at `https://canlii-mcp.<your-subdomain>.workers.dev/mcp`.

## Configuration

| Environment Variable | Required | Default | Description |
|---------------------|----------|---------|-------------|
| `CANLII_API` | Yes | — | Your CanLII API key |
| `PORT` | No | `3000` | HTTP server port (HTTP mode only) |
| `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. |

## Rate Limits

The server enforces CanLII's API limits automatically, **per CanLII key**, so one caller's usage never throttles another's:

- 1 request at a time
- 2 requests per second
- 5,000 requests per day

These 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.

## Development

```bash
npm install
npm run build      # compile TypeScript
npm run watch      # watch mode
```

## Release

This 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:

| Commit prefix | Release type |
|---------------|-------------|
| `fix:` | Patch (`1.0.0` → `1.0.1`) |
| `feat:` | Minor (`1.0.0` → `1.1.0`) |
| `feat!:` or `BREAKING CHANGE` | Major (`1.0.0` → `2.0.0`) |

Pushing to `main` triggers the release workflow. If a release is cut, the Docker image is automatically built and published to `ghcr.io`.

## License

MIT

More