eth-library-mcp 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eth_library_mcp-0.2.0/.github/workflows/ci.yml +58 -0
- eth_library_mcp-0.2.0/.github/workflows/publish.yml +54 -0
- eth_library_mcp-0.2.0/CHANGELOG.md +33 -0
- eth_library_mcp-0.2.0/CONTRIBUTING.md +135 -0
- eth_library_mcp-0.2.0/LICENSE +21 -0
- eth_library_mcp-0.2.0/PKG-INFO +301 -0
- eth_library_mcp-0.2.0/README.de.md +283 -0
- eth_library_mcp-0.2.0/README.md +283 -0
- eth_library_mcp-0.2.0/TEST_PLAN.md +350 -0
- eth_library_mcp-0.2.0/eth_library_mcp/__init__.py +1 -0
- eth_library_mcp-0.2.0/eth_library_mcp/api_client.py +288 -0
- eth_library_mcp-0.2.0/eth_library_mcp/server.py +891 -0
- eth_library_mcp-0.2.0/pyproject.toml +39 -0
- eth_library_mcp-0.2.0/tests/__init__.py +13 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
|
|
22
|
+
- name: Python ${{ matrix.python-version }} einrichten
|
|
23
|
+
uses: actions/setup-python@v6
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: uv installieren
|
|
28
|
+
run: pip install uv
|
|
29
|
+
|
|
30
|
+
- name: Abhängigkeiten installieren
|
|
31
|
+
run: uv pip install -e ".[dev]" --system
|
|
32
|
+
|
|
33
|
+
- name: Linting mit ruff
|
|
34
|
+
run: python -m ruff check eth_library_mcp/
|
|
35
|
+
|
|
36
|
+
- name: Syntax-Prüfung
|
|
37
|
+
run: python -m py_compile eth_library_mcp/server.py eth_library_mcp/api_client.py
|
|
38
|
+
|
|
39
|
+
- name: Import-Test
|
|
40
|
+
run: python -c "from eth_library_mcp.server import mcp; print('Import OK')"
|
|
41
|
+
|
|
42
|
+
- name: Unit-Tests
|
|
43
|
+
run: pytest tests/ -m "not live" -v
|
|
44
|
+
|
|
45
|
+
lint:
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v5
|
|
49
|
+
|
|
50
|
+
- uses: actions/setup-python@v6
|
|
51
|
+
with:
|
|
52
|
+
python-version: "3.11"
|
|
53
|
+
|
|
54
|
+
- run: pip install ruff
|
|
55
|
+
|
|
56
|
+
- run: python -m ruff check eth_library_mcp/
|
|
57
|
+
|
|
58
|
+
- run: python -m ruff format --check eth_library_mcp/
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
env:
|
|
8
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write # Pflicht für Trusted Publisher
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build:
|
|
15
|
+
name: Build distribution
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Python einrichten
|
|
22
|
+
uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
|
|
26
|
+
- name: Build-Tools installieren
|
|
27
|
+
run: pip install build
|
|
28
|
+
|
|
29
|
+
- name: Paket bauen
|
|
30
|
+
run: python -m build
|
|
31
|
+
|
|
32
|
+
- name: Build-Artefakte hochladen
|
|
33
|
+
uses: actions/upload-artifact@v4
|
|
34
|
+
with:
|
|
35
|
+
name: dist
|
|
36
|
+
path: dist/
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
name: Publish to PyPI
|
|
40
|
+
needs: build
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
environment:
|
|
43
|
+
name: pypi
|
|
44
|
+
url: https://pypi.org/project/eth-library-mcp/
|
|
45
|
+
|
|
46
|
+
steps:
|
|
47
|
+
- name: Build-Artefakte herunterladen
|
|
48
|
+
uses: actions/download-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/
|
|
52
|
+
|
|
53
|
+
- name: Auf PyPI publizieren
|
|
54
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Alle nennenswerten Änderungen an diesem Projekt werden hier dokumentiert.
|
|
4
|
+
Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## [0.2.0] – 2026-03-04
|
|
9
|
+
|
|
10
|
+
### Behoben
|
|
11
|
+
- **BUG-01** `pyproject.toml`: Falscher Package-Pfad `src/eth_library_mcp` → `eth_library_mcp` (Installation via `pip install -e .` schlug fehl)
|
|
12
|
+
- **BUG-03** `sort`-Parameter: Beliebige Strings akzeptiert → `Literal["rank","title","author","date"]` (verhindert ungültige API-Anfragen)
|
|
13
|
+
- **BUG-04** `resource_type`-Parameter: Beliebige Strings akzeptiert → vollständiger `Literal`-Typ mit allen 10 gültigen Werten (verhindert stille Leerantworten)
|
|
14
|
+
- **BUG-06** Persons-Response-Parsing: Nur `persons`/`results`-Keys unterstützt → robustes Parsing mit `data`, `items`, `hits` + Logging bei unbekannter Struktur
|
|
15
|
+
- **BUG-07** HTTP-404-Fehlermeldung: Generische "ID prüfen"-Meldung auch bei Suchen → kontext-spezifische Meldungen (`is_search`-Parameter in `handle_api_error`)
|
|
16
|
+
|
|
17
|
+
### Entfernt
|
|
18
|
+
- **BUG-05** Ungenutzte Konstanten `RESEARCH_BASE_URL` und `ETHORAMA_BASE_URL` aus `api_client.py` entfernt
|
|
19
|
+
|
|
20
|
+
### Bekannte Probleme
|
|
21
|
+
- **BUG-02** Persons-API-Endpunkt (`/persons/v1/persons`) gibt HTTP 404 zurück. Die korrekte URL muss via [developer.library.ethz.ch](https://developer.library.ethz.ch) verifiziert werden. Das Tool `eth_search_persons` ist strukturell korrekt implementiert, aber erst nach URL-Verifikation funktionsfähig.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## [0.1.0] – 2026-03-01
|
|
26
|
+
|
|
27
|
+
### Hinzugefügt
|
|
28
|
+
- Initiale Implementierung mit 7 Tools, 3 APIs, 2 Resources, 2 Prompts
|
|
29
|
+
- Discovery API: `eth_search_resources`, `eth_get_resource`, `eth_search_archive`, `eth_search_by_type`, `eth_search_education`
|
|
30
|
+
- Persons API: `eth_search_persons`
|
|
31
|
+
- Dual Transport: stdio (lokal) + SSE (Cloud/Render.com)
|
|
32
|
+
- Graceful Degradation ohne API-Key (hilfreiche Fehlermeldung mit Registrierungslink)
|
|
33
|
+
- Schulamt-spezifisches Tool `eth_search_education` für Bildungsthemen
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Contributing to eth-library-mcp
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to **eth-library-mcp**! This server is part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide) and contributions that strengthen Swiss open-data accessibility for AI assistants are especially welcome.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## How to Contribute
|
|
8
|
+
|
|
9
|
+
### Reporting Issues
|
|
10
|
+
|
|
11
|
+
Use [GitHub Issues](https://github.com/malkreide/eth-library-mcp/issues) to report bugs or request features.
|
|
12
|
+
|
|
13
|
+
When reporting a bug, please include:
|
|
14
|
+
- Python version (`python --version`)
|
|
15
|
+
- Operating system
|
|
16
|
+
- Steps to reproduce the issue
|
|
17
|
+
- Expected vs. actual behaviour
|
|
18
|
+
- Relevant error messages or logs
|
|
19
|
+
|
|
20
|
+
### Open Issues
|
|
21
|
+
|
|
22
|
+
| ID | Description | Priority |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| **BUG-02** | `eth_search_persons` returns HTTP 404 – correct Persons API endpoint URL needs verification at [developer.library.ethz.ch](https://developer.library.ethz.ch) | High |
|
|
25
|
+
|
|
26
|
+
If you have resolved BUG-02 or have a verified working endpoint URL, please open a pull request or comment on the issue directly.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Development Setup
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Clone and install in editable mode
|
|
34
|
+
git clone https://github.com/malkreide/eth-library-mcp.git
|
|
35
|
+
cd eth-library-mcp
|
|
36
|
+
pip install -e ".[dev]"
|
|
37
|
+
|
|
38
|
+
# Or with uv
|
|
39
|
+
uv pip install -e ".[dev]"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Running Tests
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Unit tests (no API key required)
|
|
46
|
+
PYTHONPATH=. pytest tests/ -m "not live"
|
|
47
|
+
|
|
48
|
+
# Integration tests (requires a valid API key)
|
|
49
|
+
ETH_LIBRARY_API_KEY=your_key pytest tests/ -m "live"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Tests marked `@pytest.mark.live` call the real ETH Library API and require a valid key from [developer.library.ethz.ch](https://developer.library.ethz.ch).
|
|
53
|
+
|
|
54
|
+
### Code Style
|
|
55
|
+
|
|
56
|
+
This project uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ruff check .
|
|
60
|
+
ruff format .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Pull Request Guidelines
|
|
66
|
+
|
|
67
|
+
1. **Fork** the repository and create a feature branch from `main`:
|
|
68
|
+
```bash
|
|
69
|
+
git checkout -b fix/bug-02-persons-api
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
2. **Write tests** for any new tool or bug fix. Live tests go in `tests/` with the `@pytest.mark.live` marker.
|
|
73
|
+
|
|
74
|
+
3. **Update documentation** – if you add or change a tool, update both `README.md` (English) and `README.de.md` (German). Keep the language toggle links at the top of each file.
|
|
75
|
+
|
|
76
|
+
4. **Update `CHANGELOG.md`** – add an entry under `[Unreleased]` using [Conventional Commits](https://www.conventionalcommits.org/) style:
|
|
77
|
+
- `fix:` – bug fix
|
|
78
|
+
- `feat:` – new feature or tool
|
|
79
|
+
- `docs:` – documentation only
|
|
80
|
+
- `refactor:` – code change with no functional impact
|
|
81
|
+
|
|
82
|
+
5. **Open a Pull Request** against `main` with a clear description of what changed and why.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Commit Message Convention
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
<type>: <short description>
|
|
90
|
+
|
|
91
|
+
# Examples
|
|
92
|
+
fix: resolve BUG-02 Persons API 404 with updated endpoint
|
|
93
|
+
feat: add eth_search_collections tool for collection-level browsing
|
|
94
|
+
docs: add query syntax examples to README
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Adding a New Tool
|
|
100
|
+
|
|
101
|
+
New tools go in `eth_library_mcp/server.py`. Follow the existing pattern:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
@mcp.tool()
|
|
105
|
+
async def eth_your_new_tool(param: str) -> str:
|
|
106
|
+
"""
|
|
107
|
+
One-line description for the AI model.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
param: What this parameter does.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
JSON string with results.
|
|
114
|
+
"""
|
|
115
|
+
...
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
After adding a tool:
|
|
119
|
+
- Add it to the **Available Tools** table in `README.md` and `README.de.md`
|
|
120
|
+
- Add at least one unit test in `tests/`
|
|
121
|
+
- Add an example query to the **Example Use Cases** table in the README files
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Data & Licensing Notes
|
|
126
|
+
|
|
127
|
+
- **Server code:** MIT License
|
|
128
|
+
- **Bibliographic metadata** returned by the ETH Library API: **Public Domain** – no restrictions on reuse
|
|
129
|
+
- Do not embed or cache API responses in the repository
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Questions
|
|
134
|
+
|
|
135
|
+
Open a [GitHub Discussion](https://github.com/malkreide/eth-library-mcp/discussions) or contact the maintainer via GitHub.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Schulamt der Stadt Zürich
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eth-library-mcp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: MCP Server für die ETH-Bibliothek Zürich – Zugriff auf 30+ Millionen Ressourcen via Discovery, Persons und Research Collection API
|
|
5
|
+
Author: Schulamt der Stadt Zürich
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: discovery,eth,library,mcp,open-data,research
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Requires-Dist: httpx>=0.27.0
|
|
11
|
+
Requires-Dist: mcp[cli]>=1.0.0
|
|
12
|
+
Requires-Dist: pydantic>=2.0.0
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
> 🇨🇭 **Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)**
|
|
20
|
+
|
|
21
|
+
# 🏛️ eth-library-mcp
|
|
22
|
+
|
|
23
|
+

|
|
24
|
+
[](https://opensource.org/licenses/MIT)
|
|
25
|
+
[](https://www.python.org/downloads/)
|
|
26
|
+
[](https://modelcontextprotocol.io/)
|
|
27
|
+
[](https://developer.library.ethz.ch)
|
|
28
|
+
[](https://github.com/malkreide/eth-library-mcp/actions/workflows/ci.yml)
|
|
29
|
+
|
|
30
|
+
> MCP server giving AI models direct access to 30M+ resources at ETH Library Zurich – books, maps, images, archival material, and linked-data person records.
|
|
31
|
+
|
|
32
|
+
[🇩🇪 Deutsche Version](README.de.md)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Overview
|
|
37
|
+
|
|
38
|
+
**eth-library-mcp** connects AI assistants like Claude to the largest natural-science library in Switzerland. It exposes full-text search, archive-level queries, resource-type filtering, and person lookups via the ETH Library's Discovery and Persons APIs – all through a single, standardised MCP interface.
|
|
39
|
+
|
|
40
|
+
**7 Tools · 3 APIs · 2 Resources · 2 Prompts**
|
|
41
|
+
|
|
42
|
+
> ⚠️ **Known issue (BUG-02):** The tool `eth_search_persons` is currently non-functional because the Persons API endpoint returns HTTP 404. The correct URL needs to be verified at [developer.library.ethz.ch](https://developer.library.ethz.ch). All other 6 tools work correctly.
|
|
43
|
+
|
|
44
|
+
**Anchor demo query:** *"Find historical documents about Zurich school history in the ETH Library archives."*
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- 🔍 **Full-text search** over 30M+ resources with fields, operators, and facets
|
|
51
|
+
- 📖 **Resource details** – full metadata via MMS-ID
|
|
52
|
+
- 🗂️ **Archive search** – ETH University Archives, Max Frisch, Thomas Mann, Graphische Sammlung, Bildarchiv
|
|
53
|
+
- 🏷️ **Resource type filter** – books, maps, images, archival material and more
|
|
54
|
+
- 🎓 **Education search** – curated workflow optimised for pedagogy and school history
|
|
55
|
+
- 👤 **Person search** with linked-data enrichment (Wikidata, GND, Metagrid) *(BUG-02: currently unavailable)*
|
|
56
|
+
- 📋 **Server overview** – all resource types and archives at a glance
|
|
57
|
+
- 🗣️ **Built-in prompts** – structured research and education-research workflows
|
|
58
|
+
- ☁️ **Dual transport** – stdio for Claude Desktop, Streamable HTTP/SSE for cloud deployment
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Prerequisites
|
|
63
|
+
|
|
64
|
+
- Python 3.11+
|
|
65
|
+
- A free API key from [developer.library.ethz.ch](https://developer.library.ethz.ch)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Clone the repository
|
|
73
|
+
git clone https://github.com/malkreide/eth-library-mcp.git
|
|
74
|
+
cd eth-library-mcp
|
|
75
|
+
|
|
76
|
+
# Install
|
|
77
|
+
pip install -e .
|
|
78
|
+
|
|
79
|
+
# Or with uv (recommended)
|
|
80
|
+
uv pip install -e .
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Quickstart
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Set the API key
|
|
89
|
+
export ETH_LIBRARY_API_KEY=your_key_here # macOS / Linux
|
|
90
|
+
# $env:ETH_LIBRARY_API_KEY = "your_key_here" # Windows (PowerShell)
|
|
91
|
+
|
|
92
|
+
# Start the server (stdio mode for Claude Desktop)
|
|
93
|
+
python -m eth_library_mcp.server
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> Without an API key the server returns a helpful error message with the registration link – no crashes.
|
|
97
|
+
|
|
98
|
+
Try it immediately in Claude Desktop:
|
|
99
|
+
|
|
100
|
+
> *"Find books about Swiss education history in the ETH Library."*
|
|
101
|
+
> *"Search the Max Frisch archive for manuscripts about Zurich."*
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Configuration
|
|
106
|
+
|
|
107
|
+
### Environment Variables
|
|
108
|
+
|
|
109
|
+
| Variable | Description | Required |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `ETH_LIBRARY_API_KEY` | API key for Discovery & Persons API | ✅ |
|
|
112
|
+
|
|
113
|
+
### Claude Desktop Configuration
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"eth-library": {
|
|
119
|
+
"command": "python",
|
|
120
|
+
"args": ["-m", "eth_library_mcp.server"],
|
|
121
|
+
"env": {
|
|
122
|
+
"ETH_LIBRARY_API_KEY": "your_key_here"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Config file locations:**
|
|
130
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
131
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
132
|
+
|
|
133
|
+
### Cloud Deployment (SSE for browser access)
|
|
134
|
+
|
|
135
|
+
For use via **claude.ai in the browser** (e.g. on managed workstations without local software):
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
MCP_TRANSPORT=sse PORT=8000 python -m eth_library_mcp.server
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
> 💡 *"stdio for the developer laptop, SSE for the browser."*
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Available Tools
|
|
146
|
+
|
|
147
|
+
### Discovery API (api.library.ethz.ch)
|
|
148
|
+
|
|
149
|
+
| Tool | Description |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `eth_search_resources` | Full-text search over 30M+ resources with fields, operators, facets |
|
|
152
|
+
| `eth_get_resource` | Full metadata for a specific resource via MMS-ID |
|
|
153
|
+
| `eth_search_archive` | Search within a specific archive (University Archives, Max Frisch, Thomas Mann, etc.) |
|
|
154
|
+
| `eth_search_by_type` | Filter by resource type (books, maps, images, archival material, etc.) |
|
|
155
|
+
| `eth_search_education` | Curated search for education topics (pedagogy, school history, etc.) |
|
|
156
|
+
|
|
157
|
+
### Persons API
|
|
158
|
+
|
|
159
|
+
| Tool | Description |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `eth_search_persons` | Person search with linked-data enrichment (Wikidata, GND, Metagrid) — ⚠️ BUG-02 |
|
|
162
|
+
|
|
163
|
+
### Utilities
|
|
164
|
+
|
|
165
|
+
| Tool | Description |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `eth_library_info` | Server overview: all types and archives at a glance |
|
|
168
|
+
|
|
169
|
+
### Resources & Prompts
|
|
170
|
+
|
|
171
|
+
| Item | Type | Description |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| `eth://resource-types` | Resource | All available resource types |
|
|
174
|
+
| `eth://archives` | Resource | All available archives and collections |
|
|
175
|
+
| `research-workflow` | Prompt | Structured research workflow |
|
|
176
|
+
| `education-research` | Prompt | Education topics workflow (Schulamt-optimised) |
|
|
177
|
+
|
|
178
|
+
### Query Syntax
|
|
179
|
+
|
|
180
|
+
The Discovery API uses structured queries:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
field,operator,value
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
| Field | Meaning |
|
|
187
|
+
|---|---|
|
|
188
|
+
| `any` | All fields (recommended for starters) |
|
|
189
|
+
| `title` | Title only |
|
|
190
|
+
| `creator` | Author / creator |
|
|
191
|
+
| `sub` | Subject headings / topics |
|
|
192
|
+
|
|
193
|
+
| Operator | Meaning |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `contains` | Term is present |
|
|
196
|
+
| `exact` | Exact match |
|
|
197
|
+
| `begins_with` | Starts with |
|
|
198
|
+
|
|
199
|
+
**Examples:**
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
any,contains,Volksschule Zürich
|
|
203
|
+
title,contains,Pädagogik
|
|
204
|
+
creator,exact,Einstein Albert
|
|
205
|
+
sub,contains,Bildungsforschung
|
|
206
|
+
title,contains,Schule;sub,contains,Geschichte
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Available Archives
|
|
210
|
+
|
|
211
|
+
| Identifier | Description |
|
|
212
|
+
|---|---|
|
|
213
|
+
| `ETH_Hochschularchiv` | Institutional memory of ETH Zurich |
|
|
214
|
+
| `ETH_MaxFrischArchiv` | Estate of Swiss author Max Frisch |
|
|
215
|
+
| `ETH_ThomasMannArchiv` | Letters and documents of Thomas Mann |
|
|
216
|
+
| `ETH_GraphischeSammlung` | Prints, drawings, graphic works |
|
|
217
|
+
| `ETH_Bildarchiv` | Science/technology history, Swissair (E-Pics) |
|
|
218
|
+
|
|
219
|
+
### Example Use Cases
|
|
220
|
+
|
|
221
|
+
| Query | Tool |
|
|
222
|
+
|---|---|
|
|
223
|
+
| *"Find books about Zurich school history"* | `eth_search_education` |
|
|
224
|
+
| *"What's in the Max Frisch archive?"* | `eth_search_archive` |
|
|
225
|
+
| *"Find historical maps of Switzerland"* | `eth_search_by_type` |
|
|
226
|
+
| *"Get full metadata for resource ID 991170525863705501"* | `eth_get_resource` |
|
|
227
|
+
| *"Which archives does the ETH Library hold?"* | `eth_library_info` |
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Project Structure
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
eth-library-mcp/
|
|
235
|
+
├── eth_library_mcp/ # Main package
|
|
236
|
+
│ └── server.py # FastMCP server, tool definitions
|
|
237
|
+
├── CHANGELOG.md
|
|
238
|
+
├── CONTRIBUTING.md
|
|
239
|
+
├── LICENSE
|
|
240
|
+
├── README.md # This file (English)
|
|
241
|
+
├── README.de.md # German version
|
|
242
|
+
├── TEST_PLAN.md
|
|
243
|
+
├── claude_desktop_config.json # Example Claude Desktop configuration
|
|
244
|
+
└── pyproject.toml # Build configuration
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Known Limitations
|
|
250
|
+
|
|
251
|
+
- **BUG-02 (Persons API):** `eth_search_persons` returns HTTP 404 – correct endpoint URL to be verified at [developer.library.ethz.ch](https://developer.library.ethz.ch)
|
|
252
|
+
- **Bibliographic metadata:** Licensed as Public Domain – free for all uses, no restrictions
|
|
253
|
+
- **Rate limits:** Governed by the ETH Library API terms; no built-in throttling in this server version
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Testing
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# Unit tests (no API key required)
|
|
261
|
+
PYTHONPATH=. pytest tests/ -m "not live"
|
|
262
|
+
|
|
263
|
+
# Integration tests (API key required)
|
|
264
|
+
ETH_LIBRARY_API_KEY=xxx pytest tests/ -m "live"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Contributing
|
|
270
|
+
|
|
271
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Changelog
|
|
276
|
+
|
|
277
|
+
See [CHANGELOG.md](CHANGELOG.md)
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## License
|
|
282
|
+
|
|
283
|
+
- **Server code:** MIT License — see [LICENSE](LICENSE)
|
|
284
|
+
- **Bibliographic metadata:** Public Domain (no restrictions)
|
|
285
|
+
- **API documentation:** [developer.library.ethz.ch](https://developer.library.ethz.ch)
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Author
|
|
290
|
+
|
|
291
|
+
Hayal Oezkan · [github.com/malkreide](https://github.com/malkreide)
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Credits & Related Projects
|
|
296
|
+
|
|
297
|
+
- **Data:** [ETH Library Zurich](https://library.ethz.ch) – Discovery & Persons APIs
|
|
298
|
+
- **Protocol:** [Model Context Protocol](https://modelcontextprotocol.io/) – Anthropic / Linux Foundation
|
|
299
|
+
- **Related:** [swiss-transport-mcp](https://github.com/malkreide/swiss-transport-mcp) – MCP server for Swiss public transport
|
|
300
|
+
- **Related:** [zurich-opendata-mcp](https://github.com/malkreide/zurich-opendata-mcp) – MCP server for Zurich city open data
|
|
301
|
+
- **Portfolio:** [Swiss Public Data MCP Portfolio](https://github.com/malkreide)
|