Skip to main content
Glama
README.md
# šŸ‡ØšŸ‡¦ Bank of Canada Valet MCP Server

[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![MCP](https://img.shields.io/badge/protocol-MCP-6E56CF.svg)](https://modelcontextprotocol.io)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![CI](https://github.com/Chatusvi-Karnati/boc-valet-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/Chatusvi-Karnati/boc-valet-mcp/actions)

An [MCP](https://modelcontextprotocol.io) server that gives LLM agents (Claude, and any other MCP-compatible client) live access to Canadian economic and financial data through the **[Bank of Canada Valet API](https://www.bankofcanada.ca/valet/docs)** — exchange rates, interest rates, inflation series, and thousands more.

The Valet API is **free and requires no API key**, so this server runs out of the box.

> Ask *"What's the latest USD/CAD exchange rate?"* or *"Chart CORRA over the last month"* and the agent pulls the numbers straight from the source.

---

## Why this exists

Large language models don't know today's exchange rate — their training data is frozen in the past. MCP closes that gap by letting a model call live tools. This server is a small, focused, production-shaped example of that pattern: clean tool design, input validation, actionable errors, and tests.

## Features

- **5 well-scoped tools** covering discovery → metadata → data retrieval
- **No API key** — the Valet API is public
- **Dual output** — human-readable Markdown or structured JSON, per call
- **Search + pagination** over the large series/group catalogue
- **Multi-series comparison** — pull several series side by side in one call
- **Agent-friendly errors** — every failure explains what to try next
- **Typed & validated** — Pydantic `Field` constraints on every parameter
- **Tested** — offline unit tests, no network needed for CI

## Tools

| Tool | What it does |
|------|--------------|
| `boc_list_series` | Search / list the available data series (start here) |
| `boc_list_groups` | Search / list curated groups of related series |
| `boc_get_series_info` | Fetch metadata (label, description) for one series |
| `boc_get_observations` | **Core:** get data points for one or more series, by date range or most-recent |
| `boc_get_group_observations` | Get every series in a group in a single call |

## Architecture

```
src/boc_valet_mcp/
ā”œā”€ā”€ server.py       # MCP tool definitions (the interface agents see)
ā”œā”€ā”€ client.py       # Async httpx client + centralized, actionable errors
└── formatting.py   # Markdown / JSON rendering (shared by every tool)
```

The separation keeps each layer testable: tools stay thin, HTTP concerns live in one place, and presentation logic is unit-tested offline against representative payloads.

## Quickstart

```bash
git clone https://github.com/Chatusvi-Karnati/boc-valet-mcp.git
cd boc-valet-mcp
python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e .
```

Run it directly (it speaks MCP over stdio):

```bash
boc-valet-mcp
```

### Inspect it interactively

The MCP Inspector is the fastest way to click through the tools:

```bash
npx @modelcontextprotocol/inspector boc-valet-mcp
```

### Use it with Claude Desktop

Add this to your `claude_desktop_config.json` (see [`examples/`](examples/claude_desktop_config.json)):

```json
{
  "mcpServers": {
    "bank-of-canada": {
      "command": "boc-valet-mcp"
    }
  }
}
```

Restart Claude Desktop and ask it something like *"Compare the USD/CAD and EUR/CAD rates over the past week."*

## Example

Calling `boc_get_observations` with `series_names="FXUSDCAD"`, `recent=1`:

```
**Series:**
- `FXUSDCAD` — US dollar to Canadian dollar daily exchange rate

| Date       | FXUSDCAD |
|------------|----------|
| 2024-06-03 | 1.3654   |

_1 observation(s)._
```

## Development

```bash
pip install -e ".[dev]"
pytest              # run the test suite
ruff check .        # lint
```

## How it was built

Designed and built following Anthropic's MCP server best practices — comprehensive tool coverage, `readOnly`/`idempotent` annotations, Pydantic-validated inputs, and error messages written for an agent audience. Developed with an AI-assisted workflow using Claude Code.

## License

MIT — see [LICENSE](LICENSE).

## Acknowledgements

Data is provided by the [Bank of Canada Valet API](https://www.bankofcanada.ca/valet/docs). This project is not affiliated with or endorsed by the Bank of Canada. Please review the Bank of Canada's [terms of use](https://www.bankofcanada.ca/terms/) for the data.

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clear, distinct purpose: listing series, listing groups, getting series metadata, getting observations for series, and getting observations for groups. No overlap.

Naming Consistency5/5

All tools follow a consistent 'boc_verb_noun' pattern (e.g., boc_list_series, boc_get_observations), making it easy to infer functionality.

Tool Count5/5

With 5 tools, the server is focused and each tool earns its place. The count is ideal for a read-only economic data API.

Completeness4/5

Covers discovery and retrieval for both individual series and groups. Missing a dedicated tool for group metadata, but the list tool provides enough context.

Maintenance

ActivitySlowing
ResponsivenessNo issues