Skip to main content
Glama
malkreide

i14y-mcp

by malkreide

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.


Related MCP server: swiss-food-safety-mcp

🎯 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.

Demo

Demo: Claude using search_catalog and get_dataset


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

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.

What the server carries on the modern revision

2026-07-28 moves discovery off the initialize handshake onto server/discover plus a per-request _meta envelope, and gives every cacheable result a freshness hint. What this server puts on those surfaces is measured in tests/test_spec_2026_07_28.py through the assembled stack — and, for stdio, through a real subprocess — rather than read back off the configuration:

Surface

What this server answers

serverInfo, stamped under every modern response

name, display title, description, website, and the installed distribution version — the same version the outbound User-Agent carries

server/discover → instructions

how to sequence the tools, plus the two properties of I14Y that no single tool description shows

ttlMs / cacheScope

300 s, public, on all five cacheable methods this server answers

tools[].title

a display name per tool, so a client shows «Search a concept's code list» rather than search_codelist_entries

The freshness hint is not cosmetic. With none set, the SDK answers ttlMs: 0, cacheScope: private — «already stale, never share» — for directories that are fixed at import and cannot change while the process runs.

Both transports serve the modern revision: HTTP through the streamable-HTTP session manager, and stdio — the default, and what uvx i14y-mcp starts — through the same dual-era loop. Neither is evidence for the other, so both are measured.

One thing this server advertises but does not use. On 2026-07-28 the listChanged flags and resources.subscribe derive solely from whether subscriptions/listen is served, and the SDK wires that handler unconditionally. server/discover therefore reports listChanged: true for a tool list that is fixed at import, and a subscribe capability over an empty resource list; no change notification is ever sent. It is not switchable through the public API — only a wholesale replacement of the server/discover handler could do it, which would be a second truth about our own capabilities — so it is pinned by a test instead of papered over.

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.


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=streamable-http HOST=0.0.0.0 PORT=8000 i14y-mcp

I14Y_MCP_TRANSPORT accepts stdio (the default of the entry point itself), streamable-http (http is a synonym) or sse. 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 container image already does both).

Connector URL: https://<host>/mcp

A Claude.ai custom connector speaks Streamable HTTP, and that transport serves exactly one path: /mcp. sse is the older transport and serves /sse and /messages instead — measured through the assembled app, POST /mcp answers 404 there and 200 under Streamable HTTP. The container image therefore defaults to streamable-http; a connector pointed at an SSE deployment gets a 404 and never completes a handshake.

I14Y_MCP_ALLOWED_HOSTS — required for a public deployment

A comma-separated list of the hostnames the server is reached under — hostnames only, no scheme and no port:

I14Y_MCP_ALLOWED_HOSTS=i14y-mcp.up.railway.app,mcp.example.ch

The value is compared literally against the incoming Host header, so https://i14y-mcp.up.railway.app or a trailing :443 matches nothing and every request fails with HTTP 421 Invalid Host header. Behind TLS the browser sends the bare hostname; a non-standard port needs the SDK's only wildcard form, host:*. Loopback stays reachable either way, so container health checks are unaffected.

Leaving it unset on a non-loopback bind does not fall back to something safe. The server cannot guess the name it will be addressed by, and a guessed list would reject every real request, so it switches the Host check off entirely and says so in the log:

dns_rebinding_protection_off

railway.json

railway.json pins the one build setting the deployment cannot get wrong on its own:

{ "build": { "builder": "DOCKERFILE", "dockerfilePath": "Dockerfile" } }

With any other builder Railway never looks at the Dockerfile. It derives a start command itself, I14Y_MCP_TRANSPORT is then set nowhere, and main() falls into the stdio branch — the container runs, never opens a port, and the only trace is a failing health check. tests/test_entrypoint.py fails the day that setting changes.

Two things the file deliberately does not carry:

  • No environment variables. Railway's schema has no key for them at any level, so I14Y_MCP_ALLOWED_HOSTS and I14Y_MCP_TRANSPORT belong in the service variables. The trap is that the schema validates values but waves invented keys through: a "variables": { … } block passes validation, your editor stays quiet, and Railway ignores it. A test rejects such a key.

  • No healthcheckPath. Measured through the assembled app, no path answers a GET with 2xx: / and /health are 404, /mcp is 400 without a session and 421 under a foreign Host. A health check pointed at any of them would mark the deployment unhealthy and roll it back. The Dockerfile's TCP check does the right thing instead. Should the server ever grow a real health route, the key may be set — a test then requires that the path actually answers.

CORS exposes the Mcp-Session-Id header so browser MCP clients keep their session. Which browser origins may call the server comes from I14Y_MCP_CORS_ORIGINS, a comma-separated list — unset means no browser client is permitted at all, which is the default. * is still accepted and logs a warning. stdio and other non-browser clients are unaffected either way.

Docker

docker compose up --build      # Streamable HTTP on http://localhost:8000/mcp

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

See CONTRIBUTING.md for the ground rules (read-only, one egress host, no secrets) and the local dev loop. Maintainers: PUBLISHING.md covers the PyPI / MCP Registry release process.


Security

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


License

MIT License — see LICENSE. The catalogue data remains subject to the terms declared by each publisher.


Author

Hayal Oezkan · github.com/malkreide


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


MCP Registry

Ownership marker used by the MCP Registry to link this PyPI package to the GitHub namespace:

mcp-name: io.github.malkreide/i14y-mcp

Available Tools

13 tools
api_statusCheck the I14Y API statusA
Read-onlyIdempotent

Check whether the I14Y API is reachable and which endpoints respond.

Always returns an evaluable status rather than an empty result, so an agent can distinguish «no data matched» from «the source is down».

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteYes
sourceNoAttribution string.
base_urlYes
reachableYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.
checked_endpointsYes
last_successful_callNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false, covering safety. The description adds a valuable behavioral guarantee beyond the annotations: it 'always returns an evaluable status rather than an empty result,' which shapes agent interpretation of results. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no wasted words. The main purpose is front-loaded, and the second sentence adds a key behavioral distinction that helps the agent reason about results. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter status tool with rich annotations and an output schema, the description is complete. It states what is checked, guarantees a non-empty evaluable result, and explains why that matters. Nothing necessary for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, and schema coverage is 100%, so there is nothing missing. The baseline of 4 applies because no parameter semantics are needed; the description appropriately says nothing about parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'Check whether the I14Y API is reachable and which endpoints respond.' This distinguishes it as a status/health tool from the data-retrieval siblings, though it does not explicitly name a sibling or exclusion. It is clear but lacks explicit sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear use context: it is meant to check API reachability and to distinguish 'no data matched' from 'the source is down.' It implies when to use it (after empty results or when API health is in question), but it does not explicitly state when not to use it or name alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_conceptGet one conceptA
Read-onlyIdempotent

Retrieve one concept definition, including its value type and version.

Args: concept_id: UUID from list_concepts. language: Language for titles and descriptions.

ParametersJSON Schema
NameRequiredDescriptionDefault
languageNode
concept_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sourceNoAttribution string.
conceptYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds 'including its value type and version', giving some content context, but no additional behavioral details such as error conditions, localization defaults, or response structure beyond what the output schema would provide. This is acceptable but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core action, followed by concise parameter explanations. Every sentence contributes useful information, with no redundancy or filler. The Args block is clean and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only lookup with two parametershol, strong annotations, and an output schema, the description is complete. It tells the agent what the tool returns, how to source concept_id, and what language affects. Nothing essential is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the parameter meaning burden. It does this well: concept_id is described as a UUID from list_concepts, and language is described as affecting titles and descriptions. These add practical meaning beyond the bare schema names, though the description could have noted the default language.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Retrieve one concept definition', which clearly distinguishes it from sibling tools like list_concepts and get_dataset. The title 'Get one concept' reinforces the singular focus. An agent can immediately tell this tool fetches a single concept by ID rather than listing or searching.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context that concept_id is a 'UUID from list_concepts', which tells the agent where to obtain the ID before calling this tool. It also explains that language is used for titles and descriptions. It does not explicitly discuss when not to use this tool versus search_catalog or list_concepts, so it misses a full explicit exclusion statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_data_serviceGet one data serviceA
Read-onlyIdempotent

Retrieve the full record for one registered API, including endpoints.

Args: data_service_id: UUID from list_data_services. language: Language for titles and descriptions.

ParametersJSON Schema
NameRequiredDescriptionDefault
languageNode
data_service_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sourceNoAttribution string.
provenanceNoWhere this payload came from.
data_serviceYes
retrieved_atYesUTC timestamp of retrieval.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context by stating that the returned record is 'full' and 'including endpoints,' plus the language-dependent behavior of titles and descriptions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the main purpose in the first sentence. The Args section is minimal and every line contributes either parameter meaning or workflow context. There is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-record retrieval tool, the description provides the necessary workflow source for the ID, the language behavior, and the scope of the returned record. An output schema exists, so detailed return structure is not needed in the description. The annotations cover safety and idempotency.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the burden of explaining parameters. It does so well: data_service_id is identified as a UUID from `list_data_services`, and language is defined as affecting titles and descriptions. The schema only supplies types/enums, so this adds meaningful semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Retrieve'), a resource ('the full record for one registered API'), and a distinctive detail ('including endpoints'). It clearly differentiates from list_data_services and other sibling get_* tools by targeting a single record rather than a collection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells the agent to source data_service_id from `list_data_services`, which establishes a clear workflow and prerequisite. It does not explicitly enumerate when not to use the tool, but the singular-record framing and sibling list make the selection context clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_datasetGet one datasetA
Read-onlyIdempotent

Retrieve the full, aggregated metadata record for one dataset.

This is the aggregated detail tool: a single call returns the contact point, temporal and spatial coverage, documentation links and every distribution with its licence — so search_catalog → get_dataset answers «who publishes it, through which interface, under which licence» in two calls, without a separate distributions or contact lookup.

Args: dataset_id: UUID from search_catalog or list_datasets. language: Language for titles and descriptions.

ParametersJSON Schema
NameRequiredDescriptionDefault
languageNode
dataset_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sourceNoAttribution string.
datasetYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is fully covered. The description adds value beyond annotations by disclosing the aggregation behavior — that one call returns contact point, coverage, documentation links, and every distribution with its licence — a trait an agent cannot infer from the schema or annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The first sentence front-loads the purpose, the second sentence earns its place by explaining why aggregation matters, and the Args block is cleanly formatted. The phrasing 'answers «who publishes it, through which interface, under which licence»' is slightly florid but not filler, so the size is justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema documenting return structure, annotations covering safety and idempotency, and both parameters explained including value provenance, nothing an agent needs to call this tool correctly is missing. The workflow context (used after search_catalog or list_datasets) completes the picture.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden for both parameters. It delivers: dataset_id gains provenance (a UUID from search_catalog or list_datasets) which the schema's pattern constraint lacks, and language gains a semantic effect (titles and descriptions). Both parameters are meaningfully enriched.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Retrieve the full, aggregated metadata record for one dataset') and immediately positions itself as the aggregated detail tool. The distinction from sibling get_dataset_distributions is clear: this tool returns everything in one call, so an agent can tell them apart without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes the intended workflow (search_catalog → get_dataset) and states where dataset_id comes from (search_catalog or list_datasets). It explicitly contrasts with 'a separate distributions or contact lookup,' steering agents away from redundant sibling calls. It never names get_dataset_distributions explicitly or states hard when-not-to-use conditions, so it stops just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_dataset_distributionsGet a dataset's distributionsA
Read-onlyIdempotent

Get the downloadable files and access URLs for a dataset.

This is the «where do I actually get the data» tool. Each distribution carries its own format, licence and download URL — licences differ between distributions of the same dataset, so always read the licence field before reusing the data. (get_dataset returns these same distributions alongside the rest of the record.)

Args: dataset_id: UUID from search_catalog or list_datasets. language: Language for titles and descriptions.

ParametersJSON Schema
NameRequiredDescriptionDefault
languageNode
dataset_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
sourceNoAttribution string.
returnedYes
dataset_idYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.
dataset_titleNo
distributionsYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotent, non-destructive behavior. The description adds useful extras beyond those: distributions each have their own format, licence, and download URL, licences can differ within a dataset, and the agent should read the licence field before reuse. It also reveals consistency with get_dataset. It does not go further into rate limits or error behavior, but the annotations lower that burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the main action, then uses a short positioning sentence, a licence caveat, a sibling note, and a compact Args list. Every sentence contributes either selection guidance, parameter semantics, or a behavioral warning; there is no low-value filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter read-only retrieval tool with an output schema, the description supplies the missing context: what a distribution contains, the licence warning, the source of dataset_id, the meaning of language, and the relationship to get_dataset. An agent has enough to decide when to call it and how to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the Args section carries the semantic load and succeeds: dataset_id is explained as coming from search_catalog or list_datasets, and language is defined as controlling titles and descriptions. This meaningfully compensates for the schema's absent descriptions and complements the enum/pattern constraints already present.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get the downloadable files and access URLs for a dataset.' It also differentiates itself from the close sibling get_dataset by noting that get_dataset returns the same distributions 'alongside the rest of the record,' so an agent can distinguish the two without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It frames the tool as 'the «where do I actually get the data» tool' and names get_dataset as the alternative that returns these distributions with the full record, giving clear selection context. It does not, however, state an explicit when-to-use/when-not-to-use rule such as 'use this when you only need distributions; use get_dataset when you need the full record.'

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_catalogsList cataloguesA
Read-onlyIdempotent

List the catalogues that feed into I14Y.

Each catalogue represents one contributing organisation's data collection.

Args: language: Language for titles. page: 1-based page number. page_size: Records per page (1-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
languageNode
page_sizeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
catalogsYes
returnedYes
page_sizeYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the description doesn't need to restate those. It adds some domain context about catalogues, but no additional behavioral details such as pagination behavior, sorting, or open-world caveats beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loaded with the main action, and clearly separates purpose, context, and arguments. Every sentence earns its place and there is no redundant fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema and strong annotations, the description covers the essential domain concept and all optional parameters. It is slightly incomplete because it offers no guidance on choosing among sibling list/search tools, but it is otherwise sufficient for a simple read-only listing endpoint.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates by documenting all three parameters: language controls titles, page is 1-based, and page_size is records per page. This adds meaning beyond the bare schema titles and constraints, though the explanations are minimal.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('List') and resource ('catalogues that feed into I14Y'), then adds a defining sentence about what a catalogue represents. This makes it clearly distinguishable from siblings like list_datasets and search_catalog.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no guidance about when to use this tool versus alternatives such as search_catalog or list_datasets. It states what the tool does, but an agent is left to infer the appropriate selection context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_conceptsList harmonised conceptsA
Read-onlyIdempotent

List harmonised concepts and code lists of the Swiss administration.

Concepts are the semantic backbone of interoperability: shared definitions and code lists that different bodies agree to use. Note that these are not reachable through search_catalog.

Args: publisher_identifier: Publisher identifier from list_publishers. language: Language for titles and descriptions. page: 1-based page number. page_size: Records per page (1-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
languageNode
page_sizeNo
publisher_identifierNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
conceptsYes
returnedYes
page_sizeYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld, and non-destructive behavior, so the bar is lower. The description adds useful behavioral context: the resources are harmonised concepts and code lists with a specific semantic role, and they are not reachable via search_catalog. This goes beyond the annotations and schema without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: purpose first, then domain context, then a key caveat, then compact parameter documentation. Every sentence adds value, and the Args section is scannable without redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema presentcherta, no required parameters, comprehensive annotations, and all parameters described, nothing essential is missing. The domain context and search_catalog exclusion complete the picture for an agent deciding whether to invoke this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: every parameter is described. publisher_identifier is enriched with its source (list_publishers), language is clarified as affecting titles and descriptions, and page/page_size semantics are stated. This is sufficient, though terse.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List harmonised concepts and code lists of the Swiss administration.' It clearly distinguishes this tool from siblings by naming search_catalog as not the way to reach these resources, and the plural 'list' contrasts with singular get_concept.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says these concepts are not reachable through search_catalog, giving a when-not to use an alternative. It also instructs that publisher_identifier comes from list_publishers, chaining to the prerequisite tool. It does not explicitly contrast with get_concept or search_codelist_entries, but enough context is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_data_servicesList data services (APIs)A
Read-onlyIdempotent

List machine interfaces (APIs) registered by Swiss public bodies.

The strategic payload of this server: the national register of official APIs, with endpoint URLs and OpenAPI specification links where the publisher supplied them. Use this to discover whether an interface already exists before building a scraper.

Args: publisher_identifier: Publisher identifier from list_publishers. language: Language for titles and descriptions. page: 1-based page number. page_size: Records per page (1-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
languageNode
page_sizeNo
publisher_identifierNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
returnedYes
page_sizeYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.
data_servicesYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, so the description only needs to add context beyond that. It does: results include OpenAPI links only where the publisher supplied them, the data is the national official register, and language affects titles and descriptions. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core definition, followed by the strategic value and a concrete usage sentence. The Args block is terse, parallel, and informative. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema, annotations, and sibling context, the description is nearly complete: it explains the purpose, the data caveat, the parameter source, and the intended use. The only small gap is not explicitly describing pagination behavior, but the schema already defines page and page_size bounds clearly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the Args block carries the burden. It meaningfully covers all four parameters: publisher_identifier is tied to list_publishers, language is for titles/descriptions, page is 1-based, and page_size is records per page. This compensates for the empty schema descriptions, though it does not deeply explain filtering behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and resource ('machine interfaces (APIs) registered by Swiss public bodies'), then adds what the tool returns: endpoint URLs and OpenAPI specification links. The 'discover whether an interface already exists' use case further clarifies its role and distinguishes it from sibling list/get tools at a glance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case ('Use this to discover whether an interface already exists before building a scraper') and useful context such as listing official Swiss APIs. It also cross-references list_publishers for the publisher_identifier. However, it does not explicitly contrast with get_data_service or other sibling tools, so there is minor room for ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_datasetsList datasetsA
Read-onlyIdempotent

List registered datasets, optionally filtered by publisher.

Unlike search_catalog, this endpoint paginates correctly and covers the complete register (roughly 2000 datasets as of July 2026), including records the search index misses.

Args: publisher_identifier: Publisher identifier from list_publishers. access_rights: e.g. "PUBLIC", "NON_PUBLIC", "RESTRICTED". language: Language for titles and descriptions. page: 1-based page number. page_size: Records per page (1-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
languageNode
page_sizeNo
access_rightsNo
publisher_identifierNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
datasetsYes
returnedYes
page_sizeYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the `readOnlyHint`/`idempotentHint` annotations, it discloses pagination behavior, dataset volume, and completeness relative to the search index. These are meaningful runtime traits not visible in structured metadata and add real value for an agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose, a single targeted comparison sentence, then a terse, complete Args list. No filler or redundant restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering safety/idempotency, the description covers purpose, alternative routing, filter semantics, and pagination. Nothing needed to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has no property descriptions (0% coverage), and the description compensates with an Args block for all five parameters, including the source of `publisher_identifier` (`list_publishers`), examples for `access_rights`, and semantics for `page`/`page_size`. This is exactly what an agent needs to construct valid input.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action ('List registered datasets') plus an optional filter, and explicitly contrasts itself with `search_catalog`, so an agent can distinguish it from its siblings without opening schemas. The scope is clear and the comparison reinforces what this endpoint is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly names the alternative (`search_catalog`) and gives the deciding factors: correct pagination, complete ~2000-dataset register, and coverage of records the search index misses. This tells an agent when to choose this endpoint over the search-based sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_public_servicesList public servicesA
Read-onlyIdempotent

List registered public services (administrative offerings for citizens).

Args: publisher_identifier: Publisher identifier from list_publishers. language: Language for titles and descriptions. page: 1-based page number. page_size: Records per page (1-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
languageNode
page_sizeNo
publisher_identifierNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
returnedYes
page_sizeYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.
public_servicesYes

TDQS

A3.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint, idempotentHint, openWorldHint, and non-destructiveness, so safety is covered. The description contributes no behavioral detail beyond that—nothing about pagination iteration, ordering, response shape, or side effects—so it adds little transparency beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short, front-loads the purpose in one sentence, and then presents a compact args list where each line earns its place. No redundant prose or repetition of schema defaults.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only paginated list with a full output schema and strong annotations, the description covers the essential context: what the tool returns at a conceptual level and what each argument controls. An agent has enough to invoke it correctly without needing extra return-value or safety detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates by explaining every parameter: publisher_identifier's source from list_publishers, language's effect on titles and descriptions, page as 1-based, and page_size's range. This is meaningfully more than the bare schema types and defaults, though the definitions are terse.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and a clear resource ('registered public services'), with a helpful parenthetical explaining what public services are. It does not explicitly contrast itself with sibling tools like list_data_services, so it stops short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'registered public services (administrative offerings for citizens)' implies this is the tool for administrative offerings, and the mention of list_publishers suggests a workflow, but there is no explicit when-to-use, when-not-to-use, or alternative tool guidance. Usage is inferred from the name and description rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_publishersList publishersA
Read-onlyIdempotent

List the public bodies that publish into I14Y.

Returns publisher identifiers needed by the other tools, plus the Swiss UID where available — the UID is the join key to register-mcp (Zefix).

Args: identifier: Filter by exact publisher identifier. uid: Filter by Swiss UID, e.g. "CHE-123.456.789". language: Language for names. page: 1-based page number. page_size: Records per page (1-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
uidNo
pageNo
languageNode
page_sizeNo
identifierNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
returnedYes
page_sizeYes
provenanceNoWhere this payload came from.
publishersYes
retrieved_atYesUTC timestamp of retrieval.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered by structured data. The description adds useful context beyond this by disclosing the return payload (publisher identifiers plus Swiss UID) and the UID's role as the join key to register-mcp (Zefix). No contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first sentence, followed by a brief return-value note and a clean Args block. Every line adds information with no padding, repetition, or vague filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and all five optional parameters documented in both schema (defaults, enums, bounds) and description, an agent has what it needs to call the tool correctly. Defaults like language 'de' and page_size 50 are already encoded in the schema, and the description covers the rest — the tool is simple enough that nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden for parameter meaning — and it delivers. All five parameters are explained in an Args block, with concrete format guidance: the 'CHE-123.456.789' UID example, 1-based pagination, the 1-100 page_size bound, and language applicability. This completely compensates for the empty schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific verb (List), a resource (public bodies/publishers), and scope (publishing into I14Y), which inherently distinguishes it from sibling tools like list_datasets and list_public_services. However, it doesn't explicitly differentiate itself from siblings, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The statement 'Returns publisher identifiers needed by the other tools' gives clear context for when to use it — when a downstream tool requires a publisher identifier. It stops short of naming alternatives or exclusions, such as when to prefer search_catalog over this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_catalogSearch the I14Y catalogueA
Read-onlyIdempotent

Search Switzerland's national metadata catalogue for data resources.

The primary entry point: use this to find out who publishes data on a topic before looking for a specific dataset. Returns titles, publishers, themes and portal permalinks.

Known limitation (verified live 2026-07-21): the upstream search index covers Datasets only. Filtering by types=["Concept"] or types=["DataService"] returns zero results even though those entities exist — use list_concepts and list_data_services for those.

Args: query: Free-text search term, e.g. "Sonderpaedagogik" or "Bildung". An empty string returns the full index (over 1000 records) and is not recommended. language: Language for titles and descriptions. types: Restrict to resource types. Effectively only "Dataset" works. themes: Filter by theme identifiers. publishers: Filter by publisher identifiers. limit: Maximum records to return (1-200). Upstream ignores paging, so capping happens in this server.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes
typesNo
themesNo
languageNode
publishersNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
hintNoActionable next step when match_type is 'none' (e.g. which tool to try).
hitsYes
queryNo
sourceNoAttribution string.
languageYes
returnedYesRecords in this payload after capping.
truncatedYesTrue when the upstream result set exceeded the cap.
match_typeNo'none' when nothing matched, so the agent never sees a bare empty result.
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.
total_matchedYesMatches reported by the upstream index.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool readOnly/idempotent; the description goes beyond them by disclosing that the upstream index only covers Datasets, that Concept/DataService filters return zero results, and that the server caps the limit because upstream ignores paging. This is exactly the context annotations cannot express.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although relatively long, each sentence adds operational value: purpose, return fields, limitation, and parameter caveats. It is organized with a clear intro, limitation callout, and compact Args list. No filler or duplication of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With six parameters, an output schema, and sibling discovery tools, the description covers selection, invocation, parameter semantics, and expected returns (titles, publishers, themes, permalinks). The only aspects left implicit, such as sorting/pagination, are either addressed via the limitation or likely covered by the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the Args block describes every parameter with practical detail: query includes examples and an empty-string warning, types carries the 'only Dataset works' caveat, and limit explains the 1-200 cap and server-side capping. This fully compensates for the schema's lack of descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb and object: 'Search Switzerland's national metadata catalogue for data resources,' and narrows the tool's role as 'the primary entry point' for discovery. It explicitly distinguishes itself from dataset-specific lookups ('before looking for a specific dataset') and from type-specific siblings by stating which entity types are unsupported. This leaves no ambiguity about what the tool is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states when to use ('find out who publishes data on a topic before looking for a specific dataset') and what NOT to use it for via the known limitation. It explicitly routes Concept and DataService searches to list_concepts and list_data_services. The empty-query warning also sets expectations around acceptable use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_codelist_entriesSearch a concept's code listA
Read-onlyIdempotent

List the individual codes of a code-list concept.

Use this to resolve official code values — for example the canonical list of a classification used across several federal datasets. Only concepts with concept_type == "CodeList" return entries.

Args: concept_id: UUID of a code-list concept from list_concepts. language: Language for entry names. Required by the upstream API. page: 1-based page number. page_size: Records per page (1-200).

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNo
languageNode
page_sizeNo
concept_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
pageYes
sourceNoAttribution string.
entriesYes
languageYes
returnedYes
page_sizeYes
concept_idYes
provenanceNoWhere this payload came from.
retrieved_atYesUTC timestamp of retrieval.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool read-only, idempotent, and non-destructive. The description adds non-redundant behavioral context: only CodeList concepts return entries and `language` is required by the upstream API, which helps an agent anticipate failures. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs plus a compact Args list. The core purpose and key constraint are front-loaded, and each sentence adds information without repetition or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a paged read-only listing tool with an output schema available, the description covers purpose, applicable concept type, pagination parameters, and the upstream language requirement. It doesn't fully specify behavior for invalid or non-codelist concept IDs (empty vs error), but the CodeList-only statement largely covers the main edge case.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema-level parameter descriptions, the Args section carries the full burden and succeeds: each parameter gets a purpose, and `concept_id` is tied back to `list_concepts`, `language` noted as required upstream, and paging semantics are stated. This is complete and meaningful compensation for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'List the individual codes of a code-list concept,' a specific verb-plus-resource statement that clearly distinguishes this from sibling tools like list_concepts and get_concept. The title reinforces the scope without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It says 'Use this to resolve official code values' and adds the precondition that only concepts with `concept_type == "CodeList"` return entries, giving clear when-to-use context. It does not explicitly name sibling alternatives or state 'do not use for X,' so it earns a 4 rather than 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.3.2
    • Addedapi_status
    • Addedget_data_service
    • Addedget_dataset
  2. 10 tool updatesv0.2.1
    • First observedget_concept
    • First observedget_dataset_distributions
    • First observedlist_catalogs
    • First observedlist_concepts
    • First observedlist_data_services
    • First observedlist_datasets
    • First observedlist_public_services
    • First observedlist_publishers
    • First observedsearch_catalog
    • First observedsearch_codelist_entries

TDQS

A4.3/5.0

Scored across 13 tools

Disambiguation5/5

Each tool targets a distinct resource or action: listing vs. fetching individual entities, plus search, status, and code-list lookup. Even the overlapping get_dataset and get_dataset_distributions are clearly differentiated by the description noting get_dataset returns distributions alongside the full record, making get_dataset_distributions a focused convenience tool. No two tools appear to do the same thing.

Naming Consistency5/5

Tool names follow a consistent verb_noun pattern: list_* for collections, get_* for single entities, search_* for search operations, and api_status for health. The pattern is uniform across all 13 tools with no mixed conventions or vague verbs.

Tool Count5/5

13 tools is well within the ideal 3-15 range for a domain-specific server. Each tool covers a distinct aspect of the I14Y metadata catalog (datasets, data services, public services, concepts, publishers, catalogs, status), and none feel redundant or superfluous.

Completeness4/5

The tool surface covers the core read-only workflows for a catalog: listing and retrieving datasets, data services, concepts, and code-list entries, plus search, publishers, catalogs, and status. Minor gaps exist—there is no get_public_service or get_catalog, so those entities can only be listed, not fetched individually. This is a minor gap that agents can work around, but it does not break the primary use cases.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    An MCP server providing AI-powered access to Open Data from the City of Zurich, enabling queries to 900+ datasets, real-time environmental and mobility data, geodata, parliamentary proceedings, and more.
    26
    166 PyPI
    8
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    MCP server for TERMDAT, the terminology database of the Swiss Federal Administration, giving AI agents officially validated designations of Swiss authorities, departments, and legal acts across DE/FR/IT/EN with source references and validation status.
    7
    125 PyPI
    1
    MIT