关于 swiss-culture-mcp
面向文化研究的 MCP 服务,提供瑞士联邦文化局的数据,包括受保护城镇景观、活态传统、文化奖项、新闻稿和数据集。它使用公开数据源,无需 API 密钥。
主要功能
- 01按地点搜索 ISOS 城镇景观
- 02按州或类别列出 ISOS 条目
- 03获取景观详情和统计数据
- 04浏览瑞士活态传统
- 05查询文化奖项及联邦文化局新闻稿
- 06查找 opendata.swiss 上的联邦文化局数据集
适用场景
- 01确认瑞士某处城镇景观是否受保护
- 02了解某州传承的活态传统
- 03查询瑞士文化奖项和公告
- 04查找 opendata.swiss 上的联邦文化局数据集
MCP 相关
提供十种工具和三个资源,用于查询文化遗产及相关公共数据。支持 stdio 和 Streamable HTTP 传输。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🇨🇭 属于瑞士公共数据 MCP 组合
🏛️ swiss-culture-mcp
瑞士文化遗产数据的 MCP 服务,数据来自瑞士联邦文化局(BAK)——ISOS 城镇景观、活态传统、文化奖项、新闻稿。无需 API 密钥。
🌐 English | Deutsch
概述
swiss-culture-mcp 让 AI 助手能够访问瑞士文化数据。该服务将 Claude 等大模型与瑞士的国家文化遗产相连接,涵盖受保护的城镇景观(ISOS)、非物质文化遗产活态传统以及当前文化奖项。
数据来源: geo.admin.ch REST API · news.admin.ch RSS · opendata.swiss CKAN · lebendige-traditionen.ch
无需 API 密钥。 所有数据来源均公开可用(开放政府数据)。
核心演示查询: “苏黎世市的学区内有哪些受保护的城镇景观,当地有哪些活态传统?”
功能
- 🏘️ ISOS 搜索 – 按名称、州或聚落类型搜索瑞士受保护城镇景观联邦名录
- 📜 活态传统 – 瑞士非物质文化遗产的 228 条记录
- 🏆 文化奖项 – 瑞士电影奖、文学大奖、音乐奖等
- 📰 BAK 新闻稿 – 瑞士联邦文化局的最新消息
- 📦 开放数据目录 – opendata.swiss 上的 BAK 数据集
- ☁️ 双重传输方式 – 面向 Claude Desktop 的 stdio,以及用于云部署的 Streamable HTTP
| # | 工具 | 说明 |
|---|---|---|
| 1 | bak_search_isos | 按地名搜索 ISOS 城镇景观 |
| 2 | bak_isos_by_kanton | 列出某个州的所有 ISOS 对象 |
| 3 | bak_get_isos_detail | 获取 ISOS 对象的完整详情 |
| 4 | bak_isos_by_kategorie | 按聚落类型筛选 ISOS(城市、村庄等) |
| 5 | bak_isos_statistics | ISOS 名录统计(按州抽样) |
| 6 | bak_get_news | BAK 最新新闻稿 |
| 7 | bak_get_kulturpreise | 瑞士文化奖项(电影奖、文学大奖等) |
| 8 | bak_get_opendata | opendata.swiss 上的 BAK 数据集 |
| 9 | bak_list_traditions | 列出瑞士的活态传统 |
| 10 | bak_get_tradition_detail | 获取传统的详细说明 |
3 个资源: bak://isos/kantone · bak://isos/kategorien · bak://kulturpreise/uebersicht
数据来源
| 来源 | API 类型 | 内容 |
|---|---|---|
| geo.admin.ch | REST MapServer | ISOS(瑞士城镇景观联邦名录) |
| news.admin.ch | RSS Feed | BAK 新闻稿、文化奖项 |
| opendata.swiss | CKAN REST API | BAK 开放数据集 |
| lebendige-traditionen.ch | HTML Fetch | 228 条非物质文化遗产记录 |
前提条件
- Python 3.11+
uv或pip- 无需 API 密钥
安装
# Recommended: uvx (no install step needed)
uvx swiss-culture-mcp
# Alternative: pip
pip install swiss-culture-mcp
快速入门
# Start the server (stdio mode for Claude Desktop)
uvx swiss-culture-mcp
立即在 Claude Desktop 中试用:
“显示格劳宾登州所有受保护的城镇景观” “阿彭策尔州有哪些活态传统?” “2026 年颁发了哪些瑞士文化奖项?”
配置
环境变量
| 变量 | 默认值 | 描述 |
|---|---|---|
MCP_TRANSPORT | stdio | 传输方式:stdio 或 streamable_http(也接受 streamable-http)。只有通过 HTTP 传输方式才能访问 2026-07-28 年代的数据。 |
MCP_HOST | 127.0.0.1 | HTTP 传输方式的绑定主机(默认仅限本地回环) |
MCP_PORT | 8000 | HTTP 传输方式的端口 |
MCP_ALLOW_PUBLIC_BIND | false | 若为 true,则允许在未进行身份验证的情况下绑定 0.0.0.0。仅在经过身份验证的反向代理(例如 Cloudflare Access、oauth2-proxy)之后使用此设置。 |
MCP_ALLOWED_HOSTS | (空) | 此服务响应的主机名,以逗号分隔,不包含协议(mcp.example.ch)。用于 HTTP 传输方式的 Host/Origin 检查。所有非本地回环部署都必须设置此项——请参阅下方警告。无论如何都会允许本地回环,因此容器健康检查仍能正常运行。 |
ALLOWED_ORIGINS | (空) | 以逗号分隔的 CORS 来源,包含协议(https://claude.ai)。留空表示不允许基于浏览器的 MCP 客户端;stdio 和非浏览器客户端不受影响。* 可用,但会记录为警告。 |
LOG_LEVEL | INFO | DEBUG、INFO、WARNING、ERROR——以结构化 JSON 格式向 stderr 输出日志 |
Claude Desktop 配置
{
"mcpServers": {
"swiss-culture": {
"command": "uvx",
"args": ["swiss-culture-mcp"]
}
}
}
配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
重启 Claude Desktop 后,即可使用所有工具。示例查询:
- “请列出格劳宾登州所有受保护的城镇景观”
- “什么是阿尔卑斯长号和 Büchelspiel 传统?”
- “2026 年颁发了哪些瑞士文化奖项?”
- “施泰因阿姆莱茵老城是否列入 ISOS 名录?”
- “阿彭策尔州有哪些活态传统?”
云端部署(Streamable HTTP)
通过浏览器中的 claude.ai 使用(例如在没有本地软件的托管工作站上):
连接器 URL 始终是部署主机加传输路径:
https://<host>/mcp。在 claude.ai 的 Settings → MCP Servers 下添加。
Render.com(推荐):
- 将仓库推送到 GitHub,或在 GitHub 上复刻仓库
- 在 render.com:New Web Service → 连接 GitHub 仓库
- 在 Render 控制面板中设置环境变量,包括
MCP_ALLOWED_HOSTS=your-app.onrender.com,以及浏览器客户端所需的ALLOWED_ORIGINS=https://claude.ai - 在 claude.ai 的 Settings → MCP Servers 下添加:
https://your-app.onrender.com/mcp
Docker。 仓库提供了多阶段 Dockerfile
(python:3.13-slim、非 root 用户、TCP 健康检查)。它预设了传输方式、
0.0.0.0 绑定和 MCP_ALLOW_PUBLIC_BIND=true,因为在容器内部,平台的边缘代理是唯一的入口。镜像中有意不设置
MCP_ALLOWED_HOSTS——主机名取决于部署位置,猜测一个主机名会导致所有真实请求都被拒绝并返回 HTTP 421:
docker build -t swiss-culture-mcp .
docker run -p 8000:8000 \
-e MCP_ALLOWED_HOSTS=mcp.example.ch \
-e ALLOWED_ORIGINS=https://claude.ai \
swiss-culture-mcp
这两个变量负责防护不同的内容,不能互相替代。 在
0.0.0.0绑定下对本服务进行测试,且请求携带Origin: https://claude.ai时:
MCP_ALLOWED_HOSTSALLOWED_ORIGINSHost/Origin 检查 POST 预检请求 已设置 已设置 已启用 200允许 已设置 — 已启用 403拒绝 — 已设置 已关闭 200允许 — — 已关闭 200拒绝 请逐列阅读,因为这两种失败的类型并不相同。
ALLOWED_ORIGINS决定浏览器客户端能否正常工作:未设置时,请求会被拒绝(Host 允许列表启用时,传输层会返回403——即Origin被拒绝;若Host被拒绝,则会返回421),或者浏览器无法读取响应。MCP_ALLOWED_HOSTS决定部署是否安全:未设置时,build_transport_security()会返回None,完全不检查Host和Origin标头。第三行就是陷阱——浏览器客户端可以连接,一切看起来正常,但部署却容易遭受 DNS 重绑定攻击。在公共绑定上同时设置这两个变量;仅当不打算让浏览器客户端访问服务时,才不设置ALLOWED_ORIGINS,并且绝不要在公共绑定上不设置MCP_ALLOWED_HOSTS。
# Local HTTP mode (loopback only — safe default, no allow-list needed)
MCP_TRANSPORT=streamable_http MCP_PORT=8000 python -m swiss_culture_mcp.server
# Public bind (DANGEROUS — only behind an authenticating reverse proxy)
MCP_TRANSPORT=streamable_http MCP_HOST=0.0.0.0 MCP_ALLOW_PUBLIC_BIND=true \
MCP_ALLOWED_HOSTS=mcp.example.ch python -m swiss_culture_mcp.server
⚠️ 安全: 服务本身没有身份验证。在没有上游身份验证层的情况下绑定到公共接口,会使其成为访问联邦数据源的开放代理。对于
0.0.0.0部署,务必在前置位置运行经过身份验证的反向代理(Cloudflare Access、oauth2-proxy、nginx + auth_request)。
⚠️ 在公共绑定上设置
MCP_ALLOWED_HOSTS。 未设置时,完全不会检查Host和Origin标头,服务因此容易遭受 DNS 重绑定攻击:攻击者将受害者的浏览器指向该服务,并通过伪造的Host与其通信。每次以这种方式启动时,服务都会记录dns_rebinding_protection_off——这条日志是问题的征兆,并非走个形式。回环绑定不需要允许列表;SDK 会根据绑定主机自动生成允许列表。
架构
┌─────────────────┐ ┌──────────────────────────┐ ┌──────────────────────────┐
│ Claude / AI │────▶│ Swiss Culture MCP │────▶│ geo.admin.ch REST │
│ (MCP Host) │◀────│ (MCP Server) │◀────│ news.admin.ch RSS │
└─────────────────┘ │ │ │ opendata.swiss CKAN │
│ 10 Tools · 3 Resources │ │ lebendige-traditionen │
│ Stdio | Streamable HTTP │ └──────────────────────────┘
└──────────────────────────┘
项目结构
swiss-culture-mcp/
├── src/
│ └── swiss_culture_mcp/
│ ├── __init__.py
│ └── server.py # All 10 tools, 3 resources
├── tests/
│ ├── conftest.py # pytest configuration
│ └── test_server.py # 36 tests (unit + live)
├── pyproject.toml
├── CHANGELOG.md
├── CONTRIBUTING.md # Contribution guide (English)
├── CONTRIBUTING.de.md # Contribution guide (German)
├── SECURITY.md # Security policy & posture (English)
├── SECURITY.de.md # Security policy & posture (German)
├── LICENSE
├── README.md # This file (English)
└── README.de.md # German version
MCP 协议版本
此服务通过同一端点支持两个协议时代。客户端在连接上的第一个请求决定使用哪一个;之后若声称属于另一个时代,则会被拒绝。
| 时代 | 修订版本 | 适用对象 |
|---|---|---|
initialize 握手 | 2024-11-05 … 2025-11-25 | 当今客户端使用的协议。服务会以请求指定的修订版本作答;如果请求指定了更新的版本,则使用 2025-11-25 这一上限。 |
| 每请求信封 | 2026-07-28 | 携带 2026-07-28 _meta 信封的请求会建立现代连接。 |
这两个修订版本都固定在
tests/test_protocol_version.py 中,并通过已安装的 SDK 进行断言,因此 Dependabot 更新 mcp 时不会在不知不觉中改变任一版本。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是现代时代的别名,而非握手时代的别名——仅以此为基准固定版本,会让当前客户端实际协商的时代任其漂移。
现代时代是通过测量得出的,而非推断出来的。
tests/test_modern_era.py 会构建服务实际使用的 ASGI 应用,并通过它发送请求:2026-07-28 信封、initialize 握手以及每种格式错误的变体。它会断言现代请求能够得到应答,两个时代彼此独立(现代线路上没有 initialize 方法;握手的版本上限是 2025-11-25,而不会提供 2026-07-28),server/discover 指定的正是固定的修订版本;与之不匹配的修订版本会被拒绝,并返回 -32022,同时指出请求版本和受支持版本;ttlMs/cacheScope 和 serverInfo 会作为线路字段传递。
这一点很重要,因为现代时代只存在于 streamable-HTTP 入口——stdio 和进程内客户端只使用 initialize 握手,不使用其他协议。通过进程内客户端测试规范,测试到的是处理程序,而非协议时代。这一测试盲区掩盖了一个字符级错误:main() 将 HTTP 传输启动为 streamable_http,而 SDK 的 run() 使用的是 streamable-http,因此传输因 ValueError 中止,服务根本没有提供该规范。所有测试仍然通过,因为它们模拟了 mcp.run,并将字符串与手动抄写的相同错字进行比较。
服务身份。 规范 2026-07-28 会在每个响应的 _meta 中携带 serverInfo,而不是像握手时代那样每个会话只携带一次。此服务会使用软件包元数据中的名称、标题、描述、网站 URL 和版本来填充该字段(使用 importlib.metadata,与出站 User-Agent 的数据来源相同);手动维护的字面值会被 scripts/check_version_sync.py 拒绝。
名称为 swiss-culture-mcp——与发行包、控制台脚本、注册表条目和出站 User-Agent 的拼写一致。直到 2026-09-20,它的名称还是 swiss_culture_mcp;如果同一身份在不同位置拼写各异,那它就不是同一个身份。tests/test_servername.py 会将这些来源关联起来,而不是拿字面值与自身比较。Python 日志记录器会刻意保留下划线:那是日志记录器名称,不是服务身份;重命名它只会破坏每位运维人员的日志配置,却无法让任何内容保持一致。
更新策略。 门禁检查失败时,不要盲目修改常量:请阅读这两个修订版本之间的规范更新日志,验证服务行为仍然正确,然后一并更新常量、本节、README.de.md 和
CHANGELOG.md。
测试
# Unit tests (no API key required)
PYTHONPATH=src pytest tests/ -m "not live"
# Integration tests (live API calls)
PYTHONPATH=src pytest tests/ -m "live"
使用示例
学校 / 教育
"Which protected townscapes are there in the school districts of the city of Zurich?"
→ bak_isos_by_kanton(kanton="ZH") + bak_get_isos_detail(...)
"Find living traditions for a project week on the theme of cultural heritage"
→ bak_list_traditions() + bak_get_tradition_detail(slug="...")
"Which UNESCO World Heritage Sites are also in ISOS?"
→ bak_search_isos(query="...") + bak_get_opendata(query="UNESCO")
市政管理 / 空间规划
"Is the building at address X within an ISOS perimeter?"
→ bak_search_isos(query="community/place name")
"Which BAK datasets are available for GIS integration?"
→ bak_get_opendata() → WMS/WFS URLs for GIS software
AI 工作组 / 演示
"Show current cultural policy of the federal government"
→ bak_get_news() + bak_get_kulturpreise()
→ More use cases by audience →
安全性与限制
| 方面 | 详情 |
|---|---|
| 访问权限 | 只读 — 服务无法修改或删除任何数据 |
| 个人数据 | 不涉及个人数据 — 所有来源均为汇总后的公共文化遗产数据 |
| 速率限制 | 内置每次查询上限(例如,最多 100 条 ISOS 结果、50 条新闻和 200 个类别条目) |
| 超时 | 每次 API 调用 20 秒 |
| 身份验证 | 无需 API 密钥 — 所有 4 个数据源均可公开访问 |
| 许可证 | 所有数据均采用开放许可证(Open Government Data):geo.admin.ch、opendata.swiss、news.admin.ch |
| 服务条款 | 受各数据源的服务条款约束:geo.admin.ch、opendata.swiss、news.admin.ch、lebendige-traditionen.ch |
已知限制
- ISOS 统计数据: 按州抽样,并非涵盖所有州
- 活态传统: 通过 HTML 抓取——如果 lebendige-traditionen.ch 更改结构,可能会失效
- BAK 新闻/奖项: RSS 源仅包含最新条目
- opendata.swiss CKAN: 全文搜索可能会返回其他发布方的结果
- 此服务分发的地址均经过实测,而非推测。
scripts/record_fixtures.py会在每次运行时重新检查每个地址,并同时检查四个对照项(虚构的 geo.admin.ch 服务、虚构的 BAK 路径、虚构的新闻机构编号、虚构的传统标识)。2026-08-08,其中一个地址已失效:bak_isos_overview将.../home/kulturerbe/baukultur.html作为其 BAK 来源发布——HTTP 404,整个kulturerbe分支也都如此。它已替换为可确认返回 200 的 BAK 根地址,而不是一个猜测的替代 URL。 - 其他所有项均正常。 geo.admin.ch、opendata.swiss、gisos、isos、带有
org-nr=314的新闻源以及传统页面都返回真实内容。这个空结果也会被记录:没有它,下次检查就只能从零开始。
与其他 MCP 服务的协同
swiss-culture-mcp 可与产品组合中的其他服务搭配使用:
| 组合 | 使用场景 |
|---|---|
+ swiss-transport-mcp | 文化旅游:乘坐公共交通前往传统文化目的地进行一日游 |
+ zurich-opendata-mcp | 本地文化地图集:ISOS + 苏黎世市活动 |
+ global-education-mcp | 国际比较中的文化教育 |
+ fedlex-mcp | 文化财产转让法 + BAK 执法实践 |
+ swiss-statistics-mcp | 各州文化支出(BFS 数据) |
更新日志
请参阅 CHANGELOG.md
参与贡献
欢迎贡献 — 请参阅 CONTRIBUTING.md。
安全
安全状况、加固详情和负责任披露流程记录在 SECURITY.md 中。
许可证
MIT 许可证 — 请参阅 LICENSE
作者
Hayal Oezkan · malkreide
致谢与相关项目
- 数据: Bundesamt für Kultur (BAK) – 联邦文化局
- ISOS: geo.admin.ch – 联邦测绘局 swisstopo
- 传统文化: lebendige-traditionen.ch – BAK 活态传统登记库
- 协议: Model Context Protocol – Anthropic / Linux Foundation
- 相关项目: zurich-opendata-mcp – 苏黎世市开放数据 MCP 服务
- 项目组合: Swiss Public Data MCP Portfolio
安装
通过 uv 的 uvx 运行 — 无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"swiss-culture-mcp": {
"command": "uvx",
"args": [
"swiss-culture-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。