Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
作者提供的说明(英文原文)
ETH Library Discovery API
这三项永远不会合并成一个分数:意见、测量和人气是不同的东西。
我们还没有为它写通俗的介绍。下面是我们从注册中心读取到的事实。
选择你使用的 AI 应用,然后复制设置。
你需要
你用的是哪个应用?
在上方选择你的应用。我们会记住它,下次按钮会显示“安装到 …”。
打开 Claude Desktop → Settings → Developer → Edit Config,把下面的内容粘贴到 claude_desktop_config.json
{
"mcpServers": {
"eth-library": {
"command": "uvx",
"args": [
"eth-library-mcp"
]
}
}
}在终端中运行这条命令
claude mcp add eth-library -- uvx eth-library-mcp粘贴到项目中的 .cursor/mcp.json,或 ~/.cursor/mcp.json
{
"mcpServers": {
"eth-library": {
"command": "uvx",
"args": [
"eth-library-mcp"
]
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
粘贴到项目中的 .vscode/mcp.json
{
"servers": {
"eth-library": {
"type": "stdio",
"command": "uvx",
"args": [
"eth-library-mcp"
]
}
}
}浏览器会先询问是否打开应用,然后应用会显示设置并请你确认。密钥的值会留空,由你自己填写。
这个服务器在你的电脑上运行,而 ChatGPT 只能连接互联网上的服务器。请选择其他应用。
你的选择通过 Cookie 保存在这台设备上,无需账户。
这些设置是根据作者在注册中心的条目生成的。如果 README 的写法不同,请以 README 为准。
它在你的电脑上运行;安装后,工具列表会显示在你的 AI 应用中。
我们检查的是任何人都能看到的信息;我们没有阅读代码。不适用的检查项不计入总数。 · 检查于 2026年11月8日
注册名称已通过 GitHub 账户 malkreide 验证,该账户拥有此仓库
我们还没有从 GitHub 读取这个仓库
我们还没有从 GitHub 读取这个仓库
它在你的电脑上运行,没有互联网端点
在你的电脑上运行,改用本地设置
它在你的电脑上运行;我们只能读取互联网端点的工具列表
与注册中心里这个分类中所有活跃的服务器比较。只有当发布者拥有该仓库时,星标数才计入。
它在 1 项适用的基础检查中通过了 1 项。我们没有阅读代码。在添加密钥或令牌之前,请先看看这个服务器要求哪些权限,并使用只具备所需权限的密钥。
注册中心没有列出必需的密钥,不过有些服务器会在首次使用时要求你登录。
它在你的电脑上运行。你的 AI 应用会在需要时启动它,数据不会经过作者的服务器(除非它自己调用在线服务)。
GitHub 仓库最后更新于–,最新版本(0.4.0)于2个月前进入注册中心。
支持 MCP 的应用,例如 Claude Desktop、Claude Code、Cursor 和 VS Code。你的电脑上还需要有 Python (uv)。
同一分类中有:Spec Driven Development, Remote Desktop Commander, A1RO — Irish employment tools
同一分类中其他作者的服务器,按星标数排序。
如何看卡片:★ GitHub 星标i三大支柱:评价 · 检查 · 使用情况i更新 = 最新版本发布到注册中心的时间i
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Irish temp worker cost, public holiday pay and holidays, and SafeHandle certificate checks.
按原文从作者的仓库复制。PopNx MCP 没有审查或背书其内容。HTML、图片和脚本已被移除。链接会离开本站。
🇨🇭 Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)
🌐 English | [Deutsch](README.de.md)
MCP server giving AI models direct access to 30M+ resources at ETH Library Zurich – books, maps, images and archival material.
eth-library-mcp connects AI assistants like Claude to the largest natural-science library in Switzerland. It exposes full-text search, archive-level queries and resource-type filtering via the ETH Library's Discovery API – all through a single, standardised MCP interface.
6 Tools · 1 API · 2 Resources · 2 Prompts
MCP Protocol Version: 2026-07-28 (via mcp[cli]>=2.0.0,<3).
BUG-02 is resolved — by removing the tool.
eth_search_personswas documented
as "currently non-functional, correct URL to be verified". It has now been verified,
and there is no correct URL: the Persons API is gone from the gateway, not merely
locked. The gateway routes *before* it checks the API key, so an existing route
answers
401and a missing one answers404—/discovery/v1/resourcesgives 401,
every
/persons/v1/*path gives 404, and so does a deliberately invented Discovery
path used as a control. Offering a capability that cannot exist is the same mistake as
returning an empty result, only louder. The measurement is recorded and dated in
tests/fixtures/api_routes.json.
Anchor demo query: *"Find historical documents about Zurich school history in the ETH Library archives."*
# Clone the repository
git clone https://github.com/malkreide/eth-library-mcp.git cd eth-library-mcp
pip install -e .
uv pip install -e .
# Set the API key
export ETH_LIBRARY_API_KEY=your_key_here # macOS / Linux
python -m eth_library_mcp.server
Without an API key the server returns a helpful error message with the registration link – no crashes.
Try it immediately in Claude Desktop:
*"Find books about Swiss education history in the ETH Library."*
*"Search the Max Frisch archive for manuscripts about Zurich."*
→ More use cases by audience →
| Variable | Description | Required |
|---|---|---|
ETH_LIBRARY_API_KEY | API key for the Discovery API | ✅ |
ETH_LIBRARY_LOG_LEVEL | Log level (DEBUG/INFO/WARNING/ERROR), default INFO | — |
ETH_LIBRARY_CORS_ORIGINS | Comma-separated CORS allow-origins for --http. Empty by default: no browser client is permitted. * allows any origin and is logged as a warning. Does not affect stdio clients. | — |
ETH_LIBRARY_ALLOWED_HOSTS | Comma-separated hostnames this server is reachable under. Required for a non-loopback bind (--host 0.0.0.0): the process cannot derive its own public name, and without this the SDK answers 421 Invalid Host header to every request. Empty by default; loopback stays reachable either way. | — |
{
"mcpServers": { "eth-library": { "command": "python", "args": ["-m", "eth_library_mcp.server"], "env": { "ETH_LIBRARY_API_KEY": "your_key_here" } } } }
Config file locations:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonFor use via claude.ai in the browser (e.g. on managed workstations without local software):
python -m eth_library_mcp.server --http --port 8000
The HTTP transport binds to 127.0.0.1 by default. To expose it on another interface, pass --host explicitly:
# Only behind a reverse-proxy / firewall that terminates TLS and enforces auth.
python -m eth_library_mcp.server --http --host 0.0.0.0 --port 8000
⚠️ Do not bind to `0.0.0.0` without a reverse proxy. The server has no
built-in auth, rate-limiting or TLS — any LAN neighbour could call your tools.
💡 *"stdio for the developer laptop, HTTP for the browser — behind a proxy."*
| Tool | Description |
|---|---|
eth_search_resources | Full-text search over 30M+ resources with fields, operators, facets |
eth_get_resource | Full metadata for a specific resource via MMS-ID |
eth_search_archive | Search within a specific archive (University Archives, Max Frisch, Thomas Mann, etc.) |
eth_search_by_type | Filter by resource type (books, maps, images, archival material, etc.) |
eth_search_education | Curated search for education topics (pedagogy, school history, etc.) |
| Tool | Description |
|---|---|
eth_library_info | Server overview: all types and archives at a glance |
| Item | Type | Description |
|---|---|---|
eth://resource-types | Resource | All available resource types |
eth://archives | Resource | All available archives and collections |
research-workflow | Prompt | Structured research workflow |
education-research | Prompt | Education topics workflow (Schulamt-optimised) |
The Discovery API uses structured queries:
field,operator,value
| Field | Meaning |
|---|---|
any | All fields (recommended for starters) |
title | Title only |
creator | Author / creator |
sub | Subject headings / topics |
| Operator | Meaning |
|---|---|
contains | Term is present |
exact | Exact match |
begins_with | Starts with |
Examples:
any,contains,Volksschule Zürich
title,contains,Pädagogik creator,exact,Einstein Albert sub,contains,Bildungsforschung title,contains,Schule;sub,contains,Geschichte
| Identifier | Description |
|---|---|
ETH_Hochschularchiv | Institutional memory of ETH Zurich |
ETH_MaxFrischArchiv | Estate of Swiss author Max Frisch |
ETH_ThomasMannArchiv | Letters and documents of Thomas Mann |
ETH_GraphischeSammlung | Prints, drawings, graphic works |
ETH_Bildarchiv | Science/technology history, Swissair (E-Pics) |
| Query | Tool |
|---|---|
| *"Find books about Zurich school history"* | eth_search_education |
| *"What's in the Max Frisch archive?"* | eth_search_archive |
| *"Find historical maps of Switzerland"* | eth_search_by_type |
| *"Get full metadata for resource ID 991170525863705501"* | eth_get_resource |
| *"Which archives does the ETH Library hold?"* | eth_library_info |
eth-library-mcp/
├── src/ │ └── eth_library_mcp/ │ ├── init.py # Package init, version │ └── server.py # FastMCP server, all tools ├── tests/ │ └── test_server.py # Unit tests ├── CHANGELOG.md ├── CONTRIBUTING.md # Contribution guide (English) ├── CONTRIBUTING.de.md # Contribution guide (German) ├── SECURITY.md # Security posture (English) ├── SECURITY.de.md # Security posture (German) ├── LICENSE ├── README.md # This file (English) ├── README.de.md # German version ├── claude_desktop_config.json # Example Claude Desktop configuration └── pyproject.toml # Build configuration
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 handshake ceiling is measured against a live initialize through the assembled ASGI stack, not read off a constant name.
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.
serverInfo)2026-07-28 stamps the server's Implementation block into every modern result under _meta.io.modelcontextprotocol/serverInfo (spec #3002) — earlier revisions carried it only in the initialize result. What used to be a one-time field is now repeated on every call, and version is required.
The SDK fills none of it: *"An unversioned server reports an empty version; the SDK never substitutes its own."* Measured against the assembled ASGI stack, this server used to answer "version": "" in both eras while server.json told the registry 0.3.4. It now declares:
| Field | Value | Source |
|---|---|---|
name | eth-library-mcp | the programmatic identifier — the same string as the distribution name in pyproject.toml, packages[0].identifier in server.json and the suffix of the registry name io.github.malkreide/eth-library-mcp. It used to read eth_library_mcp, the module path: a name under which this server is available nowhere. |
title | ETH-Bibliothek Zürich | SERVER_TITLE in server.py — the only value with no source outside |
version | the installed distribution's version | importlib.metadata, so it cannot drift from pyproject.toml |
description | the distribution summary | importlib.metadata |
websiteUrl | the Homepage project URL | importlib.metadata |
icons stays unset: this repository ships none, and an invented path would assert a file that does not exist.
M
只显示了开头部分;其余内容请在仓库中阅读