{
  "markdown": "> 🇨🇭 **Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)**\n\n# 🏛️ swiss-culture-mcp\n\n![Version](https://img.shields.io/badge/version-1.1.4-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[![Data Source](https://img.shields.io/badge/Data-BAK%20Open%20Data-red)](https://opendata.swiss/)\n![CI](https://github.com/malkreide/swiss-culture-mcp/actions/workflows/ci.yml/badge.svg)\n\n> MCP server for Swiss cultural heritage data from the Federal Office of Culture (BAK) — ISOS townscapes, Living Traditions, cultural prizes, press releases. No API key required.\n\n🌐 **English** | **[Deutsch](README.de.md)**\n\n<p align=\"center\">\n  <img src=\"assets/demo-flow.svg\" alt=\"Demo: Claude queries ISOS townscapes via MCP tool call\" width=\"780\">\n</p>\n\n---\n\n## Overview\n\n**swiss-culture-mcp** makes Swiss cultural data accessible to AI assistants. The server connects LLMs like Claude with Switzerland's national cultural heritage: from protected townscapes (ISOS) to living traditions of intangible cultural heritage and current cultural awards.\n\n**Sources:** geo.admin.ch REST API · news.admin.ch RSS · opendata.swiss CKAN · lebendige-traditionen.ch\n\n**No API key required.** All data sources are publicly available (Open Government Data).\n\n**Anchor demo query:** *\"Which protected townscapes are there in the school districts of the city of Zurich, and what living traditions are practised there?\"*\n\n---\n\n## Features\n\n- 🏘️ **ISOS search** – Federal Inventory of Swiss Townscapes Worth Protecting by name, canton or settlement type\n- 📜 **Living Traditions** – 228 entries of Swiss intangible cultural heritage\n- 🏆 **Cultural prizes** – Swiss Film Prize, Grand Prix Literature, Music Prize and more\n- 📰 **BAK press releases** – current news from the Federal Office of Culture\n- 📦 **Open data catalogue** – BAK datasets on opendata.swiss\n- ☁️ **Dual transport** – stdio for Claude Desktop, Streamable HTTP for cloud deployment\n\n| # | Tool | Description |\n|---|---|---|\n| 1 | `bak_search_isos` | Search ISOS townscapes by place name |\n| 2 | `bak_isos_by_kanton` | List all ISOS objects in a canton |\n| 3 | `bak_get_isos_detail` | Get full details of an ISOS object |\n| 4 | `bak_isos_by_kategorie` | Filter ISOS by settlement type (Stadt, Dorf, etc.) |\n| 5 | `bak_isos_statistics` | ISOS inventory statistics (sampled by canton) |\n| 6 | `bak_get_news` | Current BAK press releases |\n| 7 | `bak_get_kulturpreise` | Swiss cultural prizes (Film Prize, Grand Prix Literature, etc.) |\n| 8 | `bak_get_opendata` | BAK datasets on opendata.swiss |\n| 9 | `bak_list_traditions` | List Switzerland's Living Traditions |\n| 10 | `bak_get_tradition_detail` | Get detailed description of a tradition |\n\n**3 Resources:** `bak://isos/kantone` · `bak://isos/kategorien` · `bak://kulturpreise/uebersicht`\n\n---\n\n## Data Sources\n\n| Source | API Type | Content |\n|---|---|---|\n| **geo.admin.ch** | REST MapServer | ISOS (Federal Inventory of Swiss Townscapes) |\n| **news.admin.ch** | RSS Feed | BAK press releases, cultural prizes |\n| **opendata.swiss** | CKAN REST API | BAK open data datasets |\n| **lebendige-traditionen.ch** | HTML Fetch | 228 entries of intangible cultural heritage |\n\n---\n\n## Prerequisites\n\n- Python 3.11+\n- `uv` or `pip`\n- No API keys required\n\n---\n\n## Installation\n\n```bash\n# Recommended: uvx (no install step needed)\nuvx swiss-culture-mcp\n\n# Alternative: pip\npip install swiss-culture-mcp\n```\n\n---\n\n## Quickstart\n\n```bash\n# Start the server (stdio mode for Claude Desktop)\nuvx swiss-culture-mcp\n```\n\nTry it immediately in Claude Desktop:\n\n> *\"Show me all protected townscapes in the canton of Graubünden\"*\n> *\"Which living traditions are practised in canton Appenzell?\"*\n> *\"Which Swiss cultural prizes were awarded in 2026?\"*\n\n---\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|---|---|---|\n| `MCP_TRANSPORT` | `stdio` | Transport: `stdio` or `streamable_http` |\n| `MCP_HOST` | `127.0.0.1` | Bind host for HTTP transport (loopback by default) |\n| `MCP_PORT` | `8000` | Port for HTTP transport |\n| `MCP_ALLOW_PUBLIC_BIND` | `false` | If `true`, permits binding `0.0.0.0` without auth. Set this **only** behind an authenticating reverse proxy (e.g. Cloudflare Access, oauth2-proxy). |\n| `LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARNING`, `ERROR` — structured JSON logs to stderr |\n\n### Claude Desktop Configuration\n\n```json\n{\n  \"mcpServers\": {\n    \"swiss-culture\": {\n      \"command\": \"uvx\",\n      \"args\": [\"swiss-culture-mcp\"]\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 restarting Claude Desktop, all tools are available. Example queries:\n\n- \"Show me all protected townscapes in the canton of Graubünden\"\n- \"What is the Alphorn and Büchelspiel tradition?\"\n- \"Which Swiss cultural prizes were awarded in 2026?\"\n- \"Is the old town of Stein am Rhein in the ISOS inventory?\"\n- \"Which living traditions are practised in canton Appenzell?\"\n\n### Cloud Deployment (Streamable HTTP)\n\nFor use via **claude.ai in the browser** (e.g. on managed workstations without local software):\n\n**Render.com (recommended):**\n1. Push/fork the repository to GitHub\n2. On [render.com](https://render.com): New Web Service → connect GitHub repo\n3. Set environment variables in the Render dashboard\n4. In claude.ai under Settings → MCP Servers, add: `https://your-app.onrender.com/mcp`\n\n```bash\n# Docker / local HTTP mode (loopback only — safe default)\nMCP_TRANSPORT=streamable_http MCP_PORT=8000 python -m swiss_culture_mcp.server\n\n# Public bind (DANGEROUS — only behind an authenticating reverse proxy)\nMCP_TRANSPORT=streamable_http MCP_HOST=0.0.0.0 MCP_ALLOW_PUBLIC_BIND=true \\\n    python -m swiss_culture_mcp.server\n```\n\n> ⚠️ **Security:** The server itself has no authentication. Binding to a public\n> interface without an upstream auth layer turns it into an open proxy for the\n> federal data sources. Always run an authenticating reverse proxy (Cloudflare\n> Access, oauth2-proxy, nginx + auth_request) in front of `0.0.0.0` deployments.\n\n---\n\n## Architecture\n\n```\n┌─────────────────┐     ┌──────────────────────────┐     ┌──────────────────────────┐\n│   Claude / AI   │────▶│   Swiss Culture MCP      │────▶│  geo.admin.ch REST       │\n│   (MCP Host)    │◀────│   (MCP Server)           │◀────│  news.admin.ch RSS       │\n└─────────────────┘     │                          │     │  opendata.swiss CKAN     │\n                        │  10 Tools · 3 Resources  │     │  lebendige-traditionen   │\n                        │  Stdio | Streamable HTTP  │     └──────────────────────────┘\n                        └──────────────────────────┘\n```\n\n---\n\n## Project Structure\n\n```\nswiss-culture-mcp/\n├── src/\n│   └── swiss_culture_mcp/\n│       ├── __init__.py\n│       └── server.py          # All 10 tools, 3 resources\n├── tests/\n│   ├── conftest.py            # pytest configuration\n│   └── test_server.py         # 36 tests (unit + live)\n├── pyproject.toml\n├── CHANGELOG.md\n├── CONTRIBUTING.md            # Contribution guide (English)\n├── CONTRIBUTING.de.md         # Contribution guide (German)\n├── SECURITY.md               # Security policy & posture (English)\n├── SECURITY.de.md            # Security policy & posture (German)\n├── LICENSE\n├── README.md                  # This file (English)\n└── README.de.md               # German version\n```\n\n---\n\n## MCP Protocol Version\n\nThis server speaks **two protocol eras** over the same endpoint. The client's\nfirst request on a connection decides which one applies; a later claim from the\nother era is refused.\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\nBoth revisions are pinned in\n[`tests/test_protocol_version.py`](tests/test_protocol_version.py) and asserted\nagainst the installed SDK, so a Dependabot bump of `mcp` cannot move either one\nsilently. This server builds no ASGI app to send an `initialize` through, so\nthe gate asserts the SDK constants rather than a measured response — the\nweaker form, named rather than left unsaid.\n\nNote that the SDK's `LATEST_PROTOCOL_VERSION` is an alias for the **modern**\nera, not for the handshake era — pinning against it alone would leave the era\nthat current clients actually negotiate free to drift.\n\n**Update policy.** When the gate fails, do not edit the constant blindly: read\nthe spec changelog between the two revisions, verify the server still behaves,\nthen move the constant, this section, `README.de.md` and\n[`CHANGELOG.md`](CHANGELOG.md) together.\n\n---\n\n## Testing\n\n```bash\n# Unit tests (no API key required)\nPYTHONPATH=src pytest tests/ -m \"not live\"\n\n# Integration tests (live API calls)\nPYTHONPATH=src pytest tests/ -m \"live\"\n```\n\n---\n\n## Example Use Cases\n\n### Schools / Education\n\n```\n\"Which protected townscapes are there in the school districts of the city of Zurich?\"\n→ bak_isos_by_kanton(kanton=\"ZH\") + bak_get_isos_detail(...)\n\n\"Find living traditions for a project week on the theme of cultural heritage\"\n→ bak_list_traditions() + bak_get_tradition_detail(slug=\"...\")\n\n\"Which UNESCO World Heritage Sites are also in ISOS?\"\n→ bak_search_isos(query=\"...\") + bak_get_opendata(query=\"UNESCO\")\n```\n\n### City Administration / Spatial Planning\n\n```\n\"Is the building at address X within an ISOS perimeter?\"\n→ bak_search_isos(query=\"community/place name\")\n\n\"Which BAK datasets are available for GIS integration?\"\n→ bak_get_opendata() → WMS/WFS URLs for GIS software\n```\n\n### AI Working Group / Demos\n\n```\n\"Show current cultural policy of the federal government\"\n→ bak_get_news() + bak_get_kulturpreise()\n→ More use cases by audience →\n```\n\n---\n\n## Safety & Limits\n\n| Aspect | Details |\n|--------|---------|\n| **Access** | Read-only — the server cannot modify or delete any data |\n| **Personal data** | No personal data — all sources are aggregated, public cultural heritage data |\n| **Rate limits** | Built-in per-query caps (e.g. max 100 ISOS results, 50 news items, 200 category entries) |\n| **Timeout** | 20 seconds per API call |\n| **Authentication** | No API keys required — all 4 data sources are publicly accessible |\n| **Licenses** | All data under open licenses (Open Government Data): geo.admin.ch, opendata.swiss, news.admin.ch |\n| **Terms of Service** | Subject to ToS of the respective data sources: [geo.admin.ch](https://www.geo.admin.ch/de/geo-dienstleistungen/geodienste/terms-of-use.html), [opendata.swiss](https://opendata.swiss/de/terms-of-use), [news.admin.ch](https://www.admin.ch/gov/de/start/rechtliches.html), [lebendige-traditionen.ch](https://www.lebendige-traditionen.ch/) |\n\n---\n\n## Known Limitations\n\n- **ISOS statistics:** Sample-based per canton (not exhaustive for all cantons)\n- **Living Traditions:** HTML scraping – may break if lebendige-traditionen.ch changes its structure\n- **BAK news/prizes:** RSS feed limited to the most recent entries\n- **opendata.swiss CKAN:** Full-text search may return results from other publishers\n- **The addresses this server hands out are measured, not assumed.** `scripts/record_fixtures.py` re-checks every one on each run, together with four controls (an invented geo.admin.ch service, an invented BAK path, an invented news organisation number, an invented tradition slug). On 2026-08-08 one was dead: `bak_isos_overview` published `.../home/kulturerbe/baukultur.html` as its BAK source — HTTP 404, as is the whole `kulturerbe` branch. It was replaced by the BAK root, which verifiably answers 200, not by a guessed replacement URL.\n- **Everything else held.** geo.admin.ch, opendata.swiss, gisos, isos, the news feed with `org-nr=314` and the tradition pages all return real content. That null result is recorded too: without it the next pass starts from nothing.\n\n---\n\n## Synergies with Other MCP Servers\n\n`swiss-culture-mcp` can be combined with other servers in the portfolio:\n\n| Combination | Use Case |\n|---|---|\n| `+ swiss-transport-mcp` | Cultural tourism: day trips to traditions by public transport |\n| `+ zurich-opendata-mcp` | Local cultural atlas: ISOS + Zurich city events |\n| `+ global-education-mcp` | Cultural education in international comparison |\n| `+ fedlex-mcp` | Cultural property transfer act + BAK enforcement practice |\n| `+ swiss-statistics-mcp` | Cultural expenditure by canton (BFS data) |\n\n---\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md)\n\n---\n\n## Contributing\n\nContributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n---\n\n## Security\n\nSecurity posture, hardening details and the responsible-disclosure process are documented in [SECURITY.md](SECURITY.md).\n\n---\n\n## License\n\nMIT License — see [LICENSE](LICENSE)\n\n---\n\n## Author\n\nHayal Oezkan · [malkreide](https://github.com/malkreide)\n\n---\n\n## Credits & Related Projects\n\n- **Data:** [Bundesamt für Kultur (BAK)](https://www.bak.admin.ch/) – Federal Office of Culture\n- **ISOS:** [geo.admin.ch](https://geo.admin.ch/) – Federal Office of Topography swisstopo\n- **Traditions:** [lebendige-traditionen.ch](https://www.lebendige-traditionen.ch/) – BAK living traditions registry\n- **Protocol:** [Model Context Protocol](https://modelcontextprotocol.io/) – Anthropic / Linux Foundation\n- **Related:** [zurich-opendata-mcp](https://github.com/malkreide/zurich-opendata-mcp) – MCP server for Zurich city open data\n- **Portfolio:** [Swiss Public Data MCP Portfolio](https://github.com/malkreide)\n\n<!-- mcp-name: io.github.malkreide/swiss-culture-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    \"swiss-culture-mcp\": {\n      \"command\": \"uvx\",\n      \"args\": [\n        \"swiss-culture-mcp\"\n      ]\n    }\n  }\n}\n```\n<!-- END GENERATED: install -->\n",
  "bytes": 14490,
  "sha": "3f969ad35ebfe0163f6529aa5d26e23c6aef1b779efbfc4a9ecf0bb40f1aca47",
  "repo_slug": "malkreide/swiss-culture-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_malkreide_swiss_culture_mcp_1576f85a/readme"
}