Skip to main content

MCP server for the I14Y interoperability platform — Switzerland's national metadata catalogue

Project description

Part of the Swiss Public Data MCP Portfolio — a collection of open-source MCP servers connecting AI agents to Swiss public and open data. This is a private project. It is not affiliated with, endorsed by, or operated on behalf of any employer or public authority.

i14y-mcp

License: MIT Python 3.10+ MCP Data: I14Y

MCP server for the I14Y interoperability platform — Switzerland's national metadata catalogue.

🇩🇪 Deutsche Version


Why this server exists

The other servers in this portfolio answer «what does the data say?». This one answers the question that comes first: «who publishes data on this topic, through which interface, under which licence?»

I14Y is the national data catalogue maintained by the Federal Statistical Office. It describes datasets, registered APIs, public services and harmonised concepts from the Confederation, cantons and communes, using the DCAT-AP-CH profile (eCH-0200).

Mnemonic: «Catalogue before shelf.» Without a catalogue, an agent has to already know a data source exists. With one, it can find it.


🎯 Anchor Demo Query

«Which authority publishes data on special needs education, through which interface is it available, and under which licence?»

search_catalog(query="Sonderpädagogik")
  → «Statistik der Sonderpädagogik» — Federal Statistical Office (BFS), theme: Bildung

get_dataset(dataset_id=...)
  → 2 distributions, licence: «Opendata BY ASK — attribution required,
    commercial use only with permission from the data supplier»
  → contact: auskunftsdienst@bfs.admin.ch

Two tool calls turn a vague topic into a named authority, a download URL and a licence you can act on — get_dataset aggregates the distributions, licences and contact point into one record.


Architecture

                 ┌──────────────────────────────┐
                 │      MCP Host (Claude)       │
                 └───────────────┬──────────────┘
                                 │ stdio | streamable-http
                 ┌───────────────▼──────────────┐
                 │          i14y-mcp            │
                 │  ┌────────────────────────┐  │
                 │  │ server.py  (13 tools)  │  │
                 │  ├────────────────────────┤  │
                 │  │ mappers.py             │  │  DCAT → flat, one language
                 │  ├────────────────────────┤  │
                 │  │ models.py  (Pydantic)  │  │  source + provenance envelope
                 │  ├────────────────────────┤  │
                 │  │ client.py              │  │  retry 2s/4s/8s, no-retry 4xx
                 │  └────────────────────────┘  │
                 └───────────────┬──────────────┘
                                 │ HTTPS, no auth
                 ┌───────────────▼──────────────┐
                 │  api.i14y.admin.ch/api       │
                 │  datasets · dataservices ·   │
                 │  concepts · publicservices · │
                 │  catalogs · agents · search  │
                 └──────────────────────────────┘

Architecture decision

This server uses Architecture A (live API only).

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

  • All read endpoints respond without authentication and paginate correctly.
  • No bulk download of catalogue metadata is offered, and none is needed.
  • Error responses follow RFC 7807, so failure modes are distinguishable.

Consequences:

  • Every HTTP call retries transient failures with 2 s / 4 s / 8 s backoff.
  • search_catalog caps results client-side because the upstream ignores paging.
  • api_status always returns an evaluable state instead of empty records.

Full probe report: docs/probe-i14y.md.

Project phase

This server is in Phase 1 (read-only) of the portfolio's «Read-only First» phase architecture: all tools are read-only, there is no authentication and no personal data. See docs/roadmap.md for the phase model and the prerequisites for any future write capability.


Tools

Tool Purpose
search_catalog Free-text search across the catalogue. Entry point.
list_datasets Paginated dataset register (complete, unlike search).
get_dataset Full metadata record for one dataset.
get_dataset_distributions Download URLs, formats and licences.
list_data_services Register of official Swiss APIs with endpoint URLs.
get_data_service Full record for one registered interface.
list_public_services Administrative services for citizens.
list_concepts Harmonised concepts and code lists.
get_concept One concept definition.
search_codelist_entries Individual codes of a code list.
list_publishers Publishing bodies, with Swiss UID.
list_catalogs Contributing catalogues.
api_status Reachability check with graceful degradation.

All tools are annotated readOnlyHint: true. Write operations exist in the upstream API but are deliberately not exposed.

MCP primitives

This server exposes Tools only — no Resources, no Prompts. That is a deliberate choice, not an omission: I14Y is queried by free-text search and by opaque UUIDs, so there is no small, stable set of addressable URIs that would map cleanly onto MCP Resources, and the server ships no opinionated prompt templates. Every tool is read-only and idempotent; if a future stable entry point emerges (e.g. a fixed theme list) it is a candidate for a Resource.

MCP protocol version

Built against the MCP Python SDK (mcp >= 1.28.1), which negotiates the protocol version with the client at initialize time. The tested SDK floor is pinned in pyproject.toml; Dependabot opens monthly SDK-update PRs, and any change that bumps the negotiated spec version is called out in CHANGELOG.md.


Installation

uvx i14y-mcp

Or from source:

git clone https://github.com/malkreide/i14y-mcp
cd i14y-mcp
pip install -e ".[dev]"

Claude Desktop

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

Remote deployment (Render, Railway)

I14Y_MCP_TRANSPORT=sse HOST=0.0.0.0 PORT=8000 i14y-mcp

I14Y_MCP_TRANSPORT accepts stdio (default), sse or streamable-http. The HTTP transports bind to HOST, which defaults to 127.0.0.1 (loopback); set HOST=0.0.0.0 to expose the port on a PaaS (the Docker image already does). CORS exposes the Mcp-Session-Id header so browser MCP clients keep their session.

Docker

docker compose up --build      # SSE transport on http://localhost:8000

The image is a hardened multi-stage build: it runs as a non-root user, ships no build tools, and needs no secrets (the API is unauthenticated). See Dockerfile and compose.yaml.


Join keys

I14Y is a connector layer. Two identifiers make it composable with the rest of the portfolio:

Key Field Joins to
Swiss UID Publisher.uid register-mcp (Zefix)
Endpoint URL DataServiceSummary.endpoint_urls any portfolio server wrapping that API

Known limitations

Verified live on 2026-07-21.

  1. The search index covers roughly half the register. search_catalog returns at most 1013 records; list_datasets reaches about 2003. Use list_datasets when completeness matters.
  2. Search returns Datasets only. Filtering by types=["Concept"] or types=["DataService"] yields zero results even though those entities exist. Use list_concepts and list_data_services instead.
  3. The upstream ignores paging on search. The full result set is always returned; this server caps it at 200 records and sets truncated: true.
  4. Licences vary per distribution, not per dataset. Most carry «Opendata BY ASK», which requires attribution and restricts commercial use. Always read the licence field before reuse.
  5. Some metadata fields are simply empty. Frequency, temporal coverage and distribution format are optional and frequently unset by publishers. This is a data-quality property of the catalogue, not a bug in this server.
  6. Not every entry with an endpoint has a URL. Entries labelled only «OpenAPI Spezifikation» without a URI are surfaced as (no URI) <label> rather than dropped.

Testing

PYTHONPATH=src pytest tests/ -m "not live"   # offline, used in CI
PYTHONPATH=src pytest tests/ -m "live"       # hits the real API
PYTHONPATH=src pytest tests/                 # everything
python -m ruff check src tests

The live tests are not decoration: fundstück 4 in the probe report — keywords nesting their language object under label — was caught by a live test after the unit tests were already green.


Contributing & security

  • CONTRIBUTING.md — ground rules (read-only, one egress host, no secrets) and the local dev loop.
  • SECURITY.md — security posture and how to report a vulnerability.
  • PUBLISHING.md — the PyPI / MCP Registry release process.

Credits & related projects

Licence: MIT. The catalogue data remains subject to the terms declared by each publisher.

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

i14y_mcp-0.2.0.tar.gz (131.9 kB view details)

Uploaded Source

Built Distribution

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

i14y_mcp-0.2.0-py3-none-any.whl (23.9 kB view details)

Uploaded Python 3

File details

Details for the file i14y_mcp-0.2.0.tar.gz.

File metadata

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

File hashes

Hashes for i14y_mcp-0.2.0.tar.gz
Algorithm Hash digest
SHA256 972fab1c62bcfc19745b1fa854d21469f39f7ba7715d2a8537dbb58e41509bf6
MD5 c88a3ef9b691bc6a1684aab29dcbadde
BLAKE2b-256 b392adc0621a016e3156ff0cdd56b48986b703a0fcd9bfb2146aad0d102ca7ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for i14y_mcp-0.2.0.tar.gz:

Publisher: publish.yml on malkreide/i14y-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 i14y_mcp-0.2.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for i14y_mcp-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8b8876413ede221ead6664b7ff74bb9c6d0a303b5386be08ebfaa97a2007e363
MD5 899e3eb4fe232b6648c8582e32002036
BLAKE2b-256 f9f20848ea571c1cf4f1f7cb16f26feb470703808d96b47bb2727253badf5627

See more details on using hashes here.

Provenance

The following attestation bundles were made for i14y_mcp-0.2.0-py3-none-any.whl:

Publisher: publish.yml on malkreide/i14y-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