swiss-school-calendar-mcp
This server provides a Swiss holiday calendar for AI agents — querying public holidays, school holidays (differentiated by school type), local holidays, long weekends, and more for all 26 cantons without requiring an API key.
List cantons – Get all 26 Swiss cantons with ISO codes and official languages (
list_cantons).List school types – See which cantons differentiate holidays by Schulart (VS/MS/BS/EO) and their codes (
list_school_types).Get school holidays – Fetch school holiday periods for a canton and date range, optionally filtered by school type (
get_school_holidays).Get public holidays – Retrieve a canton's public holidays for a given year (
get_public_holidays).Get local holidays – Query holidays specific to a municipality or district, e.g., Zurich's Sechseläuten (
get_local_holidays).Check a date – Determine if a specific date is a school or public holiday in a canton (
check_date).Compare school holidays – Get a pairwise overlap matrix of holiday days between cantons (
compare_school_holidays).Find common free windows – Discover date ranges when all listed cantons are simultaneously on holiday (
find_common_free_window).Next school holidays – Get the next upcoming holiday periods for a canton (
next_school_holidays).Get long weekends – List long weekends and the bridge days needed to create them, based on federal holidays (
get_long_weekends).Export iCal – Generate an
.icscalendar of a canton's holidays for a year (export_holidays_ics).Is today a holiday? – One-call check if today is a holiday in a canton (
is_holiday_today).Source health – Check reachability and latency of the upstream data sources (
source_status).
All responses include provenance (live/cache/degraded) and the server is read-only, idempotent, and requires no authentication.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@swiss-school-calendar-mcpShow me school holidays in Zurich for 2026"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
🇨🇭 Part of the Swiss Public Data MCP Portfolio
This is a private project. It is independent of any employer or institutional affiliation and represents no official position of any authority.
📅 swiss-holidays-mcp
A Swiss holiday calendar for AI agents — public holidays, school holidays and long weekends for all 26 cantons, with cross-cantonal comparison. School holidays are differentiated by Schulart (school type), which matters more than it first appears. No API key required.
Overview
swiss-holidays-mcp is a Swiss holiday calendar for AI assistants like Claude — public holidays, school holidays and long weekends for all 26 cantons, no API keys required. Public holidays are cantonal (Berchtoldstag, Fronleichnam & co. differ by canton, not just the federal minimum). School holidays are set cantonally, sometimes at district level, and — in six cantons — separately per school type. A single federal calendar does not exist; anyone planning across cantonal borders is otherwise reduced to opening 26 PDF pages.
The server covers two thematic clusters: public holidays / long weekends and school holidays (with Schulart differentiation). Each cluster maps to a group of purpose-built tools that translate raw agency data into clean, provenance-tagged JSON responses. All data comes from the OpenHolidays API (CC BY 4.0) and Nager.Date (MIT).
Mnemonic: A duplicate in Swiss school data is usually a school type in disguise. The underlying API publishes the same holiday period several times when a canton differentiates by school type. That looks like duplicated data and invites naive de-duplication — which would destroy exactly the distinction a school authority needs.
Anchor demo query: "In which weeks of 2026 are the compulsory schools of Zurich, Zug and Aargau simultaneously on holiday — and how many overlapping days does each pair share?"
→ This exercises find_common_free_window, compare_school_holidays and list_school_types in a single conversation, and answers a question that recurs every planning cycle in inter-cantonal coordination.
→ More use cases by audience →
Demo
Related MCP server: mcp-nager-holidays
Features
🏫 School holidays — periods per canton and date range, differentiated by Schulart (
VS/MS/BS/EO)🎌 Public holidays — cantonal holiday sets, not just the federal minimum (Berchtoldstag & friends)
🔍 Date check — is a given date a school or public holiday in a canton?
🔗 Cross-cantonal comparison — pairwise overlap matrix of holiday days between cantons
🪟 Common free windows — date ranges where all listed cantons are simultaneously on holiday
🌉 Long weekends & bridge days — computed from federal public holidays (Nager.Date)
🏘️ Local & municipal holidays — district- and municipality-level specifics such as Zurich's Sechseläuten and Knabenschiessen, with a
scopemarker so they are never mistaken for canton-wide📆 iCal / ICS export — a canton's holidays for a year as a ready-to-import
.icscalendar🔖 Holiday feed resource —
holidays://<canton>/<year>MCP resource with a Markdown summary📌 "Is today a holiday?" — one-call convenience for the everyday question
🩺 Source health — reachability and latency of both upstreams, always evaluable
🔑 No authentication required — both data sources are publicly accessible
☁️ Dual transport — stdio for Claude Desktop, Streamable HTTP/SSE for cloud deployment
🧾 Provenance on every response —
live_api|cached|degraded, never a silent empty list
Data Sources
Source | Data | Licence |
Cantons, Schularten, school holidays, public holidays | CC BY 4.0 | |
Long weekends and required bridge days | MIT |
Both sources are publicly accessible, no authentication required. Attribution required: OpenHolidays (CC BY 4.0) and Nager.Date must be cited as the source when using their data.
Tools
Tool | Purpose | Data Source |
| The 26 cantons with ISO codes and official languages | OpenHolidays |
| Schulart groups per canton ( | OpenHolidays |
| School holidays for one canton and date range | OpenHolidays |
| Public holidays for one canton and year | OpenHolidays |
| Public holidays for one municipality or district, incl. local specifics | OpenHolidays |
| Is a given date a school or public holiday? | OpenHolidays |
| Pairwise overlap matrix across cantons | OpenHolidays |
| Windows where all listed cantons are on holiday | OpenHolidays |
| The next upcoming holiday periods | OpenHolidays |
| Long weekends and required bridge days | Nager.Date |
| A canton's holidays for a year as an iCalendar ( | OpenHolidays |
| Is today a school or public holiday in a canton? | OpenHolidays |
| Reachability and latency of both upstreams | Built-in |
Resources
Resource URI | Content |
| Markdown summary of all public + school holidays, e.g. |
All tools carry the full annotation set — readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true (they reach an external API). No tool writes anywhere. Inputs are schema-validated (canton codes against the 26 known cantons, dates as YYYY-MM-DD, year bounded, language/school_type whitelisted).
Example Use Cases
Query | Tool |
"Which cantons are there, and what are their codes?" |
|
"Show Zurich's compulsory-school holidays for spring 2026" |
|
"Is 3 April 2026 a public holiday in Ticino?" |
|
"Do Zurich and Zug school holidays overlap this year?" |
|
"When can all of ZH, ZG, AG plan a joint week off school?" |
|
"What are the next holidays for Basel-Stadt schools?" |
|
"Which long weekends does 2026 have, and which bridge days do they need?" |
|
"Which local holidays does the city of Zurich keep that the rest of the canton doesn't?" |
|
"Export Zurich's 2026 holidays as an .ics calendar I can import" |
|
"Is today a holiday in Aargau?" |
|
🛡️ Safety & Limits
Aspect | Details |
Access | Read-only ( |
Personal data | No personal data — all sources are aggregated, public holiday calendars |
Caching | 12-hour in-memory TTL (holiday tables change a handful of times per year) |
Retry | Exponential backoff 2s / 4s / 8s; 4xx except 429 are not retried |
Timeout | 20 seconds per API call (8 seconds for health probes) |
Authentication | No API keys required — both upstreams are publicly accessible |
Degradation | Upstream failure yields a |
Terms of Service | Subject to the ToS of the respective data sources: OpenHolidays, Nager.Date |
Architecture
This server uses Architecture A (live API only, with in-memory cache).
┌──────────────────────────┐
Claude / any ───▶│ swiss-holidays-mcp │
MCP host │ (MCPServer · 13 tools) │
└────────┬─────────────────┘
│ retry 2s/4s/8s · 12h cache
┌────────┴─────────┐
▼ ▼
OpenHolidays API Nager.Date
(CC BY 4.0) (MIT)
cantons · Schularten long weekends
school + public bridge daysRationale (verified live on 2026-07-19):
All ten documented OpenHolidays endpoints answered HTTP 200 with plausible payloads;
/Subdivisions?countryIsoCode=CHreturns exactly 26 cantons, matching the official count.No public bulk dump could be verified at build time (
openpotato/openholidays.dataraw access returned 404), so Architecture B was not available.Holiday tables change a handful of times per year, so a 12-hour in-memory TTL removes almost all upstream load without risking staleness.
Consequences:
Every response carries
provenance(live_api|cached|degraded).Upstream failure yields a
degradedenvelope with an explanatorynote, never a silent empty list.source_statusalways returns an evaluable health report.
Live-probe findings (2026-07-19)
Endpoint | HTTP | Status | Records | Note |
| 200 | ✅ works | 36 | |
| 200 | ✅ works | 26 | matches official canton count |
| 200 | ✅ works | 11 | Schulart groups, only 6 cantons |
| 200 | ✅ works | 39 | cantonal scope included |
| 200 | ✅ works | 193 | 183 distinct after school-type split |
| 200 | ✅ works | – | |
| 200 | ⚠️ silently empty | 0 | invalid country ≠ error |
| 200 | ⚠️ silent EN fallback | 26 | invalid language ≠ error |
| 400 | ✅ correct error | – | RFC 9110 problem+json |
Nager | 200 | ✅ works | 33 | 29 rows carry |
Nager | 200 | ✅ works | 3 | |
Nager | 404 | ✅ correct error | – | stricter than OpenHolidays |
Known findings
Apparent duplicates are school types. Zurich returns Frühlingsferien 2026 twice: once for
CH-ZH-VS(Volksschulen, taggedRecommended) and once forCH-ZH-BS+CH-ZH-MS(Berufsfach- and Mittelschulen). Use theschool_typeparameter (VS/MS/BS/EO) rather than de-duplicating.Only six cantons differentiate by school type (AI, AR, BE, GR, SO, ZH). Elsewhere
groupsis absent and one table covers everything. The filter therefore treats an absentgroupsfield as "applies to all".Subdivision codes mix levels. Records may carry
CH-AI-APorCH-BE-TH-BL. Always match on theCH-XXprefix, never on string equality.An empty list is not an answer. An unknown country or canton code yields HTTP 200 with
[]. This server sets an explanatorynoteso that "no holidays" and "bad filter" stay distinguishable.
Prerequisites
Python 3.10 or higher
uv / uvx (recommended) or pip
Internet access (both APIs are publicly available)
Installation
Run via uv's uvx — no clone or manual install needed:
uvx swiss-holidays-mcpDevelopment
git clone https://github.com/malkreide/swiss-holidays-mcp
cd swiss-holidays-mcp
pip install -e ".[dev]"Configuration
Claude Desktop
Add to claude_desktop_config.json:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"swiss-holidays": {
"command": "uvx",
"args": ["swiss-holidays-mcp"]
}
}
}Restart Claude Desktop — the server starts automatically on first use.
Cloud Deployment (SSE / Streamable HTTP for browser access)
For use via claude.ai in the browser (e.g. on managed workstations without local software):
MCP_TRANSPORT=sse PORT=8000 python -m swiss_holidays_mcpThe SDK exposes SSE at /sse, not /mcp.
Variable | Default | Description |
|
| Transport: |
|
| Port for HTTP transports |
|
| Bind address for HTTP transports. Loopback by default; |
| (empty) | Comma-separated extra CORS origins for browser clients (audit SDK-004). Loopback origins are always allowed; add the public origin your UI is served from, e.g. |
The HTTP transports attach an explicit CORS layer that exposes the
Mcp-Session-Id header, so a browser MCP client can read the session id and
make follow-up requests. The allow-list is never a wildcard.
Running more than one HTTP instance behind a load balancer requires sticky
sessions keyed on Mcp-Session-Id — see docs/scaling.md
for nginx/Traefik/Kubernetes examples. A single instance (the common case) needs
no affinity configuration.
💡 "stdio for the developer laptop, SSE for the browser."
Project Structure
swiss-holidays-mcp/
├── src/
│ └── swiss_holidays_mcp/
│ ├── __init__.py # Package init
│ ├── __main__.py # Entry point: stdio / SSE / Streamable HTTP
│ ├── server.py # MCPServer: lifespan, 13 tools, 1 resource, op_* logic
│ ├── client.py # Shared HTTP client: retry, 12h cache, egress guard
│ ├── guard.py # Egress / SSRF guard (HTTPS + allow-list + IP blocklist)
│ ├── pinning.py # DNS-pinning transport (TOCTOU-free connect, SEC-005)
│ ├── ical.py # RFC 5545 iCalendar (.ics) writer
│ ├── settings.py # Pydantic-Settings config (loopback default)
│ ├── logging_setup.py # Structured logging to stderr
│ ├── constants.py # Canton codes, Schulart suffixes, API bases, allow-list
│ └── models.py # Pydantic v2 response envelopes
├── tests/
│ ├── conftest.py # respx fixtures
│ ├── test_tools.py # Tool unit tests (mocked, no network)
│ ├── test_resilience.py # Degradation / retry / cache behaviour
│ └── test_live.py # Live smoke tests (marker: live)
├── docs/ # roadmap.md, security.md, network-egress.md
├── deploy/ # Network-layer egress manifests (Cilium / NetworkPolicy)
├── audits/ # mcp-audit run artifacts
├── Dockerfile # Non-root multi-stage container
├── .github/
│ ├── dependabot.yml # Weekly dependency / action update PRs
│ └── workflows/ # ci.yml, live-tests.yml, publish.yml
├── pyproject.toml
├── CHANGELOG.md
├── CONTRIBUTING.md # Contributing guide (English)
├── CONTRIBUTING.de.md # Contributing guide (German)
├── SECURITY.md # Security policy (English)
├── SECURITY.de.md # Security policy (German)
├── EXAMPLES.md # Use cases by audience
├── server.json # MCP registry manifest
├── LICENSE
├── README.md # This file (English)
└── README.de.md # German versionOn the single-file server.py (audit ARCH-011). The 13 tools deliberately
live in one module rather than a tools/ package. Each tool is a thin, uniform
wrapper (@mcp.tool → @_safe_tool → op_*) over a transport-agnostic op_*
operation, and every operation shares the same small set of helpers
(_to_period, _matches_school_type, _require_known_canton, …) and the one
HolidayClient. Splitting these across files would scatter that shared core and
duplicate imports for no isolation benefit — the file is uniformly sectioned
(aliases → helpers → op_* logic → tool wrappers → resource) and every op_*
is unit-tested directly without a transport. A tools/ split is the planned
step only if Phase 2 pushes the tool count materially higher.
Lifecycle Phase
This server is in Phase 1 (read-only) — all tools read-only, no auth, no side
effects. The 13-tool budget (of the 15–20 recommended maximum) still leaves
headroom. Local and municipal specifics — including Zurich's Sechseläuten and
Knabenschiessen — are covered directly from OpenHolidays via get_local_holidays
(a live probe showed they are published upstream at Gemeinde level), so no
separate city data source is required for them.
MCP Primitives & Protocol Version
Primitives — Tools + Resources. The 13 tools are idempotent, side-effect-free
GETs. A Resource exposes a stable URI feed (holidays://<canton>/<year>) so clients can read a canton's calendar as cacheable context without a tool call. There are no recurring templated workflows, so Prompts are not used (revisited if that changes).MCP protocol version — two eras.
mcp2.x serves both over the same server, and the client's first request on a connection decides which applies: theinitializehandshake caps at2025-11-25, the per-request envelope reaches2026-07-28.source_statussurfaces one of them in itsmcp_protocol_versionfield — a single string cannot name both — and it surfaces the handshake ceiling, because that is what a client reaching this server overinitializeactually negotiated. Measured, not inferred from a constant name: a client asking the handshake for2026-07-28gets2025-11-25back.MCP_PROTOCOL_VERSIONis derived from the SDK'sLATEST_HANDSHAKE_VERSIONrather than written down, so it cannot drift the way it once did — it stood at2025-06-18for two revisions while every call reported it as fact.tests/test_protocol_version.pyholds both eras against the SDK and checks the delivered field against the SDK too, not against the constant it came from. The wire version is negotiated by the pinnedmcpSDK (mcp>=2.0.0,<3).Update policy. SDK and dependency bumps land via Dependabot (weekly); protocol-version or tool-definition changes are recorded in
CHANGELOG.mdwith a version bump.
Data classification
All data is Öffentlich / Public Open Data — aggregated holiday calendars,
no personal data (DSG/DSGVO). This is the highest classification the server
handles; the full model is in docs/security.md.
Known Limitations
Unofficial source. OpenHolidays aggregates cantonal publications. For legally binding dates, the cantonal authority remains authoritative. Every response says so.
Municipal coverage depends on the upstream. OpenHolidays does carry district- and municipality-level public holidays (e.g. Sechseläuten, Knabenschiessen at
CH-ZH-ZH-ZH), exposed throughget_local_holidays. Completeness at Gemeinde level is only as good as the upstream data, which varies by canton. Municipal school holidays are not separately modelled.Nager long weekends ignore cantonal holidays. They are computed from nationwide holidays only.
No historical depth guarantee. Coverage of years before roughly 2020 is uneven.
Testing
# Unit tests (no network required — respx-mocked)
PYTHONPATH=src pytest tests/ -m "not live"
# Live smoke tests (hits the real upstream APIs)
PYTHONPATH=src pytest tests/ -m "live"
# Linting
ruff check src/ tests/ scripts/
ruff format --check src/ tests/ scripts/Contributing
Contributions are welcome! Please read CONTRIBUTING.md (English) · CONTRIBUTING.de.md (German) for guidelines on reporting bugs, setting up the development environment, code style and test requirements.
This project follows the conventions of the Swiss Public Data MCP Portfolio.
Security
To report a vulnerability, please follow the responsible disclosure process in SECURITY.md (English) · SECURITY.de.md (German). The server is read-only and requires no API key; see the Safety & Limits section above for the security model.
Changelog
See CHANGELOG.md
Deployment for Swiss Public Administration
If you self-host this server for a Swiss school authority or municipal use case:
Data residency: the query patterns themselves (which cantons a civil servant compares) may reveal ongoing planning and are best kept on Swiss or trusted infrastructure.
Upstream calls go to OpenHolidays (EU-hosted OGD project) and Nager.Date. No personal data leaves your environment; only holiday calendars are requested.
Logging: logs are written to stderr; configure your IT retention policy accordingly.
HTTP transport should run behind a reverse proxy with authentication and per-IP rate limits — the server has no built-in authentication.
License
MIT License — see LICENSE
Source data is subject to the terms of OpenHolidays (CC BY 4.0) and Nager.Date (MIT); attribution to these sources is required when using their data.
Author
Hayal Oezkan · github.com/malkreide
Credits & Related Projects
Data: OpenHolidays API (CC BY 4.0) · Nager.Date (MIT)
Protocol: Model Context Protocol — Anthropic / Linux Foundation
Built following the
mcp-data-source-probemethodology: live probe before design, dump fallback before API dependency, retry before defeatism.Portfolio: Swiss Public Data MCP Portfolio
Server | Description |
Canton of Zurich education data | |
City of Zurich Open Data | |
BFS STAT-TAB — Swiss federal statistics | |
Swiss federal geodata (swisstopo) |
MIT licensed. Public money, public code.
Available Tools
13 toolscheck_dateARead-onlyIdempotent
Check whether a given date falls into school holidays or a public holiday.
The everyday scheduling question: can we hold the parents' evening on that Thursday? Checks one date against both school and public holidays.
The everyday question behind this tool: "Can we schedule the parents' evening on that Thursday?"
| Name | Required | Description | Default |
|---|---|---|---|
| canton | Yes | ISO code, e.g. CH-ZH | |
| language | No | DE | |
| school_type | No | ||
| check_date_iso | Yes | Date as YYYY-MM-DD |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| canton | Yes | |
| source | Yes | Attribution string of the upstream source. |
| matches | Yes | |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| checked_date | Yes | |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
| is_public_holiday | Yes | |
| is_school_holiday | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, and non-destructive. Description adds context that it checks both school and public holidays, which is beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Short but includes redundant use-case block repeating the same idea. Could be more concise without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Adequately covers core purpose. Output schema exists, so return values not needed. Distinguishes from siblings partly, but lacks edge-case context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 50% schema coverage, description adds no information about parameters. Relies entirely on schema, which has descriptions for only two of four parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks a date for school and public holidays. It distinguishes from siblings like is_holiday_today and get_school_holidays.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for single date checking against both holiday types, but no explicit when-to-use or when-not-to-use compared to alternatives like get_school_holidays.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_school_holidaysARead-onlyIdempotent
Compare school holiday overlap between cantons for a calendar year.
Quantify inter-cantonal school-holiday overlap (pairwise day counts) for coordinating events or campaigns across cantonal borders.
Returns a pairwise matrix of overlapping holiday days. Defaults to VS
(Volksschule) because that is the level most inter-cantonal coordination
concerns.
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes | ||
| cantons | Yes | ||
| language | No | DE | |
| school_type | No | VS |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| rows | Yes | |
| year | Yes | |
| source | Yes | Attribution string of the upstream source. |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
| school_type_filter | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, idempotentHint, and openWorldHint. The description adds the output format and default behavior but does not significantly extend behavioral insight 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with a structured use case block. Every sentence adds value, no redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Input schema is covered with defaults and use case. Output schema exists (not shown). The description is adequate for the tool's complexity, though it could elaborate on overlap calculation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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. It explains the default for school_type and the purpose, but does not detail the language or cantons format, leaving gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool compares school holiday overlap between cantons, returning a pairwise matrix. It is distinct from siblings like get_school_holidays or find_common_free_window.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The use case explicitly states when to use the tool (coordinating events across cantonal borders) and explains the default school type (VS) as most relevant. It lacks explicit alternatives, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_holidays_icsARead-onlyIdempotent
Export a canton's holidays for a year as an iCalendar (.ics) document.
Produce a ready-to-import .ics calendar of a canton's holidays for a year, filtered by public/school and Schulart.
Returns a ready-to-save text/calendar document with one all-day event per
holiday. include selects all (default), public or school; combine
with school_type (VS/MS/BS/EO) to narrow school holidays.
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes | ||
| canton | Yes | ISO code, e.g. CH-ZH | |
| include | No | all | |
| language | No | DE | |
| school_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| ics | Yes | The full iCalendar (text/calendar) document. |
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| year | Yes | |
| canton | Yes | |
| source | Yes | Attribution string of the upstream source. |
| filename | Yes | Suggested file name, e.g. holidays-CH-ZH-2026.ics. |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| event_count | Yes | Number of VEVENTs in the calendar. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false. The description adds that the output is a text/calendar document with all-day events, and explains how parameters filter holidays. This complements the annotations without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: one sentence for the main purpose, a use_case block, and a sentence detailing return and parameters. Every sentence adds value, and there is no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations are rich, the description covers the essential behavioral and parameter details. It explains the output type and filtering options. Minor omission: it doesn't mention the output is a downloadable file, but this is inferred from 'ready-to-import .ics document.'
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers only 20% of parameters with descriptions. The description adds meaning for 'include' (all, public, school) and 'school_type' (VS/MS/BS/EO) beyond patterns. However, 'language' and the constraints on 'year' and 'canton' are not elaborated. Overall, it provides useful context but leaves some gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool exports a canton's holidays for a year as an iCalendar document. The use_case block reinforces the purpose, and the sibling tools (e.g., check_date, get_school_holidays) are distinct in that they do not produce ICS files, making this tool's purpose unique and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to produce a ready-to-import .ics calendar, implying use when an ICS file is needed. However, it does not explicitly state when not to use it or mention alternatives (e.g., get_school_holidays for JSON). The guidance is clear but lacks exclusionary context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_common_free_windowARead-onlyIdempotent
Find date ranges in which all listed cantons are simultaneously on holiday.
Find a common free window across several cantons — joint events, maintenance or campaigns when every listed canton is on holiday.
Useful for planning campaigns, joint events or maintenance windows across cantonal borders.
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes | ||
| cantons | Yes | ||
| language | No | DE | |
| min_days | No | ||
| school_type | No | VS |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| source | Yes | Attribution string of the upstream source. |
| windows | Yes | |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, openWorld, idempotent, and non-destructive hints. Description adds context about finding common free windows but does not discuss rate limits, authorization, or other behavioral traits beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very concise: two short sentences plus a use case block. Front-loaded with the core purpose. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 5 parameters and an output schema, the description covers the main use case but lacks details about return format, parameter defaults, and edge cases. Adequate but not comprehensive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%; the description does not explain individual parameters (year, cantons, language, min_days, school_type). It only briefly mentions 'listed cantons' and 'year', leaving other parameters without semantic context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool finds date ranges when all listed cantons are simultaneously on holiday, with a concrete use case. It distinguishes from sibling tools like check_date or is_holiday_today.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Describes when to use it (planning campaigns, joint events, maintenance). Does not explicitly state when not to use, but context from siblings implies alternatives. Slightly lacking explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_local_holidaysARead-onlyIdempotent
Public holidays for a single municipality or district, incl. local specifics.
Answer the locality question the canton-level tools flatten away: which holidays are observed only in this town (e.g. Zurich's Sechselaeuten)? scope is 'local' (specific here), 'regional' (canton/district) or 'national' (inherited). Accepts a name or a full subdivision code.
Answers the local question the canton-level tools flatten away: which holidays are observed only here? The city of Zurich, for example, keeps Sechseläuten and Knabenschiessen (both half-day), which the rest of the canton does not.
municipality accepts a name (e.g. "Zürich", "Morschach") or a full
subdivision code (e.g. "CH-ZH-ZH-ZH"). The result lists every holiday that
applies in that locality; each carries a scope of local (specific to this
place), regional (inherited from the canton/district) or national.
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes | ||
| canton | Yes | ISO code, e.g. CH-ZH | |
| language | No | DE | |
| municipality | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| count | Yes | |
| source | Yes | Attribution string of the upstream source. |
| holidays | Yes | |
| match_type | No | How the lookup key resolved (audit ARCH-003): 'exact' (code or full name / validated canton), 'fuzzy' (a single prefix match was assumed) or 'none' (nothing matched — see `note` for suggestions). |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false. The description adds behavioral context: it describes the scope attribute on returned holidays, that municipality accepts name or full subdivision code, and that results list every holiday applying in the locality. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with use_case and important_notes sections, but it is somewhat lengthy. Every sentence adds value, but it could be slightly more concise without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (many sibling tools) and the presence of comprehensive annotations and an output schema, the description is complete. It explains the key differentiator (local scope) and adequately covers behavior beyond structured fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low (25%), but the description adds meaning for the municipality parameter (accepts name or code) and clarifies the result structure with scope. However, it does not explain the canton, year, or language parameters beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns public holidays for a specific municipality or district, including local specifics, and explicitly distinguishes from canton-level tools that flatten away local holidays.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a use case for when to use this tool (to answer locality questions flatted by canton tools) and explains the scope concept (local/regional/national). It does not explicitly list when not to use it or mention sibling alternatives, but the differentiation is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_long_weekendsARead-onlyIdempotent
Return Swiss long weekends and the bridge days needed to create them.
Plan bridge days: which long weekends exist this year and which working days must be taken off to extend them. Computed from federal public holidays (Nager.Date); cantonal-only holidays are not considered.
Sourced from Nager.Date, which computes these from federal public holidays; cantonal-only holidays are not considered.
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| year | Yes | |
| source | Yes | Attribution string of the upstream source. |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
| long_weekends | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool as read-only, idempotent, and non-destructive. The description adds behavioral context: it is computed from federal public holidays from Nager.Date, and cantonal holidays are ignored. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is fairly structured with a main sentence and XML tags, but it contains redundancy (the note about federal holidays appears twice). It could be more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter), annotations, and existence of an output schema, the description adequately covers purpose, usage, and behavioral limitations. It is mostly complete, though it does not describe the output structure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, but the description implies the 'year' parameter through the use case ('which long weekends exist this year'). However, the description does not explicitly document the parameter or its constraints, so it provides minimal additional meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Return Swiss long weekends and the bridge days needed to create them', using a specific verb and resource. The use case further clarifies the tool's purpose, distinguishing it from siblings like get_public_holidays.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a use case for planning bridge days and notes the limitation of only considering federal holidays. It implies when to use this tool, but does not explicitly mention alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_public_holidaysARead-onlyIdempotent
Return public holidays for one canton and calendar year.
Get a canton's official public holidays for a whole year — cantonal holidays (Berchtoldstag, Fronleichnam) differ, so always pass the canton.
Cantonal holidays such as Berchtoldstag differ substantially across Switzerland, so always pass the canton rather than assuming the federal set.
| Name | Required | Description | Default |
|---|---|---|---|
| year | Yes | ||
| canton | Yes | ISO code, e.g. CH-ZH | |
| language | No | DE |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| count | Yes | |
| source | Yes | Attribution string of the upstream source. |
| holidays | Yes | |
| match_type | No | How the lookup key resolved (audit ARCH-003): 'exact' (code or full name / validated canton), 'fuzzy' (a single prefix match was assumed) or 'none' (nothing matched — see `note` for suggestions). |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering safety and idempotency. The description adds that it returns data for a whole year, but no further behavioral details (e.g., performance, errors) are provided, so the added value is moderate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded with the purpose, but it contains redundancy (e.g., 'always pass the canton' is stated twice). It could be more concise and structured better.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with an output schema, the description covers the main use case but misses the optional language parameter entirely. Given the sibling tools, it does not differentiate explicitly, leaving some context gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low at 33% (only canton has a description). The tool description repeats the need to pass the canton and year but does not explain the format or the optional language parameter, failing to compensate for the missing schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns public holidays for a canton and year, using the verb 'Return' and specifying the resource and scope. It distinguishes itself from siblings like get_school_holidays and is_holiday_today by emphasizing the need to pass a canton for cantonal holidays.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises to 'always pass the canton because cantonal holidays differ substantially,' providing clear context on when to use this tool. However, it does not mention when not to use it or list alternative tools for related queries, slightly reducing the score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_school_holidaysARead-onlyIdempotent
Return school holiday periods for one canton in a date range.
Look up a canton's school holidays for planning within an explicit from/to window (term breaks, parent events, campaigns). Apparent duplicates are the same period per Schulart; set school_type to collapse them. Cantons that do not differentiate return one table.
Args:
canton: ISO subdivision code, e.g. CH-ZH.
valid_from: Inclusive start date, YYYY-MM-DD.
valid_to: Inclusive end date, YYYY-MM-DD.
school_type: Optional Schulart suffix -- VS, MS, BS or EO.
Use VS for compulsory schooling (Volksschule).
language: DE, FR, IT or EN.
Records that look duplicated are usually the same period published for a
different Schulart. Set school_type to collapse them.
| Name | Required | Description | Default |
|---|---|---|---|
| canton | Yes | ISO code, e.g. CH-ZH | |
| language | No | DE | |
| valid_to | Yes | Date as YYYY-MM-DD | |
| valid_from | Yes | Date as YYYY-MM-DD | |
| school_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| count | Yes | |
| source | Yes | Attribution string of the upstream source. |
| holidays | Yes | |
| match_type | No | How the lookup key resolved (audit ARCH-003): 'exact' (code or full name / validated canton), 'fuzzy' (a single prefix match was assumed) or 'none' (nothing matched — see `note` for suggestions). |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint, idempotentHint), the description discloses duplicate handling and how to collapse them via 'school_type', and explains behavior for cantons that don't differentiate. This adds significant context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with tags but slightly verbose. It could be tightened without losing clarity, but remains efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
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, the description adequately covers use case, parameters, and behavioral quirks. It is complete for a tool of moderate complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The 'Args' section provides clear explanations for all 5 parameters, including format examples and guidance on 'school_type' values. This surpasses the schema descriptions, which had 60% coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'return', resource 'school holiday periods', and constraints (one canton, date range). It distinguishes from siblings like 'get_public_holidays' by focusing on school holidays and canton-specific scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'use_case' tag explicitly describes when to use the tool (planning within an explicit from/to window). It does not provide direct exclusions but the sibling list implies alternatives for other holiday types.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
is_holiday_todayARead-onlyIdempotent
Is today a school or public holiday in the given canton?
One-call convenience for the everyday 'are we off today?' question in a given canton.
Convenience wrapper over check_date for the everyday question
"are we off today?".
| Name | Required | Description | Default |
|---|---|---|---|
| canton | Yes | ISO code, e.g. CH-ZH | |
| language | No | DE | |
| school_type | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| canton | Yes | |
| source | Yes | Attribution string of the upstream source. |
| matches | Yes | |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| checked_date | Yes | |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
| is_public_holiday | Yes | |
| is_school_holiday | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, covering the safe nature. The description adds that it's a convenience wrapper for `check_date`, but does not provide significant additional behavioral context beyond what annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences and a tag. Every word earns its place, and the main purpose is front-loaded immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and the presence of annotations and an output schema, the description adequately covers the main use case. It does not explain return values (not needed due to output schema) and is sufficiently complete for a convenience wrapper.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33% (canton described). The description mentions 'given canton' but does not elaborate on `language` or `school_type` parameters. It fails to compensate for the low coverage, leaving agents unclear on optional parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks if today is a school or public holiday in a given canton, using a specific verb and resource. It distinguishes itself from sibling tool `check_date` as a convenience wrapper for the everyday question.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'one-call convenience for the everyday...are we off today?' and 'convenience wrapper over check_date', providing clear context for when to use this tool over alternatives. However, it does not explicitly state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_cantonsARead-onlyIdempotent
List the 26 Swiss cantons with their ISO subdivision codes.
Resolve a canton name to the CH-XX code every other tool needs; call this first when the user gives a canton by name.
Use this first to resolve a canton name to the CH-XX code that every other
tool expects.
| Name | Required | Description | Default |
|---|---|---|---|
| language | No | DE |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| source | Yes | Attribution string of the upstream source. |
| cantons | Yes | |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, indicating a safe read operation. The description adds that it returns 26 cantons with codes and the CH-XX format, which is helpful but not required.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, with the core action in the first sentence and additional guidance in a separate use case section. It is well-structured and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with a single optional parameter and an output schema, the description is mostly adequate but fails to document the language parameter's effect. The use case guidance is helpful, but the parameter gap reduces completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description does not mention the 'language' parameter, its default, or how it affects the output. The description only says 'list the 26 Swiss cantons', without clarifying that names vary by language.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it lists the 26 Swiss cantons with ISO codes. It uses a specific verb 'list' and resource 'Swiss cantons', and the use case differentiates from sibling tools which focus on holidays and dates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to 'call this first' when resolving a canton name to the CH-XX code needed by other tools. Provides clear when-to-use and a concrete use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_school_typesARead-onlyIdempotent
List the Schularten (school types) that publish separate holiday tables.
Discover whether a canton differentiates school holidays by Schulart before querying, so VS/MS/BS/EO filters are used only where they exist.
Only a minority of cantons differentiate. For Zurich the codes are
CH-ZH-VS (Volksschulen), CH-ZH-MS (Mittelschulen) and CH-ZH-BS
(Berufsfachschulen). Cantons absent from this list publish one table for
all school types.
| Name | Required | Description | Default |
|---|---|---|---|
| canton | No | ||
| language | No | DE |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| source | Yes | Attribution string of the upstream source. |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
| school_types | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=False. The description adds behavioral context: it lists only school types that publish separate holiday tables, and absence means unified table. It also gives example codes for Zurich, enhancing transparency beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise with three sentences plus a use_case tag. It is front-loaded with the main action. The use_case tag is helpful but somewhat redundant. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple listing nature and presence of output schema, the description covers all necessary context: what the tool does, when to use, behavior regarding missing cantons, and example codes. Annotations cover safety. Complete for its purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and parameters have minimal descriptions ('ISO code', 'Language'). The description does not explain the canton parameter format or language parameter function beyond examples. It mentions canton codes in Zurich example but not the ISO pattern. Description does not compensate for lack of schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'List the Schularten (school types) that publish separate holiday tables.' It uses specific verb+resource, and distinguishes from sibling tools like list_cantons and get_school_holidays by focusing on differentiation of holiday tables.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit use case: 'Discover whether a canton differentiates school holidays by Schulart before querying.' It also notes that only a minority of cantons differentiate, guiding when to use. However, it does not explicitly state when not to use or suggest alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
next_school_holidaysARead-onlyIdempotent
Return the next upcoming school holiday periods for a canton.
Forward-looking planning: the next N school-holiday periods for a canton from today, without computing a date range by hand.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| canton | Yes | ISO code, e.g. CH-ZH | |
| language | No | DE | |
| school_type | No | VS |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| count | Yes | |
| source | Yes | Attribution string of the upstream source. |
| holidays | Yes | |
| match_type | No | How the lookup key resolved (audit ARCH-003): 'exact' (code or full name / validated canton), 'fuzzy' (a single prefix match was assumed) or 'none' (nothing matched — see `note` for suggestions). |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds context about computing from today, which is useful but not extensive. No additional behavioral details like rate limits or caching are provided, but the annotations cover the core safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short, with a clear main sentence and a helpful use case block. No redundant text, though the use case could be integrated more concisely.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description provides the core purpose and context (forward-looking, from today). However, with low parameter documentation and no mention of output format (despite an output schema existing), it is not fully complete for a tool with 4 parameters and sibling alternatives.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25% (only 'canton' has a description). The tool description does not mention any parameter details, leaving the other three parameters (count, language, school_type) with no semantic guidance beyond the schema's minimal info.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Return' and the resource 'next upcoming school holiday periods for a canton', with a specific use case for forward-looking planning. This distinguishes it from sibling tools like 'get_school_holidays' which likely handle date ranges.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The use case explains when to use this tool (forward-looking planning without manual date range computation). However, it does not explicitly state when not to use it or provide direct alternatives, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
source_statusARead-onlyIdempotent
Report reachability and latency of both upstream sources.
Health check before a batch of queries, or to distinguish 'no data' from 'source down' — always returns an evaluable status.
Always returns an evaluable status rather than an empty result set, so that "no data" can be distinguished from "source down".
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | Human-readable caveat, set when provenance is 'degraded'. |
| source | Yes | Attribution string of the upstream source. |
| sources | Yes | |
| provenance | Yes | live_api = freshly fetched, cached = in-memory cache, degraded = upstream unreachable, stale or empty payload. |
| all_healthy | Yes | |
| retrieved_at | Yes | ISO-8601 UTC timestamp of the underlying fetch. |
| mcp_protocol_version | Yes | MCP wire protocol version this server is built and tested against. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and non-destructive behavior. The description adds that it always returns an evaluable status, which is a behavioral guarantee not covered by annotations. However, it does not detail how reachability or latency is measured.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise with two sentences and a structured use_case tag. Every sentence adds value and is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and an output schema, the description fully covers what the tool does, when to use it, and its behavioral guarantee. No gaps are evident.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are no parameters, so schema coverage is 100%. Baseline 4 is appropriate; the description does not need to add param information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool reports reachability and latency of upstream sources, with a specific use case for health checks and distinguishing 'no data' from 'source down'. This is distinct from the sibling holiday/date tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly mentions when to use the tool: as a health check before queries or to differentiate source status. It does not specify when not to use it, but the use case is well-defined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
All 13 tools have clearly distinct purposes. Each targets a specific aspect of Swiss school calendar queries, from date checks to holiday comparisons and exports. There is no ambiguity or overlap.
Most tool names follow a verb_noun pattern (e.g., check_date, list_cantons, get_school_holidays). Two tools (is_holiday_today, source_status) deviate slightly, but the pattern is still predictable and readable.
13 tools is well-scoped for the Swiss school calendar domain. Each tool serves a specific need such as querying holidays, comparing cantons, or exporting calendars, without unnecessary duplication.
The tool surface covers the full lifecycle of holiday lookups: enumeration (list_cantons, list_school_types), individual checks (check_date, is_holiday_today), bulk retrieval (get_school_holidays, get_public_holidays, get_local_holidays), comparison (compare_school_holidays, find_common_free_window, next_school_holidays, get_long_weekends), export (export_holidays_ics), and health checks (source_status). No obvious gaps.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for public_holidays_mcp
Holidays MCP — wraps Nager.Date API (free, no auth)
opendata.swiss MCP — Switzerland's federal open-data portal (CKAN catalogue).
Nager.Date Public Holidays MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceSwiss open data MCP server — transport, weather, geodata, companies, etc,. Zero API keys.7622722MIT
- AlicenseNot gradedqualityFmaintenanceMCP server for accessing Nager.Date public holidays data. It provides tools to query and retrieve holiday information for various countries through natural language or direct tool calls.13MIT
- AlicenseAqualityAmaintenanceMCP server for searching Swiss court decisions from federal and cantonal courts via entscheidsuche.ch. Enables full-text search, law reference lookup, and filtering by canton, court level, and date without API keys.81MIT
- AlicenseAqualityDmaintenanceAn unofficial MCP server for accessing Swiss Federal Statistical Office (BFS) data.81MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/malkreide/swiss-holidays-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server