Skip to main content

MCP server for TERMDAT โ€” the terminology database of the Swiss Federal Administration

Project description

๐Ÿ‡จ๐Ÿ‡ญ Part of the Swiss Public Data MCP Portfolio โ€” open-source MCP servers connecting AI agents to Swiss public and open data. This is a private project. It is independent of any employer or institutional affiliation.

๐Ÿท๏ธ termdat-mcp

Version CI License: MIT Python 3.10+ MCP Auth: none Portfolio

Official, validated Swiss administrative designations across DE / FR / IT / EN โ€” with source references and validation status.

๐Ÿ‡ฉ๐Ÿ‡ช Deutsche Version

Overview

MCP server for TERMDAT, the terminology database of the Swiss Federal Administration, maintained by the Federal Chancellery. It gives an AI agent the officially validated designations of Swiss authorities, departments and legal acts across DE / FR / IT / EN โ€” with source references and validation status.

Discovered through i14y-mcp, which catalogues TERMDAT as data service ff0c37eb-2f7c-4ff6-996e-d22b77bf52fc.

What this is โ€” and what it is not. TERMDAT is not a subject dictionary. It is a certified name-plate archive: it will not tell you what ยซSonderpรคdagogikยป means, but it will tell you the official name of the authority responsible for it, and what that authority is called in French.

Measured coverage (live, 2026-07-19, German search over the Terminus field):

Search term Hits
Departement 20
Bildung 13
Verordnung 8
Schule 5
Behรถrde 4
Sonderpรคdagogik 3
Volksschule ยท Lehrperson ยท Schulleitung ยท Unterricht ยท Kindergarten 0

The thirteen ยซBildungยป hits are organisational names โ€” Bildungsdirektion, Erziehungsdepartement, Departement fรผr Volkswirtschaft und Bildung โ€” not pedagogical concepts. Plan accordingly: this server is strong for authority naming, official titles and abbreviations, and largely silent on domain vocabulary.

Features

  • Seven read-only tools over the official TERMDAT public v2 API.
  • Official designations across DE / FR / IT / EN, with source reference and validation status on every response.
  • Communication QA: check up to 25 terms in one call against validated designations.
  • Vocabulary cache (24 h TTL) for the 140 collections and 23 classifications, with stale-serve fallback.
  • Retry with exponential backoff (2/4/8 s); explicit MaxEntryCount to avoid silent truncation.
  • Dual transport: stdio (local) and SSE (cloud).
  • No authentication required โ€” public, unauthenticated API (No-Auth-First).

๐ŸŽฏ Anchor demo query

ยซWhat are the official French and Italian names of the education directorates of the German-speaking cantons?ยป

Resolved with list_classifications โ†’ search_terms โ†’ translate_term.

Prerequisites

  • Python 3.10+
  • uv / uvx (recommended) or pip
  • Network access to api.termdat.bk.admin.ch โ€” no API key needed

Installation

uvx termdat-mcp

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "termdat": {
      "command": "uvx",
      "args": ["termdat-mcp"]
    }
  }
}

Quickstart

# Run locally over stdio (default transport)
uvx termdat-mcp

# From a checkout, without installing
PYTHONPATH=src python -m termdat_mcp

Configuration

All configuration is via environment variables. Defaults are safe for local use.

Variable Default Purpose
TERMDAT_MCP_TRANSPORT stdio Transport: stdio (local) or sse / streamable-http / http (cloud)
HOST 0.0.0.0 Bind host (SSE transport only)
PORT 8000 Bind port (SSE transport only)

Cloud (Render / Railway):

TERMDAT_MCP_TRANSPORT=sse PORT=8000 termdat-mcp   # exposes /sse

Available Tools

Tool Purpose
search_terms Search TERMDAT with field flags, collection and classification filters
translate_term Official equivalent of an administrative term in another national language
check_terms Communication QA: check up to 25 terms against validated designations
get_entries Fetch known entries by numeric ID
list_collections The ~140 terminology collections (filter values)
list_classifications The 23 subject classifications, e.g. BILD = education
api_status Availability; never returns silently empty

All tools are annotated readOnlyHint: true, destructiveHint: false.

Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   stdio / SSE    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  MCP host       โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ โ”‚  termdat-mcp             โ”‚
โ”‚  (Claude, IDE)  โ”‚ โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ”‚  vocabulary cache (24 h) โ”‚
                                     โ”‚  140 collections         โ”‚
                                     โ”‚   23 classifications     โ”‚
                                     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                  โ”‚ httpx + retry (2/4/8 s)
                                                  โ–ผ
                              https://api.termdat.bk.admin.ch/v2
                              โ”œโ”€โ”€ /Search          (SearchTerm + InLanguageCode)
                              โ”œโ”€โ”€ /Entry           (EntryIds)
                              โ”œโ”€โ”€ /Collection      (140 values)
                              โ””โ”€โ”€ /Classification  ( 23 values, incl. BILD)

Architecture decision

This server uses Architecture A (live API only), with caching limited to the two controlled vocabularies.

Rationale (verified live on 2026-07-19):

  • The API publishes a complete OpenAPI 3.0.4 specification at /swagger/v2/swagger.json and declares no security schemes โ€” unauthenticated access, No-Auth-First satisfied.
  • Server-side search works properly, including 11 field flags and filters by collection and classification. There is no reason to mirror the database locally, and no bulk dump is offered.
  • /Collection (140 entries) and /Classification (23 entries) change rarely and are needed to make filter arguments legible to an agent, so they are cached with a 24-hour TTL and a stale-serve fallback.

Consequences:

  • Every search is a live call; provenance is live_api except for vocabulary lookups.
  • Validation errors arrive as clean RFC 9110 payloads and are surfaced rather than swallowed.

Project Structure

termdat-mcp/
โ”œโ”€โ”€ src/termdat_mcp/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ __main__.py       # entry point; dual transport (stdio / SSE)
โ”‚   โ”œโ”€โ”€ client.py         # httpx client, retry, vocabulary cache
โ”‚   โ”œโ”€โ”€ models.py         # Pydantic models
โ”‚   โ””โ”€โ”€ server.py         # MCP tool definitions
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ test_client.py    # offline, respx-mocked
โ”‚   โ””โ”€โ”€ test_live.py       # hits the real TERMDAT API
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ README.de.md
โ”œโ”€โ”€ CHANGELOG.md
โ”œโ”€โ”€ LICENSE
โ””โ”€โ”€ pyproject.toml

Safety & Limits

  • Read-only. Every tool is annotated readOnlyHint: true, destructiveHint: false; the server never writes to TERMDAT.
  • No credentials handled. The API is unauthenticated; the server stores and forwards no secrets.
  • No silent empties. api_status and error paths surface failures instead of returning an empty result that looks complete.
  • Truncation is explicit. MaxEntryCount is always sent and truncated is reported (see Known Limitations).
  • Licence caution. TERMDAT content carries no licence statement; every response repeats this in source. Clarify terms with the Federal Chancellery before republishing downstream.

Known Limitations

  • Administrative scope only. See the coverage table above. check_terms returns not_found, never ยซincorrectยป, precisely because absence from TERMDAT is not evidence of error.
  • MaxEntryCount has a silent default of ~25. Omitting it looks like a complete result set. This server always sends the parameter explicitly and reports truncated.
  • Multilingual variants are opt-in. Without OutLanguageCode, entries return German designations only. translate_term sets it for you.
  • No licence statement. The I14Y catalogue record carries license: null. Clarify terms with the Federal Chancellery before republishing TERMDAT content downstream. Every response repeats this in source.
  • Entry-level language coverage varies. Not every entry exists in all four languages; translate_term omits entries without a target-language variant rather than inventing one.

Live probe findings (2026-07-19)

Endpoint HTTP Status Note
/swagger/v2/swagger.json 200 โœ… OpenAPI 3.0.4, 132 KB, securitySchemes: []
/v2/Search 200 โœ… requires SearchTerm, InLanguageCode, ReturnType
/v2/Entry 200 โœ… requires EntryIds, InLanguageCode
/v2/Collection 200 โœ… 140 values
/v2/Classification 200 โœ… 23 values, incl. BILD (education)
/v2/ (root) 404 โŒ no index; the I14Y record points here
InLanguageCode=deu / de-CH 400 โŒ only two-letter ISO codes, case-insensitive

Probe note: a correction worth recording. An earlier probe concluded that OutLanguageCode filters the result set, because adding it appeared to drop all hits. It does not. Two variables had been changed at once โ€” the parameter and the search term โ€” and the term itself (ยซVolksschuleยป) genuinely has zero hits. Verified afterwards across four broad terms: result counts are identical with and without OutLanguageCode; the parameter is purely additive. A regression test (test_out_language_is_additive_not_filtering) now guards this.

Rule of thumb: change one variable per probe call, or the API will confess to a crime it did not commit.

Project Phase

This server is in Phase 1 (read-only). All tools are annotated readOnlyHint: true / destructiveHint: false and only ever query the public TERMDAT v2 API โ€” there are no write, send, or filesystem capabilities.

Phase Scope Status
1 โ€” Read-only Search, translate and check administrative designations โœ… current
2 โ€” Write-capable (none planned) โ€”
3 โ€” Multi-agent (none planned) โ€”

A transition to a later phase would require a re-audit and human-in-the-loop controls before any write-capable tool is added.

MCP Protocol Version

The protocol version is negotiated at the initialize handshake by the mcp Python SDK (pinned to >=1.2.0 in pyproject.toml). The SDK is kept current via monthly Dependabot PRs (.github/dependabot.yml); protocol-relevant bumps are noted in CHANGELOG.md.

Testing

PYTHONPATH=src pytest tests/ -m "not live"   # offline, respx-mocked
PYTHONPATH=src pytest tests/ -m live         # hits the real API
PYTHONPATH=src ruff check src tests

Changelog

See CHANGELOG.md.

Security

See SECURITY.md for the security posture, hardening controls, and how to report a vulnerability.

Contributing

Issues and pull requests are welcome. Please keep tools read-only, run ruff check and the offline test suite before submitting, and add a CHANGELOG.md entry under [Unreleased] for user-facing changes.

Maintainers: see PUBLISHING.md for the step-by-step PyPI release process (Trusted Publishing via GitHub Release).

License

MIT for this server โ€” see LICENSE. TERMDAT content remains subject to the Federal Chancellery's terms.

Author

Hayal Oezkan ยท github.com/malkreide

Credits & Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

termdat_mcp-0.1.0.tar.gz (26.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

termdat_mcp-0.1.0-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

Details for the file termdat_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: termdat_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 26.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for termdat_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0d4bcc8f8101985153e3aad0bedf4e24239ab05e3e1237682007b8e819cbf90a
MD5 24c91534cede5a0380611ea267d31aad
BLAKE2b-256 aa31e9262e563beae102cf607371e6efeab4c2db9cc9009b89bc924de44c21c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for termdat_mcp-0.1.0.tar.gz:

Publisher: publish.yml on malkreide/termdat-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file termdat_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: termdat_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for termdat_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d612938ac4f91851c74e3b5ac0b52274ef864dee9f5ba85697e9c790611a5df7
MD5 9704a0b55d7e0a1e2836d4d2619304ed
BLAKE2b-256 c6b4c2292c6e1d75ebebc839e2c85f9ffca519a864babdae2618053a2c9fbb62

See more details on using hashes here.

Provenance

The following attestation bundles were made for termdat_mcp-0.1.0-py3-none-any.whl:

Publisher: publish.yml on malkreide/termdat-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page