Skip to main content
Glama
swiss-snb-mcp

swiss-snb-mcp

by malkreide

🇨🇭 Part of the Swiss Public Data MCP Portfolio

🏦 swiss-snb-mcp

Version License: MIT Python 3.11+ MCP Data Source CI

MCP server for the Swiss National Bank (SNB) data portal — exchange rates, balance sheet, interest rates, SARON, monetary aggregates, banking statistics, and balance of payments.

🇩🇪 Deutsche Version


Overview

swiss-snb-mcp connects AI models to the official Swiss National Bank data portal at data.snb.ch via the Model Context Protocol (MCP). It provides structured access to SNB's public REST API — no authentication required.

The server covers three tiers of datasets, all confirmed against the live API:

Phase 1 — Dedicated tools:

  • Exchange rates (monthly averages, month-end rates, annual averages) for the 28 currency series devkum publishes against CHF — including two USD forward rates, which are labelled as such

  • SNB balance sheet (Bilanz): gold reserves, foreign exchange investments, banknotes in circulation, sight deposits, and totals

Phase 2 — Via generic cube tools (snb_get_cube_data + snb_get_cube_metadata):

  • SNB policy rate (Leitzins) and SARON daily fixing, emergency facility rate, sight deposit rates

  • SARON compound rates: Overnight, 1M, 3M, 6M

  • International money market rates: SARON (CH), SOFR (USA), TONA (JP), SONIA (UK), €STR/EURIBOR (EZ)

  • Official central bank rates: SNB, Fed, ECB, Bank of England, Bank of Japan

  • Monetary aggregates M1, M2, M3: stock levels and year-on-year changes

Phase 3 — Warehouse API (banking statistics) and balance of payments:

  • Banking balance sheets (BSTA BIL): total assets and liabilities by bank group — annual and monthly

  • Banking income statements (BSTA EFR): operating income, expenses, taxes by bank group — annual

  • Balance of payments: current account, capital account, financial account (quarterly)

  • International investment position: components by investment type (quarterly)

  • Generic warehouse access: raw access to any SNB Warehouse cube by ID

Anchor demo query: "What was the EUR/CHF exchange rate during the 2015 Franc shock, and where does the SNB policy rate stand today compared to the Fed and ECB?"


Related MCP server: swiss-statistics-mcp

Features

  • 💱 Exchange rates — monthly CHF rates for EUR, USD, JPY, GBP, CNY and 23 more series

  • 📅 Annual averages — year-by-year rates from 1980 onwards

  • 🏛️ SNB balance sheet — gold, foreign exchange investments, banknotes, sight deposits (monthly)

  • 🔄 Currency conversion — convert any amount to CHF using official SNB rates

  • 📈 Policy rate & SARON — daily fixing, Leitzins, compound rates (1M/3M/6M)

  • 🌍 International rate comparison — SNB, Fed, ECB, Bank of England, Bank of Japan side by side

  • 💰 Monetary aggregates — M1, M2, M3 stock levels and year-on-year growth

  • 🏦 Banking statistics — balance sheets and income statements by bank group (12 groups)

  • 📊 Balance of payments — current account, IIP, and international investment position

  • 🔍 Generic cube access — query any SNB data cube or Warehouse cube by ID

  • 🔓 No authentication required — fully public SNB data portal


Prerequisites

  • Python 3.11+

  • uv or pip

  • MCP-compatible client (Claude Desktop, Claude Code, or any MCP host)


Installation

Via uvx (recommended — no permanent installation needed):

uvx swiss-snb-mcp

Via pip:

pip install swiss-snb-mcp

From source:

git clone https://github.com/malkreide/swiss-snb-mcp.git
cd swiss-snb-mcp
pip install -e .

Usage / Quickstart

Claude Desktop — add to claude_desktop_config.json:

{
  "mcpServers": {
    "swiss-snb-mcp": {
      "command": "uvx",
      "args": ["swiss-snb-mcp"]
    }
  }
}

Config file locations:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Try it immediately in Claude Desktop:

"What is the current EUR/CHF exchange rate according to the SNB?" "Show me the SNB balance sheet for the last 12 months — gold and foreign reserves."


Configuration

No API key or authentication required. The SNB data portal is fully public.

Optional environment variable:

Variable

Default

Description

SNB_TIMEOUT

15

HTTP request timeout in seconds


Available Tools

Phase 1 — Dedicated Tools

Tool

Description

snb_get_exchange_rates

Monthly CHF rates for EUR, USD, JPY, GBP, CNY and 22 more currencies

snb_get_annual_exchange_rates

Annual average rates, data from 1980

snb_get_balance_sheet

SNB Bilanz positions in millions CHF (monthly)

snb_convert_currency

Convert any amount to CHF using official SNB rates

Phase 2 — Generic Cube Tools

Tool

Description

snb_get_cube_data

Generic access to any SNB cube by ID

snb_get_cube_metadata

Inspect dimensions and filter values of any cube

Phase 3 — Warehouse API (Banking Statistics) and Balance of Payments

Tool

Description

snb_get_banking_balance_sheet

Banking balance sheets by bank group (monthly/annual, assets/liabilities)

snb_get_banking_income

Banking income statements by bank group (annual)

snb_get_balance_of_payments

Balance of payments and international investment position (quarterly)

snb_get_warehouse_data

Generic access to any SNB Warehouse cube by ID

snb_get_warehouse_metadata

Inspect dimensions and last update of a Warehouse cube

Resources (static catalogs)

Discovery aids served as MCP resources rather than tools so they don't crowd the tool manifest:

URI

Description

data://snb/currencies

All 28 currency IDs with labels and units

data://snb/balance-sheet-positions

Asset and liability position IDs

data://snb/cubes

All verified Cube-API IDs (Phase 1–2) + discovery guide

data://snb/warehouse-cubes

Available Warehouse cube IDs (BSTA)

data://snb/bank-groups

All 12 bank group IDs with labels

Example Use Cases

Query

Tool

"What is the current EUR/CHF rate?"

snb_get_exchange_rates

"Convert CHF 10,000 to USD"

snb_convert_currency

"Show SNB gold reserves over the last year"

snb_get_balance_sheet

"What is the current SNB policy rate?"

snb_get_cube_data (cube: snbgwdzid)

"How do SNB, Fed and ECB rates compare?"

snb_get_cube_data (cube: snboffzisa)

"What is the SARON 3M compound rate?"

snb_get_cube_data (cube: zirepo)

"How fast is M3 money supply growing?"

snb_get_cube_data (cube: snbmonagg)

"Total assets of all Swiss banks?"

snb_get_banking_balance_sheet

"Income statement of cantonal banks?"

snb_get_banking_income (bank_group: G10)

"Switzerland's balance of payments?"

snb_get_balance_of_payments

"Which cubes are available?"

resource data://snb/cubes

→ More use cases by audience →


Safety & Limits

Aspect

Details

Access

Read-only (readOnlyHint: true) — the server cannot modify or delete any data

Personal data

No personal data — all sources are aggregated, public macroeconomic statistics

Rate limits

SNB Warehouse API has WAF protection (HTTP 503 after ~100 rapid requests); the server retries automatically with exponential backoff (max 3 retries, delays 2/4/8s)

Timeout

15 seconds per API call

Authentication

No API keys required — both APIs (/api/cube/ and /api/warehouse/cube/) are publicly accessible

Data source

Swiss National Bank — data.snb.ch

Terms of Service

Subject to SNB's Terms of Use and Copyright; data is free for non-commercial use with source attribution


Architecture

┌─────────────────┐     ┌───────────────────────────┐     ┌──────────────────────┐
│   Claude / AI   │────▶│     Swiss SNB MCP         │────▶│     data.snb.ch      │
│   (MCP Host)    │◀────│     (MCP Server)          │◀────│                      │
└─────────────────┘     │                           │     │  /api/cube/ (JSON)   │
                        │  11 Tools · 5 Resources   │     │  /api/warehouse/     │
                        │  Stdio | SSE              │     │  Public · No Auth    │
                        │                           │     │                      │
                        │  Phase 1: dedicated tools │     │  Exchange rates      │
                        │  Phase 2: generic cubes   │     │  Balance sheet       │
                        │  Phase 3: warehouse +     │     │  Interest rates      │
                        │           banking stats   │     │  Banking statistics  │
                        └───────────────────────────┘     │  Balance of payments │
                                                          └──────────────────────┘

Cube Discovery Pattern

The SNB API follows a consistent cube-based structure. Read the data://snb/cubes resource to explore verified cube IDs, then snb_get_cube_metadata to inspect dimensions before querying with snb_get_cube_data. Phase 3 adds the Warehouse API (/api/warehouse/cube/) for granular banking statistics — start from the data://snb/warehouse-cubes and data://snb/bank-groups resources.


Project Structure

swiss-snb-mcp/
├── src/
│   └── swiss_snb_mcp/
│       ├── __init__.py
│       ├── server.py       # Core tools and FastMCP server (Phase 1–2 + BoP)
│       └── warehouse.py    # Warehouse API tools (Phase 3: banking statistics)
├── scripts/
│   └── record_fixtures.py          # records tests/fixtures/* from data.snb.ch
├── tests/
│   ├── fixtures/                   # recorded responses + PROVENANCE.md (date, rule, SHA-256)
│   ├── fixture_data.py             # loader — a missing name is an error, not an empty dict
│   ├── test_unit.py                # respx-mocked unit tests (run in CI)
│   ├── test_live_scenarios.py      # 20 live scenarios for Phase 1–2 (nightly)
│   └── test_live_warehouse.py      # 20 live scenarios for Phase 3 (nightly)
├── pyproject.toml          # Build configuration (hatchling)
├── CHANGELOG.md
├── CONTRIBUTING.md         # Contribution guidelines (English)
├── CONTRIBUTING.de.md      # German version
├── SECURITY.md             # Security policy & posture (English)
├── SECURITY.de.md          # German version
├── LICENSE
├── README.md               # This file (English)
└── README.de.md            # German version

Known Limitations

  • Exchange rates: Monthly averages only — no intraday or daily rates available via this API

  • Balance sheet: Monthly data; some positions may have a publication lag of 1–2 months

  • Cube access: Cube IDs are not officially documented by the SNB — read the data://snb/cubes resource for verified IDs

  • Historical depth: Coverage varies by series; exchange rates go back to 1980, some interest rate series start later

  • No forecasts: All data is historical/realised — SNB does not publish forecasts via this API


MCP Protocol Version

This server speaks two protocol eras over the same endpoint. The client's first request on a connection decides which one applies; a later claim from the other era is refused.

Era

Revision

Who reaches it

initialize handshake

2024-11-05 … 2025-11-25

What today's clients speak. The server answers with the revision asked for, or with the 2025-11-25 ceiling when the request asks for something newer.

Per-request envelope

2026-07-28

A request carrying the 2026-07-28 _meta envelope opens a modern connection.

Both revisions are pinned in tests/test_protocol_version.py and asserted against the installed SDK, so a Dependabot bump of mcp cannot move either one silently.

The table above is measured, not inferred. The same gate drives the server's real serving loop over an in-memory stream pair — the loop stdio runs in production — and sends actual JSON-RPC frames through it: an enveloped request is served at 2026-07-28, an initialize asking for 2026-07-28 is answered 2025-11-25, and a claim from the other era is refused on an already-decided connection (-32022 one way, -32600 the other). An earlier revision of this section claimed the measurement needed an ASGI app; it does not — the modern era has no initialize, and the handshake never rode on HTTP to begin with.

What the server reports about itself is measured the same way, in tests/test_server_identity.py: the package version and the project URL are read back off the wire, not off the constructor.

Note that the SDK's LATEST_PROTOCOL_VERSION is an alias for the modern era, not for the handshake era — pinning against it alone would leave the era that current clients actually negotiate free to drift.

Update policy. When the gate fails, do not edit the constant blindly: read the spec changelog between the two revisions, verify the server still behaves, then move the constant, this section, README.de.md and CHANGELOG.md together.


Testing

# Unit tests (no API key required)
PYTHONPATH=src pytest tests/ -m "not live"

# Integration tests (live SNB API)
PYTHONPATH=src pytest tests/ -m "live"

# Re-record the fixtures from data.snb.ch (writes tests/fixtures/PROVENANCE.md)
python scripts/record_fixtures.py

The unit-test payloads are recorded, not invented. Source, retrieval date, selection rule and SHA-256 per file are in tests/fixtures/PROVENANCE.md. A hand-written mock encodes its author's assumption and can therefore never refute it — production code and fixture come from the same head, so where both are wrong, both are wrong together and the suite stays green. Each file keeps every series and only shortens the value lists: the code reasons about the dimensions and merely displays the values, so cutting "the first N series" would have hidden exactly what three of the findings depended on.


Changelog

See CHANGELOG.md


Contributing

See CONTRIBUTING.md for guidelines on reporting issues, suggesting new SNB cube IDs, and contributing code.


Security

This server is read-only, processes no personal data, and talks only to data.snb.ch. See SECURITY.md for the full security posture, audit results, and how to report a vulnerability.


License

MIT License — see LICENSE


Author

Hayal Oezkan · github.com/malkreide


Installation

Run via uv's uvx — no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):

{
  "mcpServers": {
    "swiss-snb-mcp": {
      "command": "uvx",
      "args": [
        "swiss-snb-mcp"
      ]
    }
  }
}

Available Tools

11 tools
snb_convert_currencyA
Read-onlyIdempotent

Convert a foreign currency amount to CHF using official SNB exchange rates.

Uses the monthly average rate (Monatsmittel) from the SNB data portal. Suitable for budget calculations, cost estimations, and financial planning.

Args: params (ConvertCurrencyInput): - amount: Amount in foreign currency to convert. - currency_id: SNB currency ID (e.g. 'EUR1', 'USD1', 'JPY100'). - reference_month: Month YYYY-MM for the rate. Default: most recent.

Returns: str: CHF equivalent, exchange rate used, and reference date.

Example: amount=45000, currency_id='USD1' → CHF equivalent of USD 45,000 amount=100, currency_id='JPY100' → CHF equivalent of JPY 100

Inputs: params (required). Returns: result

snb_get_annual_exchange_ratesA
Read-onlyIdempotent

Retrieve annual average CHF exchange rates from the SNB (cube 'devkua').

Returns yearly average exchange rates for all major currencies against CHF. Useful for multi-year trend analysis, budget planning, and financial reporting. Data goes back to 1980 for most currencies.

Args: params (AnnualExchangeRatesInput): - currencies: List of currency IDs (e.g. ['EUR1', 'USD1']). Default: all. - from_year: Start year, e.g. '2015'. Default: 5 years ago. - to_year: End year, e.g. '2025'. Default: current year. - lang: Response language. Default: de.

Returns: str: Markdown summary and JSON data with annual exchange rates.

Inputs: params (required). Returns: result

snb_get_balance_of_paymentsA
Read-onlyIdempotent

Retrieve balance-of-payments or international investment position data.

Categories:

  • overview: Zahlungsbilanz — Übersicht (cube bopoverq)

  • iip: Auslandvermögen — Komponenten (cube auvekomq)

Args: params (BalanceOfPaymentsInput): - category: 'overview' or 'iip'. - from_date: Start date, e.g. '2020-Q1' or '2020'. - to_date: End date. - lang: Response language (de/en/fr).

Returns: str: Markdown summary with JSON data.

Inputs: params (required). Returns: result

snb_get_balance_sheetA
Read-onlyIdempotent

Retrieve SNB balance sheet (Bilanz) data from the data portal (cube 'snbbipo').

Returns monthly balance sheet positions of the Swiss National Bank in millions of CHF. Covers assets (gold, foreign exchange reserves, repos) and liabilities (banknotes in circulation, sight deposits of domestic banks, government deposits).

Key positions:

  • GFG: Gold und Forderungen aus Goldgeschäften

  • D: Devisenanlagen (foreign exchange reserves — the world's largest relative to GDP)

  • N: Notenumlauf (banknotes in circulation)

  • GB: Girokonten inländischer Banken (sight deposits)

  • T0/T1: Total Aktiven / Total Passiven

Args: params (BalanceSheetInput): - positions: List of position IDs. Default: key positions (GFG, D, N, GB, T0, T1). - from_date: Start month YYYY-MM. Default: 24 months ago. - to_date: End month YYYY-MM. Default: latest available. - lang: Response language. Default: de.

Returns: str: Markdown summary and JSON data in millions CHF.

Inputs: params (required). Returns: result

snb_get_banking_balance_sheetA
Read-onlyIdempotent

Retrieve banking balance sheet data from SNB Warehouse (BSTA BIL cubes).

Returns total assets and/or liabilities for selected bank groups from the Swiss banking statistics. Values are converted to millions of CHF.

Args: params (BankingBalanceSheetInput): - side: 'assets', 'liabilities', or 'both'. - bank_groups: Bank group IDs (default: ['A30'] = all banks). - frequency: 'annual' or 'monthly'. - currency: Currency filter (default: 'T' = Total). - from_date / to_date: Date range. - lang: Response language.

Returns: str: Markdown summary with values in Millionen CHF, plus JSON data.

Inputs: params (required). Returns: result

snb_get_banking_incomeA
Read-onlyIdempotent

Retrieve banking income statement data from SNB Warehouse (BSTA EFR cubes).

Returns key income statement positions (Geschäftsertrag, Geschäftsaufwand, etc.) for selected bank groups. Values are converted to millions of CHF.

Args: params (BankingIncomeInput): - bank_groups: Bank group IDs (default: ['A30'] = all banks). - from_year / to_year: Year range (YYYY). - lang: Response language.

Returns: str: Markdown summary with values in Millionen CHF, plus JSON data.

Inputs: params (required). Returns: result

snb_get_cube_dataA
Read-onlyIdempotent

Retrieve raw data from any SNB data cube by ID.

Generic tool for accessing SNB cubes beyond the dedicated tools. Use snb_get_cube_metadata first to understand the cube structure. Browse https://data.snb.ch to discover cube IDs from the URL pattern: data.snb.ch/de/topics/{topic}/cube/{cubeId}

Args: params (CubeDataInput): - cube_id: SNB cube identifier (lowercase), e.g. 'devkum', 'snbbipo'. - from_date: Start date (YYYY-MM for monthly, YYYY for annual). - to_date: End date. - lang: Response language (de/en/fr).

Returns: str: Raw timeseries data from the cube as JSON.

Inputs: params (required). Returns: result

snb_get_cube_metadataA
Read-onlyIdempotent

Get metadata and dimension structure for any SNB data cube.

Retrieves the cube's dimension definitions, available filter values, and structure. Use this before querying snb_get_cube_data to understand what parameters and filters are available.

Args: params (CubeMetadataInput): - cube_id: SNB cube identifier, e.g. 'devkum', 'snbbipo'. - lang: Language for labels (de/en/fr).

Returns: str: Cube ID, dimensions, and all available dimension item IDs with labels.

Inputs: params (required). Returns: result

snb_get_exchange_ratesA
Read-onlyIdempotent

Retrieve monthly CHF exchange rates from the Swiss National Bank (data.snb.ch).

Returns monthly average rates (and optionally month-end rates) for all major currencies against the Swiss Franc (CHF). Data source: SNB cube 'devkum'. Rates are expressed as the CHF value of the stated foreign currency unit (e.g. EUR1: 1 EUR = 0.9416 CHF; JPY100: 100 JPY = 0.58 CHF).

Args: params (ExchangeRatesInput): - currencies: List of currency IDs (e.g. ['EUR1', 'USD1']). Default: all. - from_date: Start month YYYY-MM. Default: 12 months ago. - to_date: End month YYYY-MM. Default: current month. - include_month_end: Also include month-end rates. Default: False. - lang: Response language (de/en/fr). Default: de.

Returns: str: Markdown table with dates and CHF exchange rates per currency. Includes publication date and data source metadata.

Schema: { "cube_id": "devkum", "publishing_date": "YYYY-MM-DD HH:MM", "currencies_returned": int, "timeseries": [ { "currency": str, "type": "Monatsmittel" | "Monatsende", "unit": str, "values": [{"date": "YYYY-MM", "value": float}] } ] }

Inputs: params (required). Returns: result

snb_get_warehouse_dataA
Read-onlyIdempotent

Retrieve raw data from any SNB Warehouse cube by ID.

Generic tool for accessing SNB Warehouse cubes (BSTA banking statistics). Use snb_get_warehouse_metadata first to understand the cube structure. Use snb_list_warehouse_cubes to discover available cube IDs.

Args: params (WarehouseDataInput): - cube_id: SNB Warehouse cube ID (uppercase, dot-separated). - from_date: Start date (YYYY for annual, YYYY-MM for monthly). - to_date: End date. - lang: Response language (de/en/fr).

Returns: str: Timeseries data from the warehouse cube as Markdown + JSON.

Inputs: params (required). Returns: result

snb_get_warehouse_metadataA
Read-onlyIdempotent

Get metadata and dimension structure for any SNB Warehouse cube.

Retrieves the cube's dimension definitions and last update date. Use this before querying snb_get_warehouse_data to understand what dimensions and filter values are available.

Args: params (WarehouseMetadataInput): - cube_id: SNB Warehouse cube ID to inspect. - lang: Language for labels (de/en/fr).

Returns: str: Cube ID, edition date, dimensions and their items.

Inputs: params (required). Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 11 tools

    Disambiguation5/5

    Each tool targets a specific, distinct data type or operation: currency conversion, monthly/annual exchange rates, balance sheet, balance of payments, banking statistics, and generic cube/warehouse access. There is no overlap that would confuse an agent; even the exchange rate tools are clearly differentiated by frequency and purpose.

    Naming Consistency4/5

    All tools follow the 'snb_' prefix and snake_case convention. Most are 'snb_get_' except for 'snb_convert_currency', which uses a different verb. This minor inconsistency is justified by the distinct action (conversion vs. retrieval), but it breaks the otherwise uniform pattern.

    Tool Count5/5

    With 11 tools, the server covers the core SNB data domains (exchange rates, balance sheet, banking statistics) plus generic cube access without being overwhelming. The count is well-scoped for its purpose.

    Completeness4/5

    The tool set covers major SNB data categories: exchange rates, conversion, balance of payments, SNB balance sheet, banking balance sheet, and banking income. The generic cube and warehouse tools fill gaps for other SNB data. A minor gap is the lack of a dedicated tool for daily exchange rates, but monthly and annual are covered.

    Maintenance

    ActivitySlowing
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to query Norges Bank's open data API for exchange rates, policy rates, government securities, money market data, bank liquidity, and regional network survey data.
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Provides AI-native access to Swiss Federal Statistical Office datasets through 9 tools for querying education, population, and cross-cantonal comparisons without authentication.
      3
      15
      42 PyPI
      2
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI models to access Swiss weather and climate data from MeteoSwiss, including current observations, forecasts, and warnings.
      6
      33 PyPI
      MIT