关于 zh-education-mcp
zh-education-mcp 是面向教育数据分析者的 MCP 服务,连接苏黎世州教育统计 BISTA 公共 API。它提供按学区、学校类型、国籍和居住地划分的汇总数据,无需 API 密钥。
主要功能
- 01学区学生人数趋势
- 02全州学生统计概览
- 03中学类型与学生结构
- 04按学校社区统计国籍
- 05按市镇统计高中毕业率
- 06标准输入输出与 HTTP 传输
适用场景
- 01比较 Letzi 等学区的学生人数变化
- 02查看 Sek A、B、C 人数分布
- 03查询市镇学生国籍构成
- 04查看苏黎世市高中毕业率
MCP 相关
作为 MCP 服务,它向客户端提供 8 个只读教育统计工具,数据来自 BISTA 公共 API。支持标准输入输出和 Streamable HTTP。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🇨🇭 属于 瑞士公共数据 MCP 项目组合
📊 zh-education-mcp
用于获取苏黎世州和苏黎世市教育统计数据(BISTA)的 MCP 服务
概述
zh-education-mcp 将 AI 助手连接到 苏黎世州教育统计局(Bildungsstatistik Kanton Zürich,BISTA)——苏黎世州的官方教育统计数据。它提供结构化访问,可查询学生人数、学区趋势、中学概况、国籍分布以及高中毕业率。
| 来源 | 数据 | API |
|---|---|---|
| 苏黎世州 BISTA | 学习者统计数据(Volksschule、Mittelschulen、Maturität) | REST/CSV |
所有数据均通过 BISTA 公共 API(bista.zh.ch/basicapi/ogd/)获取——无需 API 密钥。数据每年于 9 月 15 日更新(参考日期)。
示例查询: “过去 5 年,Letzi 学区的学生人数有何变化?”
演示
功能
- 📊 8 个工具,覆盖所有学段的教育数据
- 🔍 学区趋势——从 2000 年至今,查询所有 Schulkreise(Letzi、Glattal、Schwamendingen、Oerlikon、Uto、Waidberg、Zürichberg)的学生人数
- 🏫 中学概况——按要求类型细分(Sek A/B/C、Mittelschule、特殊班级)
- 🌐 国籍构成——按学校社区列出学生人数最多的国籍
- 🎓 高中毕业率——按市镇、区和州查询 Maturitätsquote
- 📈 全州概览——按学段、类型、性别和国籍统计所有学习者
- 🏠 按居住地统计的趋势——按居住地(Bezirk / Gemeinde)统计学生人数
- 🏛️ Mittelschulen——Gymnasium、FMS、HMS 统计数据
- 🔓 无需 API 密钥——所有数据均采用 CC BY 4.0 许可
- ☁️ 双重传输方式——stdio(Claude Desktop)+ Streamable HTTP(云端)
前置条件
- Python 3.11+
- uv(推荐)或 pip
安装
# Clone the repository
git clone https://github.com/malkreide/zh-education-mcp.git
cd zh-education-mcp
# Install
pip install -e .
# or with uv:
uv pip install -e .
或使用 uvx(无需永久安装):
uvx zh-education-mcp
快速开始
# stdio (for Claude Desktop)
python -m zh_education_mcp.server
# Streamable HTTP (port 8000)
python -m zh_education_mcp.server --http --port 8000
在 Claude Desktop 中立即试用:
“Wie hat sich die Lernendenzahl im Schulkreis Letzi entwickelt?” “Zeige die Maturitätsquote der Stadt Zürich” “Welche Nationalitäten sind in Adliswil am häufigsten?”
→ 按受众分类的更多用例 →
配置
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%\Claude\claude_desktop_config.json(Windows):
{
"mcpServers": {
"zh-education": {
"command": "python",
"args": ["-m", "zh_education_mcp.server"]
}
}
}
或使用 uvx:
{
"mcpServers": {
"zh-education": {
"command": "uvx",
"args": ["zh-education-mcp"]
}
}
}
配置文件位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
云端部署(用于浏览器访问的 Streamable HTTP)
适用于通过浏览器中的 claude.ai 使用(例如,在未安装本地软件的受管工作站上):
Render.com(推荐):
- 将仓库推送到 GitHub 或将其复刻到 GitHub
- 在 render.com 上:New Web Service → 运行时选择 Docker(使用提供的
Dockerfile) - 设置环境变量:
MCP_TRANSPORT=streamable-http、MCP_HOST=0.0.0.0、MCP_PORT=8000和MCP_CORS_ORIGINS=https://claude.ai - 在 claude.ai 的 Settings → MCP Servers 中添加:
https://your-app.onrender.com/mcp
💡 “开发者笔记本电脑使用 stdio,浏览器使用 Streamable HTTP。”
健康检查:GET /health。完整部署指南(容器、负载均衡、CORS、资源限制):docs/deployment.md。
可用工具
| 工具 | 描述 |
|---|---|
zh_edu_list_schulgemeinden | 列出苏黎世州的所有学校社区 / Schulkreise |
zh_edu_schulkreis_trend | 按 Schulkreis 划分的学生趋势(2000 年至今) |
zh_edu_overview | 按学校级别划分的全州学习者概览 |
zh_edu_sek1_profil | 中学 I 阶段概况(Sek A/B/C 分类) |
zh_edu_staatsangehoerigkeiten | 各学校社区学生的国籍构成 |
zh_edu_maturitaetsquote | 按市镇 / 区划分的 Gymnasium 毕业率 |
zh_edu_wohnort_trend | 按居住地划分的学习者趋势(Bezirk / Gemeinde) |
zh_edu_mittelschulen | 中学统计数据(Gymnasium、FMS、HMS) |
使用场景示例
| 查询 | 工具 |
|---|---|
| “列出苏黎世所有 Schulkreise” | zh_edu_list_schulgemeinden |
| “Letzi 过去 5 年的学生趋势” | zh_edu_schulkreis_trend |
| “Winterthur 有多少 Sek A 学生,相比 Sek B 呢?” | zh_edu_sek1_profil |
| “Zürich-Letzi 的主要国籍” | zh_edu_staatsangehoerigkeiten |
| “Stadt Zürich 的 Maturitätsquote” | zh_edu_maturitaetsquote |
架构
┌─────────────────┐ ┌──────────────────────────────┐ ┌──────────────────────────┐
│ Claude / AI │────▶│ zh-education-mcp │────▶│ BISTA Kanton Zürich │
│ (MCP Host) │◀────│ (MCP Server) │◀────│ REST/CSV (Public API) │
└─────────────────┘ │ │ └──────────────────────────┘
│ 8 Tools │
│ Stdio | Streamable HTTP │
│ 24h Cache │
│ No authentication required │
└──────────────────────────────┘
数据源特征
| 来源 | 协议 | 覆盖范围 | 身份验证 | 更新 |
|---|---|---|---|---|
| BISTA Kanton ZH | REST/CSV | 学习者统计数据,2000 年至今 | 无 | 每年(9 月 15 日) |
项目结构
zh-education-mcp/
├── src/zh_education_mcp/
│ ├── __init__.py # Package
│ ├── config.py # ENV settings (MCP_*)
│ ├── constants.py # API base, endpoints, timeouts
│ ├── logging_setup.py # structured stderr logging
│ ├── identity.py # server identity for `_meta` / `server/discover`
│ ├── provenance.py # response envelope, license attribution
│ ├── http_client.py # egress guard, connection pool, lifespan
│ ├── data.py # cache, CSV fetch, filters, error handling
│ ├── models.py # Pydantic input models
│ ├── tools.py # FastMCP instance, 8 tools, 2 resources
│ └── server.py # thin composition layer + entrypoint
├── tests/
│ └── test_server.py # Unit tests (mocked HTTP with respx)
├── docs/ # deployment, security, egress, roadmap, …
├── Dockerfile # multi-stage, non-root, healthcheck
├── docker-compose.yml # resource limits, read-only rootfs
├── .github/workflows/ci.yml # GitHub Actions (Python 3.11/3.12/3.13)
├── .github/dependabot.yml # monthly dependency updates
├── pyproject.toml
├── CHANGELOG.md
├── CONTRIBUTING.md # + CONTRIBUTING.de.md
├── SECURITY.md # + SECURITY.de.md
├── LICENSE
├── README.md # This file (English)
└── README.de.md # German version
已知限制
- **仅每年更新:**BISTA 数据每年更新一次(参考日期:9 月 15 日)。24 小时内存缓存与此周期相符。
- **基于 CSV 的 API:**BISTA API 返回 CSV 数据;解析大型数据集可能需要一些时间。
- **学校社区名称:**名称必须完全匹配(使用
zh_edu_list_schulgemeinden查找有效名称)。
安全与限制
| 主题 | 详情 |
|---|---|
| 无个人数据 | BISTA 统计数据经过汇总,不会公开或提供任何学生个人数据。所有数据均在学校社区层面匿名化。 |
| 只读 | 所有工具均为只读(readOnlyHint: true)。服务无法修改、删除或写入任何数据。 |
| 无需身份验证 | BISTA API 完全公开。不存储或传输 API 密钥、令牌或凭据。 |
| 速率限制 | BISTA API 没有公开说明的速率限制,但服务使用 24 小时内存缓存来尽量减少请求。请负责任地使用。 |
| 数据许可 | 苏黎世州依据 CC BY 4.0 发布所有数据。署名:Bildungsstatistik Kanton Zürich (BISTA)。 |
| 服务条款 | 使用须遵守 BISTA 使用条款。此 MCP 服务是独立的开源项目,与苏黎世州无关联。 |
| AI 输出免责声明 | 统计数据按原样从 BISTA API 传递。AI 生成的解读或摘要应通过 BISTA 官方门户核实。 |
测试
# Unit tests (no API calls)
PYTHONPATH=src pytest tests/ -m "not live"
# Integration tests (live API calls)
pytest tests/ -m "live"
实时测试套件还会按计划运行:每周一 05:23 UTC,以及按需运行(live-tests.yml)。运行失败时会创建一个带有 upstream 标签的 issue;运行成功时则会关闭该 issue。-m "not live" 并不是运行测试的地方,而这里的这三项测试是唯一能够验证关于 BISTA 的错误假设的测试——请参阅
CONTRIBUTING。
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 时不会悄然更改其中任何一个。握手上限通过组装后的 ASGI 堆栈发送实时 initialize 请求进行测量,而非从常量名称读取。
请注意,SDK 的 LATEST_PROTOCOL_VERSION 是现代时代的别名,而非握手时代的别名——仅以它为基准固定版本,会让当前客户端实际协商的时代存在漂移空间。
服务本身在现代时代提供的内容
支持该修订版是 SDK 的职责。服务需要提供的内容列于此处,并在
tests/test_modern_protocol.py 中通过组装后的 ASGI 堆栈发送真实请求进行测量,而非针对常量进行断言:
2026-07-28 的要求 | 此服务的提供方式 |
|---|---|
每个结果都带有 serverInfo 标记(规范 #3002) | 名称、标题、版本、描述和网站——来自包元数据,请参阅 identity.py |
server/discover(“服务必须实现”) | 返回 supportedVersions、capabilities 和 instructions |
提供给模型的 instructions | 参考日期、抑制显示的较小计数、署名义务、只读范围——刻意包含工具描述中未提及的内容 |
每个结果都带有 resultType | 由 SDK 设置,并在此处与线路上的值进行断言比对 |
信封和标头验证(Mcp-Method、Mcp-Name、Mcp-Protocol-Version) | 相互矛盾的标头会以 -32020 拒绝,缺少信封则会以 -32602 拒绝 |
| 新鲜度提示(SEP-2549) | 每种可缓存的列表方法都带有 ttlMs 300,000 / cacheScope public;resources/read 则刻意不带这些字段 |
身份信息并非维护在 src/ 中:版本、描述和网站来自发行版元数据,因此源自 pyproject.toml——这是 check_version_sync.py 允许的唯一来源。在此修订版之前,服务会在每个现代时代的结果上写入 version: ""。
更新政策。 门禁失败时,不要盲目修改常量:阅读两个修订版之间的规范变更日志,确认服务仍然正常运行,然后一起更新常量、本节、README.de.md 和
CHANGELOG.md。
项目阶段: 阶段 1——只读(所有工具均为 readOnlyHint: true)。请参阅
docs/roadmap.md。
发布
发布由 GitHub release(release: published →
publish.yml)驱动:构建 → 门禁检查 → PyPI → MCP Registry。
门禁检查(check_release_artifacts.py)会在上传之前运行,并检查构建好的 wheel,而不是源文件:
- wheel METADATA 中必须恰好有一个
mcp-name:标记(HTML 注释,见本文件底部)——MCP Registry 通过它验证 PyPI 所有权——且该标记必须与server.json中的name一致 server.json中的description不得超过 100 个字符;Registry 会返回422,而此时 PyPI 上传早已成功server.json中的版本必须与pyproject.toml中的版本一致,且 git 标签必须与实际构建的版本一致
门禁检查安排在上传之前,因为上传后无从修正:PyPI 版本不可变,因此修复需要递增版本号。
**如果你编辑此 README:**文件最底部的标记会作为软件包描述的一部分发布(pyproject.toml 中的 readme = "README.md"),删除它会导致门禁检查失败。README.de.md 不包含标记,也不会发布。上述版本徽章会在每个 pull request 中由 check_version_sync.py 对照 pyproject.toml 和 server.json 进行检查。
更新日志
请参阅 CHANGELOG.md
贡献
请参阅 CONTRIBUTING.md · 🇩🇪 Beitragen
安全
请参阅 SECURITY.md · 🇩🇪 Sicherheit
许可证
MIT 许可证 — 请参阅 LICENSE
作者
Hayal Oezkan · malkreide
致谢与相关项目
- BISTA:pub.bista.zh.ch — 苏黎世州教育统计(CC BY 4.0)
- 协议:Model Context Protocol — Anthropic / Linux Foundation
- 相关:zurich-opendata-mcp — 苏黎世市开放数据(停车、天气、议会)
- 相关:swiss-cultural-heritage-mcp — 瑞士文化遗产数据
- 相关:fedlex-mcp — 瑞士联邦法律
- 作品集:Swiss Public Data MCP Portfolio
安装
通过 uv 的 uvx 运行——无需克隆或手动安装。将其添加到 MCP 客户端配置中(Claude Desktop、Cursor 和 Windsurf 使用 mcpServers;VS Code 在 .vscode/mcp.json 中使用顶层 servers 键):
{
"mcpServers": {
"zh-education-mcp": {
"command": "uvx",
"args": [
"zh-education-mcp"
]
}
}
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。