{
  "markdown": "> 🇨🇭 **Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)**\n\n# 📺 srgssr-mcp\n\n![Version](https://img.shields.io/badge/version-2.0.1-blue)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)\n[![MCP](https://img.shields.io/badge/MCP-Model%20Context%20Protocol-purple)](https://modelcontextprotocol.io/)\n[![CI](https://github.com/malkreide/srgssr-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/malkreide/srgssr-mcp/actions)\n[![Data Source](https://img.shields.io/badge/Data-SRG%20SSR%20Public%20API-red)](https://developer.srgssr.ch)\n\n> MCP server connecting AI models to SRG SSR public APIs – weather, TV/radio metadata, program guide and Swiss votations/elections since 1900 (SRF, RTS, RSI, RTR, SWI).\n\n[🇩🇪 Deutsche Version](README.de.md)\n\n<p align=\"center\">\n  <img src=\"assets/demo.svg\" alt=\"Demo: Claude asks a question → srgssr-mcp tool call → grounded answer from SRG SSR Polis API\" width=\"760\">\n</p>\n\n---\n\n## Overview\n\n**srgssr-mcp** gives AI assistants like Claude direct access to the public APIs of SRG SSR – Switzerland's national public broadcaster. Weather forecasts, TV and radio metadata, electronic program guides, and historical democratic data (votations and elections since 1900) are all accessible through a single standardised MCP interface.\n\nThe server covers five thematic clusters: SRF Weather, Video, Audio, EPG and Polis (Swiss Democracy). Each cluster maps to a group of purpose-built tools that translate raw SRG SSR API data into clean JSON responses.\n\n**Anchor demo query:** *\"What were the cantonal results of the popular vote on initiative X in Zurich?\"* – answered with historical real-time data from the Polis system, not a hallucination.\n\n---\n\n## Features\n\n- 🌦️ **Weather** – location search, current conditions, 24h hourly forecast, 7-day forecast (SRF Meteo)\n- 📺 **Video** – TV show listings, latest episodes, live TV channels across all business units\n- 🎙️ **Audio** – radio show listings, audio episodes, live radio stations\n- 📅 **EPG** – daily program schedule for any TV or radio channel\n- 🗳️ **Polis** – popular votes and elections since 1900, national and cantonal results\n- 🏢 **Multi-unit** – SRF (DE), RTS (FR), RSI (IT), RTR (RM), SWI (multilingual)\n- 🔐 **OAuth2** – automatic token management with Client Credentials flow\n- ☁️ **Dual transport** – stdio for Claude Desktop, Streamable HTTP/SSE for cloud deployment\n\n---\n\n## Prerequisites\n\n- Python 3.11+\n- **API keys** from [developer.srgssr.ch](https://developer.srgssr.ch) (free registration):\n  1. Create an account and log in\n  2. Under \"My Apps\", create a new application\n  3. Add the product **SRG SSR PUBLIC API V2**\n  4. Note your **Consumer Key** and **Consumer Secret**\n\n> ⚠️ **Terms of use:** SRG SSR APIs are available for non-commercial use. For commercial use, contact [api@srgssr.ch](mailto:api@srgssr.ch) directly.\n\n---\n\n## Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/malkreide/srgssr-mcp.git\ncd srgssr-mcp\n\n# Install\npip install -e .\n```\n\nOr with `uvx` (no permanent installation):\n\n```bash\nuvx srgssr-mcp\n```\n\nOr via pip:\n\n```bash\npip install srgssr-mcp\n```\n\n---\n\n## Quickstart\n\n```bash\n# Set credentials\nexport SRGSSR_CONSUMER_KEY=\"your-consumer-key\"\nexport SRGSSR_CONSUMER_SECRET=\"your-consumer-secret\"\n\n# Start the server (stdio mode for Claude Desktop)\nsrgssr-mcp\n```\n\nTry it immediately in Claude Desktop:\n\n> *\"What will the weather be like in Zurich tomorrow?\"*\n> *\"What's on SRF 1 tonight?\"*\n> *\"Which popular votes took place in the canton of Bern between 2010 and 2020?\"*\n\n---\n\n## Configuration\n\n### Claude Desktop\n\n**Minimal (recommended):**\n\n```json\n{\n  \"mcpServers\": {\n    \"srgssr\": {\n      \"command\": \"uvx\",\n      \"args\": [\"srgssr-mcp\"],\n      \"env\": {\n        \"SRGSSR_CONSUMER_KEY\": \"your-consumer-key\",\n        \"SRGSSR_CONSUMER_SECRET\": \"your-consumer-secret\"\n      }\n    }\n  }\n}\n```\n\n**Config file locations:**\n- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\nAfter saving, restart Claude Desktop completely.\n\n### Other MCP Clients\n\nCompatible with Cursor, Windsurf, VS Code + Continue, LibreChat, Cline, and self-hosted models via `mcp-proxy`. Set the same environment variables.\n\n### Cloud Deployment (SSE for browser access)\n\nFor use via **claude.ai in the browser** (e.g. on managed workstations without local software):\n\n```bash\nSRGSSR_CONSUMER_KEY=... \\\nSRGSSR_CONSUMER_SECRET=... \\\nSRGSSR_MCP_TRANSPORT=streamable-http \\\nSRGSSR_MCP_HOST=0.0.0.0 \\\nSRGSSR_MCP_PORT=8000 \\\n  python -m srgssr_mcp.server\n```\n\nTransport, host, port and mount path are all driven by environment variables\n(see `srgssr_mcp.server.Settings`). Valid values for `SRGSSR_MCP_TRANSPORT`\nare `stdio` (default), `sse`, and `streamable-http`.\n\n> 💡 *\"stdio for the developer laptop, SSE for the browser.\"*\n\n---\n\n## MCP Primitives\n\nThis server exposes all three orthogonal MCP primitives:\n\n| Primitive | Mental model | What's here |\n|---|---|---|\n| **Tools** (verbs) | Executable functions / parametrized queries | 15 tools — search, list, fetch, aggregate |\n| **Resources** (nouns) | Cache-friendly passive data behind URIs | EPG entries and immutable votation results |\n| **Prompts** (recipes) | Reusable workflow templates | Voting analysis & daily briefing |\n\nTools cover parametrized searches (year ranges, free-text, paginated listings) where every call may yield different results. Resources expose stable data points that are safe to cache: a published EPG for a given channel/date, or the final result of a closed Swiss votation. Prompts standardise recurring multi-step analyses so users don't have to phrase them from scratch.\n\n### Resources\n\n| URI template | Description |\n|---|---|\n| `epg://{bu}/{channel_id}/{date}` | Daily TV/radio program guide for SRF, RTS, RSI (e.g. `epg://srf/srf-1/2026-04-30`) |\n| `votation://{votation_id}` | Detailed result of a closed Swiss popular vote (e.g. `votation://v1`) |\n\n**EPG station ids** — hyphenated, and not the same as the livestream ids:\n\n| Business unit | TV | Radio |\n|---|---|---|\n| SRF | `srf-1`, `srf-2`, `srf-info` | `srf-1`, `srf-2`, `srf-2-kultur`, `srf-3`, `srf-4`, `srf-musikwelle`, `srf-virus` |\n| RTS | `rts-1`, `rts-2`, `rts-info` | `LA1ERE`, `ESPACE2`, `COULEUR3`, `OPTION_MUSIQUE` |\n| RSI | `la-1`, `la-2` | `rete-uno`, `rete-due`, `rete-tre` |\n\n\n### Prompts\n\n| Name | Arguments | Purpose |\n|---|---|---|\n| `analyse_abstimmungsverhalten` | `votation_id`, `focus` (`stadt_land` / `sprachregionen` / `kantone`) | Structured analysis of a Swiss popular vote |\n| `tagesbriefing_kanton` | `location`, `channel_id`, `business_unit`, `date` | Daily briefing combining weather and EPG |\n\n---\n\n## Available Tools\n\n### Tool Naming Convention\n\nThis server uses **`snake_case`** for tool names, following Python ecosystem idioms. While MCP best practice favors `camelCase` for optimal LLM tokenization, `snake_case` remains acceptable and keeps tool names aligned with the underlying Python function identifiers.\n\nAll tools follow the pattern `srgssr_<domain>_<action>` with the namespace prefix `srgssr_` and a semantically meaningful `<domain>_<action>` suffix (e.g. `srgssr_weather_current`, `srgssr_polis_get_votations`).\n\n### 🌦️ SRF Weather (4 tools)\n\n| Tool | Description | Data Source |\n|---|---|---|\n| `srgssr_weather_search_location` | Search for a location by name or postal code to obtain a `geolocationId` | SRF Meteo |\n| `srgssr_weather_current` | Current weather conditions for a Swiss location | SRF Meteo |\n| `srgssr_weather_forecast_24h` | Hourly 24-hour forecast | SRF Meteo |\n| `srgssr_weather_forecast_7day` | Daily 7-day forecast | SRF Meteo |\n\n### 📺 Video (3 tools)\n\n| Tool | Description | Data Source |\n|---|---|---|\n| `srgssr_video_get_shows` | List TV shows for a business unit (`character_filter` a–z/# selects one initial; omit it to fan out over all 27) | SRG SSR IL |\n| `srgssr_video_get_episodes` | Retrieve latest episodes of a show | SRG SSR IL |\n| `srgssr_video_get_livestreams` | List live TV channels | SRG SSR IL |\n\n### 🎙️ Audio (3 tools)\n\n| Tool | Description | Data Source |\n|---|---|---|\n| `srgssr_audio_get_shows` | List radio shows for one radio channel (`channel_id` required — the v2 API has no per-unit listing) | SRG SSR IL |\n| `srgssr_audio_get_episodes` | Retrieve audio episodes of a show | SRG SSR IL |\n| `srgssr_audio_get_livestreams` | List live radio stations | SRG SSR IL |\n\n### 📅 EPG – Electronic Program Guide (1 tool)\n\n| Tool | Description | Data Source |\n|---|---|---|\n| `srgssr_epg_get_programs` | Daily program schedule for a TV or radio channel | SRG SSR IL |\n\n### 🗳️ Polis – Swiss Democracy (3 tools)\n\n| Tool | Description | Data Source |\n|---|---|---|\n| `srgssr_polis_get_votations` | Popular votes since 1900 (national or cantonal) | Polis API |\n| `srgssr_polis_get_votation_results` | Detailed results of a specific vote | Polis API |\n| `srgssr_polis_get_elections` | Election results since 1900 | Polis API |\n\n### Supported Business Units\n\n| Code | Unit | Language |\n|---|---|---|\n| `srf` | SRF (Schweizer Radio und Fernsehen) | German |\n| `rts` | RTS (Radio Télévision Suisse) | French |\n| `rsi` | RSI (Radiotelevisione svizzera) | Italian |\n| `rtr` | RTR (Radiotelevisiun Svizra Rumantscha) | Romansh |\n| `swi` | SWI swissinfo.ch | Multilingual |\n\n### Example Use Cases\n\n| Query | Tool |\n|---|---|\n| *\"Weather in Zurich tomorrow?\"* | `srgssr_weather_forecast_24h` |\n| *\"What's on SRF 1 tonight?\"* | `srgssr_epg_get_programs` |\n| *\"Latest Tagesschau episodes?\"* | `srgssr_video_get_episodes` |\n| *\"Popular votes in Canton Bern 2010–2020?\"* | `srgssr_polis_get_votations` |\n| *\"Cantonal results of the mask initiative vote?\"* | `srgssr_polis_get_votation_results` |\n| *\"All current RTS radio shows?\"* | `srgssr_audio_get_livestreams` → `srgssr_audio_get_shows` |\n\n→ [More use cases by audience](EXAMPLES.md) →\n\n---\n\n## Architecture\n\n```\n┌─────────────┐\n│ Claude / LLM│\n└──────┬──────┘\n       │ MCP (stdio)\n┌──────▼───────────────────┐\n│ srgssr-mcp Server        │\n│  ├─ Weather Tools (4)    │\n│  ├─ EPG Tools (1)        │\n│  ├─ Polis Tools (3)      │\n│  ├─ Video Tools (3)      │\n│  └─ Audio Tools (3)      │\n└──────┬───────────────────┘\n       │ HTTPS (OAuth2)\n┌──────▼──────────────┐\n│ SRG SSR Public APIs │\n│  developer.srgssr.ch│\n└─────────────────────┘\n```\n\n### Data Sources\n\n| Source | Data | Access |\n|---|---|---|\n| [developer.srgssr.ch](https://developer.srgssr.ch) | SRG SSR PUBLIC API V2 (weather, A/V, EPG, Polis) | OAuth2 (free registration) |\n\n**Attribution:** SRG SSR APIs are subject to the [SRG SSR Terms of Use](https://developer.srgssr.ch).\n\n---\n\n## Development Phase\n\nThis server is in **Phase 1: Read-only Wrapper**.\n\nThe server exposes only `GET`-style operations against public SRG SSR APIs. There are no write, mutate or delete capabilities by design — see [Safety & Limits](#-safety--limits) for the threat-model implications.\n\n### Phase 1 Completion Criteria\n\n- [x] 14 read-only tools across five thematic clusters (Weather, Video, Audio, EPG, Polis)\n- [x] OAuth2 Client Credentials authentication with token caching\n- [x] Bilingual documentation (EN/DE)\n- [x] Test suite (unit + live) — see [OPS-001](audits/2026-04-30-srgssr-mcp/findings/OPS-001-test-strategy.md)\n- [x] Structured logging — see [OBS-003](#logging) and CHANGELOG\n- [ ] Production-ready error handling (uniform retry/backoff, typed error envelopes)\n\n### Future Phases\n\n- **Phase 2 (Write):** **Not planned.** The SRG SSR Public APIs are read-only by contract; there is no upstream surface to write to.\n- **Phase 3 (Multi-Agent):** **Evaluation deferred.** Will be reconsidered once user feedback indicates concrete multi-agent workflows that this server should orchestrate (e.g. cross-server aggregation with `swiss-statistics-mcp` or `swiss-transport-mcp`).\n\n---\n\n## MCP Protocol Version\n\n`mcp` 2.x serves **two protocol eras** over the same server, and the client's\nfirst request on a connection decides which one applies:\n\n| Era | Revision | Who reaches it |\n|---|---|---|\n| `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. |\n| Per-request envelope | **`2026-07-28`** | A request carrying the `2026-07-28` `_meta` envelope opens a modern connection. |\n\n`PROTOCOL_VERSION` in [`src/srgssr_mcp/_app.py`](src/srgssr_mcp/_app.py) names\nthe **modern** era. It is validated at import time against the installed SDK's\n`SUPPORTED_PROTOCOL_VERSIONS` — but that list is backwards-compatible and still\ncontains `2024-11-05`, so the membership check catches a revision being dropped,\nnever a drift. [`tests/test_protocol_version.py`](tests/test_protocol_version.py)\nholds both eras against the SDK and is the check that catches drift. Bumps are\ntracked in [CHANGELOG.md](CHANGELOG.md) under the matching release.\n\n### Update Policy\n\n- SDK dependency updates land via Dependabot (`.github/dependabot.yml`, monthly cadence, grouped under the `mcp-sdk` label) and run the full test suite before merge.\n- Spec bumps are evaluated on a feature branch against the relevant MCP SDK release; the [official MCP changelog](https://modelcontextprotocol.io/specification/draft/changelog) is the source of truth for breaking changes.\n- A spec-version bump is always documented in `CHANGELOG.md` and, if it changes the externally observable wire contract, triggers a minor or major release per [Semantic Versioning](https://semver.org/).\n\n---\n\n## Project Structure\n\n```\nsrgssr-mcp/\n├── src/srgssr_mcp/\n│   ├── __init__.py          # Package\n│   └── server.py            # MCPServer: 15 tools, OAuth2 client\n├── .github/\n│   └── workflows/\n│       └── ci.yml           # GitHub Actions CI (Python 3.11–3.13)\n├── pyproject.toml           # Build configuration (hatchling)\n├── CHANGELOG.md\n├── CONTRIBUTING.md          # English\n├── CONTRIBUTING.de.md       # German\n├── SECURITY.md              # Security policy (English)\n├── SECURITY.de.md           # Security policy (German)\n├── LICENSE                  # MIT\n├── README.md                # This file (English)\n└── README.de.md             # German version\n```\n\n---\n\n## 🛡️ Safety & Limits\n\n| Aspect | Details |\n|--------|---------|\n| **Access** | Read-only — the server only reads from SRG SSR APIs and cannot post, modify or delete any content |\n| **Personal data** | No personal data — all endpoints serve public broadcast metadata, weather observations and historical votation/election results |\n| **Rate limits** | Subject to the tier of your OAuth2 application on [developer.srgssr.ch](https://developer.srgssr.ch); the server adds sensible per-query caps (e.g. max 100 episodes, 50 shows per list call) |\n| **Timeout** | 30 seconds per upstream API call |\n| **Authentication** | OAuth2 Client Credentials (free registration); secrets stay local, never logged |\n| **Licensing & use** | SRG SSR APIs are for **non-commercial use**; commercial use requires written permission from [api@srgssr.ch](mailto:api@srgssr.ch) |\n| **Terms of Service** | Subject to the [SRG SSR Developer Terms of Use](https://developer.srgssr.ch) — users remain responsible for attribution and compliance |\n\n---\n\n## Known Limits\n\n- **Rate Limits:** SRG SSR APIs enforce rate limits — see [developer.srgssr.ch](https://developer.srgssr.ch) for details on the tier of your OAuth2 application\n- **Data Freshness:** EPG data may be delayed by up to 6 hours\n- **Historical Data:** Polis data goes back to 1900 — older data is not available\n- **Geo-Restriction:** Some streaming APIs are only available within Switzerland\n- **API keys required:** SRG SSR APIs require free OAuth2 credentials from [developer.srgssr.ch](https://developer.srgssr.ch)\n- **Non-commercial use:** SRG SSR API terms restrict commercial use without explicit permission from [api@srgssr.ch](mailto:api@srgssr.ch)\n- **Weather coverage:** SRF Meteo covers Switzerland only\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) (English) · [CONTRIBUTING.de.md](CONTRIBUTING.de.md) (German)\n\n---\n\n## Security\n\nFor the full security posture, vulnerability reporting process and accepted-risk\nregister, see [SECURITY.md](SECURITY.md) (English) · [SECURITY.de.md](SECURITY.de.md) (German).\nThe key egress control is summarised below.\n\n### Egress Allowlist\n\nThe server implements a **code-layer egress allowlist** (SEC-021, combined with SEC-004 SSRF defense) to prevent unintended external requests. Every outbound HTTP request is validated by `_validate_url_safe()` in [`src/srgssr_mcp/_http.py`](src/srgssr_mcp/_http.py) before it is issued.\n\n**Three controls per request:**\n\n1. **HTTPS-only** — `http://`, `file://`, `ftp://` and other non-HTTPS schemes are rejected.\n2. **Host allowlist** — the URL hostname must equal `ALLOWED_HOSTS = {\"api.srgssr.ch\"}` (exact match — subdomain tricks like `api.srgssr.ch.attacker.example` are blocked). One host covers everything: the OAuth2 token endpoint and every data endpoint.\n3. **IP blocklist** — every resolved IP for the hostname is checked against private, loopback, link-local (incl. `169.254.169.254` cloud-metadata), CGNAT, multicast and reserved ranges (IPv4 + IPv6). Any single match aborts the request — defense-in-depth against DNS rebinding.\n\nViolations surface as `ValueError` and are mapped to a localized `Konfigurationsfehler: …` message by `_handle_error`, so internal network details never leak to the MCP client.\n\n**Adding a new SRG SSR domain:**\n\n1. Update `ALLOWED_HOSTS` in [`src/srgssr_mcp/_http.py`](src/srgssr_mcp/_http.py).\n2. Document the reason in the PR and `CHANGELOG.md`.\n3. Add a positive test case in `tests/test_unit.py` (mirror `test_validate_url_safe_accepts_public_srgssr_host`).\n\n**Network-Layer Egress (for future SSE/HTTP deployments):** see [`docs/network-egress.md`](docs/network-egress.md). For the current `stdio` transport, network-layer controls do not apply — the process runs in the MCP client's user context.\n\n---\n\n## Logging\n\nThe server uses **structured logging** (OBS-003) via [`structlog`](https://www.structlog.org/) with JSON output to **stderr** — keeping `stdout` clean for the stdio transport's JSON-RPC traffic.\n\n**Format:**\n- JSON-encoded events, one per line\n- ISO 8601 UTC `timestamp` on every record\n- RFC 5424 severity levels: `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`\n- Per-call bound context: `tool`, `business_unit`, `channel_id`, `query`, etc.\n\n**Example output:**\n\n```json\n{\"event\": \"tool_invoked\", \"tool\": \"srgssr_weather_search_location\", \"query\": \"Bern\", \"level\": \"info\", \"logger\": \"mcp.srgssr.weather\", \"timestamp\": \"2026-04-30T14:23:45.123Z\"}\n{\"event\": \"tool_succeeded\", \"tool\": \"srgssr_weather_search_location\", \"query\": \"Bern\", \"result_count\": 3, \"matched_variant\": \"Bern\", \"level\": \"info\", \"logger\": \"mcp.srgssr.weather\", \"timestamp\": \"2026-04-30T14:23:45.456Z\"}\n```\n\n**Log levels (RFC 5424):**\n\n| Level | Used for |\n|-------|----------|\n| `debug` | OAuth token cache hits, internal state |\n| `info` | Tool invocations, successful responses, server lifecycle |\n| `warning` | Recoverable conditions (rate-limit approaching, unsupported business unit) |\n| `error` | API failures, timeouts (recoverable) |\n| `critical` | Credential issues, service degradation |\n\n**Configuration:**\n\nThe default level is `info`. Override via the `SRGSSR_LOG_LEVEL` environment variable (`debug`, `info`, `warning`, `error`, `critical`):\n\n```bash\nSRGSSR_LOG_LEVEL=debug srgssr-mcp\n```\n\nJSON output is aggregator-friendly — pipe stderr to Datadog, Splunk, Loki, etc., and filter by structured fields (`tool`, `business_unit`, `level`) without regex parsing.\n\n---\n\n## Testing\n\n```bash\n# Unit tests (no network required)\nPYTHONPATH=src pytest tests/ -m \"not live\"\n\n# Integration tests (requires SRG SSR API keys)\nPYTHONPATH=src pytest tests/ -m \"live\"\n\n# Linting\nruff check src/\n```\n\n---\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md)\n\n---\n\n## Data Sources & Licenses\n\nAll data exposed by this server is fetched live from a single upstream\nprovider, **SRG SSR Public API V2** (`https://api.srgssr.ch`). Every tool\nreturn is a typed [Pydantic `BaseModel`](src/srgssr_mcp/_models.py) that\nembeds `source` / `license` / `provenance_url` / `fetched_at` at the top\nlevel — so downstream consumers can record the data origin without\nround-tripping through this README. The SDK exposes the corresponding\n`outputSchema` in the `tools/list` manifest so MCP clients can plan\nfollow-up calls precisely.\n\n| Cluster | Provider | License | Notes |\n|---|---|---|---|\n| Weather | SRF Meteo (api.srgssr.ch) | SRG SSR Terms of Use | Geo-restricted to Switzerland |\n| Video / Audio / EPG | SRF · RTS · RSI · RTR · SWI | SRG SSR Terms of Use | Metadata only — stream URLs are not redistributed |\n| Polis (Votations / Elections) | SRG SSR Polis | SRG SSR Terms of Use | Historical data since 1900 |\n\n**Use of the SRG SSR APIs**\n\n- Non-commercial use: free, no application required.\n- Commercial use: written permission required via [api@srgssr.ch](mailto:api@srgssr.ch).\n\nThis server's MIT license covers the source code only; it does **not**\nrelicense the upstream data.\n\n---\n\n## License\n\nMIT License — see [LICENSE](LICENSE)\n\nThe SRG SSR APIs used in this project are subject to the [SRG SSR Terms of Use](https://developer.srgssr.ch).\n\n---\n\n## Author\n\nHayal Oezkan · [github.com/malkreide](https://github.com/malkreide)\n\n---\n\n## Credits & Related Projects\n\n- **Data:** [SRG SSR Developer Portal](https://developer.srgssr.ch) · SRF Meteo · Polis API\n- **Protocol:** [Model Context Protocol](https://modelcontextprotocol.io/) – Anthropic / Linux Foundation\n- **Related:**\n\n| Server | Description |\n|---|---|\n| [zurich-opendata-mcp](https://github.com/malkreide/zurich-opendata-mcp) | City of Zurich open data (OSTLUFT air quality, weather, parking, geodata) |\n| [swiss-transport-mcp](https://github.com/malkreide/swiss-transport-mcp) | Swiss public transport – OJP 2.0 journey planning, SIRI-SX disruptions |\n| [swiss-environment-mcp](https://github.com/malkreide/swiss-environment-mcp) | BAFU environmental data – air quality, hydrology, natural hazards |\n| [swiss-statistics-mcp](https://github.com/malkreide/swiss-statistics-mcp) | BFS STAT-TAB – 682 statistical datasets |\n| [fedlex-mcp](https://github.com/malkreide/fedlex-mcp) | Swiss federal law via Fedlex SPARQL |\n\n**Synergy example:** *\"What were the results of the 2020 popular votes in Canton Zurich – and how did turnout compare to the national average?\"*\n→ `srgssr-mcp` (Polis, cantonal results) + `swiss-statistics-mcp` (BFS, turnout data)\n\n- **Portfolio:** [Swiss Public Data MCP Portfolio](https://github.com/malkreide)\n\n<!-- mcp-name: io.github.malkreide/srgssr-mcp -->\n\n<!-- BEGIN GENERATED: install -->\n## Installation\n\nRun via [`uv`](https://docs.astral.sh/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`):\n\n```json\n{\n  \"mcpServers\": {\n    \"srgssr-mcp\": {\n      \"command\": \"uvx\",\n      \"args\": [\n        \"srgssr-mcp\"\n      ]\n    }\n  }\n}\n```\n<!-- END GENERATED: install -->\n",
  "bytes": 23402,
  "sha": "83319472877e49c086204551c72bfb9c8bc5ce8e14df63a2ead8d423f2cd7b4b",
  "repo_slug": "malkreide/srgssr-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_malkreide_srgssr_mcp_e7ac181e/readme"
}