seco-labor-mcp
The seco-labor-mcp server provides access to Swiss labor market statistics from SECO and AMSTAT via opendata.swiss, enabling AI models and applications to query unemployment, job seeker, and open position data without any API key.
Available tools:
seco_search_datasets– Search the Swiss Open Government Data portal for SECO labor market datasets by keyword (German or English), returning titles, IDs, and download links.seco_get_dataset– Retrieve full metadata and resource download URLs for a specific dataset by ID or slug.seco_get_unemployment_overview– Fetch national or cantonal unemployment figures, including rates and year-over-year comparisons, with optional canton/year filters.seco_get_youth_unemployment– Access unemployment data for 15–24 year olds, useful for educational planning, vocational guidance, and apprenticeship market monitoring.seco_get_job_seekers– Get Stellensuchende statistics (broader than unemployed; includes people in retraining/ALV programs) at national or cantonal level.seco_get_open_positions– Retrieve open job position statistics as a leading indicator for labor market demand and sector analysis.seco_get_unemployment_by_occupation– Get unemployment breakdowns by occupational group (Berufshauptgruppe) for vocational counseling and identifying high-risk or high-demand professions.seco_get_monthly_report_url– Generate and validate URLs for SECO's monthly labor market press report PDF in German, French, or Italian.seco_list_cantons– Retrieve all 26 Swiss canton codes and full names as a reference utility.
Most tools support both markdown (human-readable) and json (structured) output formats.
Click on "Deploy 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., "@seco-labor-mcpshow youth unemployment in Bern"
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
SECO Labor Market MCP Server
🌐 English | Deutsch
An MCP (Model Context Protocol) server for Swiss labor market data from SECO (Staatssekretariat für Wirtschaft) and AMSTAT via opendata.swiss.
Overview
This server connects AI models to Swiss labor market statistics — unemployment rates, job seekers, open positions, youth unemployment, and occupational breakdowns — all without requiring an API key.
Primary audiences:
🏫 Schulamt / Education planning — youth unemployment, vocational guidance data
📊 Research & analysis — labor market trends, cantonal comparisons
🤖 AI agents — automated labor market monitoring and reporting
Anchor query:
"Welche Berufsgruppen haben im Kanton Zürich die höchste Jugendarbeitslosigkeit, und welche Lehrberufe unterliegen der Stellenmeldepflicht?"
→ More use cases by audience →
Related MCP server: mcp-destatis
Data Sources (Phase 1 — No Auth Required)
Source | Description | Status |
CKAN catalogue; the pinned BFS table | ✅ Live | |
Monthly press reports (PDF, structured URL pattern) | ✅ Live | |
AMSTAT reference portal | ⚠️ JavaScript SPA, no public REST API | |
Unfallstatistik UVG (SSUV/KSUV c/o Suva) — occupational accidents and diseases | ⚠️ PDF only, no API (see below) |
Architecture
┌─────────────────────────────────────────────────────┐
│ seco-labor-mcp │
│ │
│ ┌─────────────┐ ┌──────────────────────────┐ │
│ │ FastMCP │ │ 9 MCP Tools │ │
│ │ Server │◄──►│ seco_search_datasets │ │
│ │ (stdio / │ │ seco_get_dataset │ │
│ │ SSE) │ │ seco_get_unemployment_* │ │
│ └─────────────┘ │ seco_get_youth_* │ │
│ │ │ seco_get_job_seekers │ │
│ ▼ │ seco_get_open_positions │ │
│ ┌─────────────┐ │ seco_get_monthly_url │ │
│ │ httpx │ │ seco_list_cantons │ │
│ │ async │ └──────────────────────────┘ │
│ └──────┬──────┘ │
└─────────┼───────────────────────────────────────────┘
│
▼
┌───────────────────────────────────┐
│ opendata.swiss CKAN API │
│ https://opendata.swiss/api/3/ │
│ action/package_search │
│ action/package_show │
└───────────┬───────────────────────┘
│
▼
┌───────────────────────────────────┐
│ SECO Data Resources │
│ CSV / XLSX / PDF Downloads │
│ (monthly labor market data) │
└───────────────────────────────────┘Where the figures come from — and what is missing
SECO is no longer a publisher on opendata.swiss. Verified 2026-08-14:
organization_show returns 404, and none of the 176 entries in
organization_list is SECO. Until then the server filtered every search on
that organisation and therefore returned nothing — a name lookup that
misses looks exactly like an empty search.
The registered unemployed and job seekers are still SECO's figures: the BFS
publishes them in table T3.3.0.1 and names SECO in the footer. The server
reads that table through a pinned dataset id (sources.py), checked
against the live source by a live test.
Series | 2000 | 2025 |
Registered job seekers (SECO) | 124.6 | 214.1 |
Registered unemployed (SECO) | 72.0 | 133.7 |
ILO unemployed (BFS) | 126.5 | 248.5 |
thousands, annual average
The three series do not measure the same thing: in 2000 the ILO figure is 1.76× the registered one. The server reports them separately and labelled, and never converts one into the other.
The cantonal layer: four cantons, four schemas
There is no national monthly series — but four cantons publish their own
RAV figures, each in its own portal with its own column names. For those,
seco_get_unemployment_overview(canton=…) returns real values:
Canton | Granularity | from | Level | Note |
TG | monthly | 2016-01 | canton | only series by age class → youth unemployment as a count |
FR | monthly | 2004-01 | canton and Switzerland | carries the national monthly figure as a comparison row |
ZG | monthly | 1993-01 | canton | youth unemployment only as a rate, not a count |
ZH | annual | 1991 | municipality | no monthly values; districts and regions sit in the same column as municipalities and are separated out |
The other 22 cantons get a named refusal — no figure from another canton and no national aggregate. Partial coverage that feels complete is worse than none.
The four series are not comparable with each other and do not add up to a Swiss figure: different time axes, different geographic levels, and in ZG's case a rate rather than a count.
Still not available: unemployment by occupational group, open positions as a national series, and youth unemployment for Switzerland or for 24 of the 26 cantons. The affected tools say so and return no substitute figure. These values exist interactively on amstat.ch, which offers no interface a server could call.
Tools
Tool | Description | Key Use Case |
| Search labour-market datasets on opendata.swiss (publisher shown per hit) | Discovery |
| Full metadata + download links for a dataset | Data access |
| Registered unemployed: national annual, cantonal for TG/FR/ZG/ZH | Labor market overview |
| Youth unemployment (15–24) — TG (count) and ZG (rate) only | 🎓 Berufswahlberatung |
| Registered job seekers, national, annual series from 2000 | Training demand |
| Open positions — no national series available | Sector analysis |
| Breakdown by Berufshauptgruppe — no machine-readable source | 🎓 Vocational guidance |
| Generate/verify PDF report URL | Source access |
| All 26 canton codes and names | Utility |
| UVG key figures on occupational accidents and diseases | Risk overview |
| Results per NOGA 2008 economic branch | 🎓 Vocational guidance |
| Ten-year accident time series per branch | Trend analysis |
12 of a maximum of 15 tools.
Unfallstatistik UVG (SSUV)
The three seco_get_uvg_* tools cover the risk side of the same labour market
the unemployment tools describe: how many occupational accidents and diseases
occur per branch, and how that develops over ten years.
The publisher is not SECO. The Unfallstatistik UVG is issued by the
Koordinationsgruppe KSUV and the Sammelstelle SSUV c/o Suva, Lucerne. The
seco_ prefix addresses this server, not the source; every response names the
actual publisher in its source field.
Architecture decision: C (dump-first)
Verified live on 2026-08-05, full write-up in
PROBE_REPORT_UVG.md.
The source has no API. A link scan across every data page returned 165 PDFs
and zero files with .csv, .xlsx or .json. opendata.swiss does not list the
source at all (count=0 for six of seven search terms), and the BFS dam-api
silently ignores its filter parameters. What remains is machine-readable in
practice but not by design:
Access | Format | Refresh |
| HTML table, 5 years, Switzerland-wide | annually |
| annual edition, tables 1.2 and 2.4 by NOGA | annually, June |
| ten-year series per NOGA division | annually, January |
PDFs are cached for 24 h and fetched with 2s/4s/8s backoff.
What every response tells you
source_freshness.data_year— the data year, not the edition year. The 2026 edition reports 2024; that two-year lag is stated, not buried.totals_check— parsed rows are summed and compared against the total printed in the same publication. A broken layout shows up here instead of becoming a plausible wrong number.significant— the source marks statistically significant year-on-year changes with an asterisk. That flag is preserved per data point, so a change is only reported as significant where the source says so.
Installation
Claude Desktop (stdio)
Add to claude_desktop_config.json:
{
"mcpServers": {
"seco-labor": {
"command": "uvx",
"args": ["seco-labor-mcp"]
}
}
}Cloud / SSE
pip install seco-labor-mcp
MCP_TRANSPORT=sse PORT=8000 seco-labor-mcpThe SSE server binds to 127.0.0.1 (loopback) by default to prevent
NeighborJack on shared networks. For container deployments where you actually
need to accept traffic from outside the container, set HOST=0.0.0.0
explicitly — ideally in your Dockerfile / orchestrator config, and only behind
an upstream proxy or firewall:
HOST=0.0.0.0 MCP_TRANSPORT=sse PORT=8000 seco-labor-mcp # container onlyDevelopment
git clone https://github.com/malkreide/seco-labor-mcp.git
cd seco-labor-mcp
pip install -e ".[dev]"
pytest tests/ -m "not live" -vUsage Examples
Search for youth unemployment data
Tool: seco_search_datasets
Input: { "query": "Jugendarbeitslosigkeit Alter", "limit": 5 }Get cantonal unemployment for Zürich
Tool: seco_get_unemployment_overview
Input: { "canton": "ZH", "response_format": "markdown" }Get monthly report URL
Tool: seco_get_monthly_report_url
Input: { "year": 2026, "month": 2, "language": "de" }Key Concepts
Arbeitslose vs. Stellensuchende
Eselsbrücke: Arbeitslose ⊂ Stellensuchende — Arbeitslose sind eine Teilmenge.
Term | Definition | Dec 2025 |
Arbeitslose | RAV-registered, immediately available | ~149'000 (3.2%) |
Stellensuchende | All RAV-registered (incl. training programs) | ~233'900 |
Youth Unemployment Seasonality
July/August: Sharp increase (school leavers without placements)
September/October: Decline (apprenticeship starts)
The residual that remains after the autumn decline signals structural need for bridge programs (Brückenangebote)
Stellenmeldepflicht (since 2020)
Occupations with ≥5% unemployment rate must be reported to the RAV before posting publicly. The list changes annually. This is directly relevant for vocational counseling — these professions have highest availability for Swiss job seekers.
Portfolio Synergies
Server | Synergy |
| BFS population/employment data for deeper context |
| City of Zurich-level education and social data |
| Economic context (GDP, wages) for labor market interpretation |
| ALV (Arbeitslosenversicherung) legislative framework |
Known Limitations
amstat.arbeit.swisshas no public REST API (JavaScript SPA) → workaround via CKANOccupational/sectoral detail requires CSV download from SECO resources
Monthly press report URL patterns may vary for older reports
Cantonal sub-municipal data not available at this level
UVG figures come from PDF parsing — the layout was stable across the 2025 and 2026 editions, but a redesign can break it. The
totals_checkin every response is what makes such a break visible rather than silent.UVG data lags roughly two years (the 2026 edition reports 2024)
UVG branch detail follows NOGA 2008 and groups some divisions (
41 – 42,77, 79 – 82); there is no cantonal breakdown at this levelDetailed UVG data beyond the publications sits behind the SSUV closed user group and is out of scope for this no-auth server
Phase 2 roadmap:
Automatic CSV caching with 24h TTL
Direct XLSX parsing for cantonal breakdowns
Integration with
zh-education-mcpfor Schulamt-specific correlations
Data License
Two different licences apply — the code of this server is MIT either way, but the data is not covered by it.
SECO / AMSTAT data published on opendata.swiss is under Creative Commons CCZero (public domain). Source: Staatssekretariat für Wirtschaft (SECO) — seco.admin.ch
Unfallstatistik UVG data is not openly licensed. The publication states:
«Abdruck – ausser für kommerzielle Nutzung – mit Quellenangabe gestattet.» (Reproduction permitted, except for commercial use, with attribution.)
That is a non-commercial restriction with an attribution requirement. It belongs
to KSUV/SSUV and cannot be lifted by this repository's MIT licence: the MIT terms
cover the code, not the figures the code retrieves. If you use this server
commercially, the UVG tools are not covered — clarify directly with the
Sammelstelle (unfallstatistik@suva.ch). Every UVG response repeats this
restriction in its source field, because a README is not passed to the model.
Safety & Limits
Aspect | Details |
Access | Read-only ( |
Personal data | No personal data — all sources are aggregated, anonymous public statistics |
Rate limits | No enforced external limits; server caps queries at 20 results by default; 30 s HTTP timeout |
Authentication | No API keys required — opendata.swiss and arbeit.swiss are publicly accessible |
Licenses | SECO data under Creative Commons CCZero (public domain) |
Terms of Service | Subject to ToS of: opendata.swiss, SECO, arbeit.swiss |
GDPR / DSG | Fully compliant — no personal data transmitted or stored; all data is official public statistics |
MCP Protocol Version
The protocol version is negotiated at the initialize handshake by the SDK,
not chosen by this server. The revision it is built and audited against is
2025-11-25, which is LATEST_PROTOCOL_VERSION in the pinned mcp
release that fastmcp brings in.
tests/test_protocol_version.py holds three things against each other: this
line, that SDK constant, and the revision a real handshake against the server
object actually returns. An SDK bump that changes the revision therefore fails
CI instead of drifting silently.
The sister servers in this portfolio pin a pair of revisions — a handshake
ceiling and a modern one — because mcp 2.x serves two protocol eras over the
same server. fastmcp 3.x pins mcp 1.x, where mcp.types.version does not
exist and one revision is the whole story. test_das_sdk_kennt_hier_nur_eine_aera
is tied to the SDK rather than to this paragraph and fails the day an upgrade
brings the two-era constants in.
Contributing
See CONTRIBUTING.md for development guidelines.
Security
See SECURITY.md for the security posture and how to report a vulnerability.
License
Released under the MIT License — Copyright © 2026 Hayal Oezkan.
Author
Hayal Oezkan · github.com/malkreide
Installation
Run via uv's uvx — no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):
{
"mcpServers": {
"seco-labor-mcp": {
"command": "uvx",
"args": [
"seco-labor-mcp"
]
}
}
}Available Tools
9 toolsseco_get_datasetSECO-Datensatz-Details abrufenARead-onlyIdempotent
Fetch full details and download links for a specific SECO dataset.
Use this after seco_search_datasets to get complete metadata and all resource download URLs for a dataset.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - dataset_id (str): Dataset ID/slug from opendata.swiss - response_format (str): 'markdown' or 'json' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotentHint=true, readOnlyHint=true, and destructiveHint=false. The description adds that it returns 'full details' and 'download links', which are useful output traits. It does not contradict 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?
Two sentences with no redundancy. The first sentence clearly states the purpose, and the second provides usage guidance. Every sentence earns its place.
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?
With an output schema present, the description does not need to detail return values. It covers the tool's purpose and usage context sufficiently. Slight gap: what constitutes 'full details' could be elaborated, but the output schema handles that.
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 100%, so baseline is 3. The description adds value by clarifying that dataset_id must be obtained from seco_search_datasets first, which is beyond the schema description.
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 'Fetch' and the resource 'full details and download links for a specific SECO dataset'. It distinguishes this tool from siblings by specifying it should be used after seco_search_datasets, which retrieves a single dataset.
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 use this tool after seco_search_datasets, providing clear context for when it should be invoked. This guidance helps the agent decide between this and sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_get_job_seekersStellensuchende SchweizARead-only
Get job seeker (Stellensuchende) statistics from SECO/AMSTAT.
Stellensuchende is a broader category than unemployed (Arbeitslose) – it includes people in retraining programs, temporary employment programs, and other ALV programs. Important for understanding the full scope of labor market challenges.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - canton (Optional[str]): Canton code (e.g. 'ZH'). None = national. - response_format (str): 'markdown' or 'json' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so safety is covered. The description adds valuable context by explaining the inclusive nature of 'Stellensuchende', which helps agents understand what the data represents.
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?
Two short, focused sentences: the first states the core function, the second provides essential context. No unnecessary words or repetition.
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 a full output schema and high schema coverage, the description adequately explains the tool's context. Minor gap: no explicit mention of when not to use this tool over siblings.
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 100% with clear descriptions for both parameters (canton and response_format). The description does not add parameter-specific details, which is acceptable when schema is thorough.
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?
Clearly states 'Get job seeker statistics' and distinguishes 'Stellensuchende' from 'unemployed', making the tool's purpose distinct from sibling tools like seco_get_unemployment_overview.
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 use for understanding broader labor market challenges, but does not explicitly state when to avoid or list alternatives. The context signal of sibling tools provides indirect differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_get_monthly_report_urlSECO Monatsbericht-URL generierenARead-onlyIdempotent
Generate and validate URL for SECO monthly labor market press report.
SECO publishes monthly press documentation 'Die Lage auf dem Arbeitsmarkt' as PDF. This tool constructs the URL for a specific month/year and verifies availability.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - year (int): Report year (e.g. 2025, 2026) - month (int): Report month (1-12) - language (str): 'de', 'fr', or 'it' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the safety profile is clear. The description adds that the tool also verifies availability (a behavioral trait beyond read-only URL generation), which provides useful context 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?
Two concise sentences followed by a short paragraph. The main purpose is front-loaded in the first sentence. Every sentence adds value with no fluff.
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 an output schema (not shown but indicated), the description sufficiently explains the tool's function. It covers the purpose, the construction logic, and the verification step, making it complete for an agent to understand when and how to invoke it.
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 100% description coverage with clear constraints (year range, month range, language pattern). The description adds the context that the tool constructs a URL for a specific month/year and verifies availability, going beyond the schema's parameter 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 generates and validates a URL for SECO's monthly labor market press report. It specifies the exact resource (monthly press report PDF URL) and verb (generate and validate), and is distinct from sibling tools that handle datasets or job seekers.
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 implies the tool is for constructing URLs for specific months/years and verifying availability, but it does not explicitly state when to use it versus sibling tools like seco_get_dataset or seco_get_unemployment_overview. No exclusionary guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_get_open_positionsOffene Stellen Schweiz (SECO)ARead-only
Get open job positions (Offene Stellen) statistics from SECO/AMSTAT.
Open positions data is a leading indicator for labor market demand – relevant for identifying which professions/sectors to emphasize in vocational guidance and which Lehrberufe are in high demand.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - response_format (str): 'markdown' or 'json' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. Description adds context about being a leading indicator, but no additional behavioral traits beyond that.
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?
Two sentences: first states function, second adds relevant context. No unnecessary 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 parameter set and presence of output schema, the description adequately covers what the tool does and its relevance.
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 100%, and description does not add new meaning to parameters. The single parameter 'response_format' is already described in schema.
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 'Get open job positions statistics from SECO/AMSTAT', specifying the verb and resource. It distinguishes from siblings like 'seco_get_job_seekers' and 'seco_get_unemployment_by_occupation'.
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?
Provides context for when to use the tool: for identifying professions/sectors in high demand for vocational guidance. While it doesn't explicitly exclude alternatives, the sibling tools cover different metrics.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_get_unemployment_by_occupationArbeitslosigkeit nach BerufsgruppeARead-only
Get unemployment statistics broken down by occupation/profession (Berufshauptgruppe).
This is the most directly relevant tool for Berufswahlberatung – it shows which professions have high unemployment rates, which sectors are declining, and which Lehrberufe lead to stable employment outcomes.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - response_format (str): 'markdown' for human-readable, 'json' for structured data. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false. The description adds beyond this by explaining what specific statistics it returns (high unemployment rates, declining sectors, stable outcomes). 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first directly states purpose, second adds context and use-case. No wasted words, every sentence earns its place.
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 low complexity (one parameter, output schema exists, annotations present), the description is complete enough. It explains the purpose and relevance adequately.
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 100% with both parameters documented. The description does not add additional parameter semantics beyond what the schema provides, so baseline score of 3 is appropriate.
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 'Get unemployment statistics broken down by occupation/profession'. It uses a specific verb and resource, and distinguishes itself from siblings by directly linking to Berufswahlberatung (career counseling) and listing specific insights it provides.
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 states that this tool is 'the most directly relevant tool for Berufswahlberatung' and gives examples of its use. It provides clear context but does not explicitly state when not to use it or provide alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_get_unemployment_overviewAktuelle Arbeitslosigkeit SchweizARead-only
Get the latest Swiss unemployment statistics from SECO/AMSTAT.
Fetches current unemployment data including national totals, rates, year-over-year comparisons, and optionally cantonal breakdowns. Data is sourced from SECO's published datasets on opendata.swiss.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - canton (Optional[str]): Canton code (e.g. 'ZH'). None = national. - year (Optional[int]): Filter year. None = latest available. - response_format (str): 'markdown' or 'json' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds value by specifying the data source (SECO AMSTAT via opendata.swiss) and the scope of data (latest, year-over-year, cantonal), which enriches the agent's understanding beyond the 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: the first announces the purpose, the second details the data content and source. No wasted words, and critical information 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 the parameter count, full schema coverage, and presence of an output schema, the description adequately covers what the tool does and returns. The scope and data source are clear, and sibling tools handle other unemployment facets, leaving no 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 coverage is 100%, so baseline is 3. The description adds meaning by explaining how the 'canton' parameter affects the output (national vs. cantonal) and describing the content (rates, comparisons). This goes beyond the schema's brief 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 fetches the latest Swiss unemployment statistics, specifying it includes national totals, rates, year-over-year comparisons, and optionally cantonal breakdowns. This distinguishes it from siblings like seco_get_job_seekers or seco_get_unemployment_by_occupation, which focus on different aspects.
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 implies when to use this tool (for overall unemployment stats) but does not explicitly exclude other cases or mention alternatives. With sibling tools listed, the context provides some guidance, but no direct 'when not to use' or comparison to siblings is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_get_youth_unemploymentJugendarbeitslosigkeit SchweizARead-only
Get youth unemployment data (15–24 year olds) from SECO/AMSTAT.
Especially relevant for educational planning, vocational guidance (Berufswahlberatung), and apprenticeship market monitoring. Shows trends in youth employment to inform school and career counseling.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - canton (Optional[str]): Canton code (e.g. 'ZH'). None = national. - response_format (str): 'markdown' or 'json' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, so the description contributes additional context about the age group (15-24) and data source. It does not contradict annotations. However, it could be more transparent about data limitations, update frequency, or seasonality effects.
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 moderately concise, with three sentences covering purpose and use cases. It uses both German and English, which is acceptable but slightly redundant. The core action is stated in the first sentence, and the rest provides relevant context. It could be trimmed to be more 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 the presence of an output schema and comprehensive annotations, the description provides sufficient context for educational planning and career counseling applications. It adds use-case detail beyond what structured fields provide. However, it could mention that data is likely aggregated over time and note any potential missing values or data freshness.
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 100%, with both parameters fully described in the input schema. The description adds minimal new semantic detail beyond the schema; it mentions 'canton' and 'response_format' implicitly but provides no additional constraints or examples. Baseline 3 is appropriate given high 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 that the tool retrieves youth unemployment data (ages 15-24) from SECO/AMSTAT, specifically for educational planning and career guidance. It is specific about the resource (youth unemployment data) and the source, but could better differentiate from sibling tools like seco_get_unemployment_overview which may cover all ages.
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 implies usage for educational planning and vocational guidance, but lacks explicit guidance on when to use this tool versus siblings such as seco_get_unemployment_overview or seco_get_job_seekers. No alternative tools are mentioned, and there are no conditions provided for when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_list_cantonsSchweizer Kantone – Codes und NamenARead-onlyIdempotent
List all Swiss canton codes and their names.
Utility tool to look up canton codes needed for other seco_* tools. Returns all 26 cantons with their 2-letter codes and full names.
Returns: str: Markdown table of canton codes and names.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint, idempotentHint. The description adds that it returns a Markdown table with all 26 cantons, which is consistent and provides no surprises.
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 brief (3 sentences) and front-loaded with the main action. Every sentence adds value: what, why, and return format.
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, rich annotations, and output schema (implied as Markdown table), the description fully covers what the agent needs to know. No 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?
No parameters exist, so schema coverage is 100%. The description adds value by specifying the exact output format (Markdown table) and the count (26 cantons). Baseline 4 is appropriate.
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 all Swiss canton codes and their names.' This is a specific verb+resource combination. It distinguishes itself from sibling tools like seco_get_dataset which query data, not codes.
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 'Utility tool to look up canton codes needed for other seco_* tools.' This tells the agent when to use it (to get codes for other tools) and implies it's not for querying data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
seco_search_datasetsSECO-Datensätze suchenARead-onlyIdempotent
Search SECO labor market datasets on opendata.swiss CKAN.
Searches the Swiss Open Government Data portal for datasets published by SECO (Staatssekretariat für Wirtschaft). Returns dataset titles, IDs, and available resource download links.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes | Contains: - query (str): Search terms (German/English) - limit (int): Max results (1-20, default 10) - response_format (str): 'markdown' or 'json' |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the tool as read-only, idempotent, and non-destructive. The description adds that it returns dataset titles, IDs, and download links, which aligns with and complements 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 two sentences, front-loaded with the main purpose, and no redundant information. Every sentence adds value.
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?
With one required parameter, full schema coverage, and an output schema, the description adequately covers what the tool returns. It does not mention pagination but the limit parameter addresses that implicitly.
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 100%, so the baseline is 3. The description adds little extra beyond the schema; it does not elaborate on query language or examples already in the schema.
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 ('Search'), the specific resource ('SECO labor market datasets'), and the platform ('opendata.swiss CKAN'). It distinguishes itself from sibling getter tools by being the only search tool.
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 implies usage context as a search tool versus specific dataset retrieval, but lacks explicit guidance on when to choose this tool over siblings or what alternatives exist.
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.
9 tool updates
v0.3.0- First observed
seco_get_dataset - First observed
seco_get_job_seekers - First observed
seco_get_monthly_report_url - First observed
seco_get_open_positions - First observed
seco_get_unemployment_by_occupation - First observed
seco_get_unemployment_overview - First observed
seco_get_youth_unemployment - First observed
seco_list_cantons - First observed
seco_search_datasets
TDQS
Scored across 9 tools
Each tool has a clearly distinct purpose: unemployment overview, by occupation, youth, job seekers, open positions, dataset search/retrieval, monthly report URL, and canton lookup. Descriptions are detailed and avoid overlap.
All tools follow a consistent 'seco_verb_noun' pattern in snake_case (e.g., seco_get_unemployment_overview, seco_list_cantons). The single use of 'list' instead of 'get' is a minor variation but still fits the pattern.
With 9 tools, the set is well-scoped for a labor market statistics server. Each tool covers a necessary operation without redundancy, making the surface manageable for agents.
Covers core SECO labor market data: unemployment (overview, by occupation, youth), job seekers, open positions, dataset search, monthly report, and canton codes. Minor gaps exist (e.g., unemployment by canton is only optionally available in overview, no historical trends), but overall sufficient for vocational guidance use case.
Maintenance
Related MCP Connectors
Search and query 1,500+ OECD statistical datasets via SDMX. Keyless.
Swiss federal law (Fedlex) and political data (LINDAS) for agents, every answer with sources
Query official statistics of Catalonia (Idescat): tables, metadata and JSON-stat data via MCP.
opendata.swiss MCP — Switzerland's federal open-data portal (CKAN catalogue).
Related MCP Servers
- AlicenseAqualityAmaintenanceProvides AI-native access to Swiss Federal Statistical Office datasets through 9 tools for querying education, population, and cross-cantonal comparisons without authentication.152MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying Germany's official statistics from Destatis GENESIS-Online through natural language or direct tool calls.5 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables querying Swiss public transport (trains, buses, trams, boats) for stations, connections, and station boards via the opendata.ch API.-
- FlicenseAqualityCmaintenanceEnables LLMs to query structured statistical data from the Swiss Federal Archives' Linked Data platform (LINDAS) by translating natural language questions into SPARQL queries against RDF data cubes.8-