sns-portugal-mcp
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., "@sns-portugal-mcpHow many emergency visits did Santa Maria have last month, by triage colour?"
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.
sns-portugal-mcp
MCP server for official open-data statistics about Portugal's national health service (SNS), so Claude (or any MCP client) can answer "how busy is the emergency department at Santa Maria?", "how many people are waiting for surgery in the Norte region?" or "which SNS hospitals are near me?".
Read-only, no key, no account. It uses only public open data. Not affiliated with the SNS, SPMS or the Portuguese Ministry of Health.
Statistics, not the live queue. The figures are official monthly statistics; the newest month is usually 2-3 months old and provisional. This server does not show live emergency-room waiting times. For those, see tempos.min-saude.pt.
Not medical advice. In an emergency call 112. For health advice call SNS 24 on 808 24 24 24.
Tools
find_institutions
Finds SNS hospitals and local health units (ULS) by name, or the nearest ones to a coordinate. Each result says whether the place reports emergency, consultation and surgery data, and gives stats_entity: the name the statistics use for it. Statistics are published per ULS or hospital group, not per building.
Parameters: query (name, accent-insensitive), lat / lon (sort by distance), emergency_only, limit.
emergency_stats
Emergency-department visits per month, by type (general, paediatric, obstetric, psychiatric) and by Manchester triage colour (red, orange, yellow, green, blue, white, not triaged), with each colour's share of the month. Covers one institution, one region, or the whole country.
Parameters: institution, region (Norte | Centro | LVT | Alentejo | Algarve), period ("YYYY-MM", latest month to include), months (default 6).
surgery_wait_stats
Surgery access per month:
the surgical waiting list (LIC) at month end;
the % of waiting patients still within the legal maximum guaranteed time (TMRG);
the mean days from hospital admission to the operation (scheduled inpatient surgery);
surgeries performed: scheduled (inpatient and day surgery) and urgent.
Same parameters as emergency_stats. The open data has no breakdown by specialty.
consultation_wait_stats
Hospital outpatient consultations per month (first and follow-up), plus the % of first specialist consultations (referred by a family doctor) held within the TMRG. Same parameters as above.
search_datasets
Searches the 149 datasets of the SNS Transparency portal by keyword. Titles are in Portuguese, so Portuguese keywords work best: "ocupação", "partos", "rastreios", "SNS 24", "INEM". Returns each dataset's id, description and field names.
query_dataset
Runs an ODSQL query (where, select, group_by, order_by, limit, offset) on any portal dataset. Use it for anything the tools above don't cover.
Year-to-date values
Most hospital-activity datasets publish year-to-date cumulative values, so the December figure is the annual total. The curated tools return both the year-to-date value and a derived in_month value (this month minus the previous one). If you use query_dataset directly, do that subtraction yourself.
Related MCP server: mcp-cnes
Install
Requires Python 3.10+.
git clone https://github.com/ThiagoJacobLannes/sns-portugal-mcp
cd sns-portugal-mcp
python -m pip install -e .On Windows, if you keep code in a cloud-synced folder (Google Drive, OneDrive), create the virtual environment outside it. Sync clients drop desktop.ini files into folders, which can crash packages on startup.
Add to Claude Code
claude mcp add sns-portugal -- python -m sns_portugal_mcp.serverAdd to Claude Desktop
Merge claude_desktop_config.snippet.json into your Claude Desktop claude_desktop_config.json, then restart Claude Desktop:
{
"mcpServers": {
"sns-portugal": {
"command": "python",
"args": ["-m", "sns_portugal_mcp.server"]
}
}
}Data sources
Source | What it gives | Access | Licence / terms |
149 datasets of monthly SNS statistics, published by the SNS Executive Direction (DE-SNS) | Open, no key | No licence is set in any dataset's metadata (checked 2026-10-31). The portal's terms allow reuse under Portuguese public-sector-information law (Lei n.º 26/2016): cite the source, keep the data's integrity and context, and flag any changes you make. Some of the same datasets are mirrored on dados.gov.pt; there, some copies are marked CC-BY and others "not specified". | |
List of hospitals and ULS with coordinates and which data each reports | Public static file, no key | No licence stated. |
Datasets used by the curated tools:
Tool | Datasets |
|
|
|
|
|
|
Data derived from these sources keeps the source's terms. The code in this repository is MIT-licensed.
What this server does not do. It does not call tempos.min-saude.pt/api/*: that API needs a key embedded in the site's own web app, and this server does not use other people's keys. It also does not scrape the live waiting-time report (an embedded Power BI report).
How it works
The server calls the portal's public Explore API with httpx and aggregates in the query itself (group_by tempo, sum(...)), so regional and national totals are computed on the server side. Hospital names are matched without regard to accents. A hospital such as "Hospital de Faro" is mapped to the ULS it reports under ("ULS do Algarve") using the institution list. The dataset catalog, the institution list and the institution names are cached in memory for 6 hours. If an upstream call fails or a query is malformed, the tool returns a clear {"error": ...} and does not guess.
Environment overrides (optional): SNS_ODS_BASE_URL, SNS_INSTITUTIONS_URL.
License
MIT
Available Tools
6 toolsconsultation_wait_statsA
Hospital outpatient consultations per month and the % of FIRST specialist consultations (referred by a family doctor via CTH/SIGA) held within the guaranteed maximum time (TMRG).
Use for "how long is the wait for a first hospital appointment at X?", "is hospital Y on time with first consultations?", "how many consultations did the Centro region do?". Official monthly statistics (latest month usually 2-3 months back, provisional); there is no breakdown by specialty in the open data.
Per period (latest first): consultations_in_month / _year_to_date (total, first, subsequent) and first_consultations_within_max_time_pct for the month and year-to-date.
Args: institution: Hospital or ULS name; mapped to its ULS. region: Norte | Centro | LVT (Lisboa) | Alentejo | Algarve. Ignored if institution is given. period: Latest month to include, "YYYY-MM" (default: newest available). months: How many months back (default 6, max 24).
| Name | Required | Description | Default |
|---|---|---|---|
| months | No | ||
| period | No | ||
| region | No | ||
| institution | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses data provenance and staleness ('official monthly statistics, latest month usually 2-3 months back, provisional'), aggregation limits, and the institution-to-ULS remapping side effect of the institution argument. It does not explicitly state read-only/safe semantics or pagination/size limits, which is the remaining gap for a zero-annotation tool.
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?
Purpose and metric come first, then usage triggers, caveats, and an Args block — a sensible front-loaded order with no filler sentences. It is somewhat dense with unexplained domain acronyms (CTH/SIGA, TMRG) and the terse return-field notation in the middle paragraph is compact to the point of being cryptic.
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?
An output schema exists, yet the description still sketches the returned shape (consultations_in_month / _year_to_date broken out by total, first, subsequent, plus the within-max-time percentage) and adds the data-freshness caveat an agent needs to interpret it. Nothing needed to call this correctly is missing.
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, and it fully does: institution is described with its ULS mapping behavior, region with its five accepted values and the explicit 'ignored if institution is given' rule, period with its YYYY-MM format and default, and months with its default and max of 24.
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 opening sentence names the specific resource (hospital outpatient consultations per month) and the key derived metric (% of first consultations within the guaranteed maximum time). It is clearly distinct from the sibling wait/emergency tools by resource and metric, so an agent can disambiguate without opening the schema.
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?
It supplies concrete trigger questions ('how long is the wait for a first hospital appointment at X?') and states a real limitation (no breakdown by specialty in the open data) plus the institution-vs-region precedence rule. Defaults and the -2/-3 month latency expectation are given, leaving little to infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
emergency_statsA
Emergency-department (urgência) visits per month: by type and by Manchester triage colour.
Use for "how busy is the ER at X?", "how many emergency visits in the Algarve last month?", "what share of ER visits are green/blue (non-urgent)?". OFFICIAL MONTHLY STATISTICS ONLY — not the live queue (the latest month is usually 2-3 months back and provisional). For live waiting times send the user to https://tempos.min-saude.pt. Not medical advice: in an emergency call 112; SNS 24 (808 24 24 24) for advice.
Scope: one institution, one region, or (neither) all of mainland Portugal's SNS hospitals.
Per period (latest first): visits_in_month and visits_year_to_date by type (general, paediatric, obstetric, psychiatric, total), triage_in_month by colour (red = immediate, orange = very urgent, yellow = urgent, green = less urgent, blue = non-urgent, white = not clinical / other) and triage_share_in_month_pct.
Args:
institution: Hospital or ULS name, accent-insensitive ("Santa Maria", "São João",
"Hospital de Faro"). A hospital is mapped to its ULS; check scope.
region: Norte | Centro | LVT (Lisboa) | Alentejo | Algarve. Ignored if institution is given.
period: Latest month to include, "YYYY-MM" (default: newest available).
months: How many months back to return (default 6, max 24).
| Name | Required | Description | Default |
|---|---|---|---|
| months | No | ||
| period | No | ||
| region | No | ||
| institution | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden and does so: it warns the latest month is usually 2-3 months back and provisional, explains the institution→ULS mapping and the `scope` field to verify it, and documents default/max behaviour for period and months. Those are the traits that actually change how an agent interprets and presents results.
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?
Front-loaded with the core purpose and example queries, then scope, then args — a good ordering with no filler sentences. It is on the long side, and the emergency-contacts disclaimer (112 / SNS 24) is an emergency-response message that contributes little to tool selection or invocation.
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 0-required-param statistics tool with an output schema, the definition covers everything that remains open: geographic scope semantics, time-window semantics, freshness caveats, and what the returned fields mean (visit types, triage colours and their clinical meanings, share percentages). Nothing needed to call it correctly is missing.
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 the description fully compensates: it gives the accepted region vocabulary (Norte | Centro | LVT (Lisboa) | Alentejo | Algarve), states region is ignored when institution is supplied, defines period as 'YYYY-MM' with newest-available default, and gives months default 6 / max 24 plus accent-insensitive institution examples. This exceeds what the bare schema conveys.
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?
States a specific resource and breakdown precisely: monthly emergency-department visits by visit type and by Manchester triage colour. It also contrasts itself with the nearest confusable thing (live queue / waiting-time tools) and with the sibling wait-stats family, so the agent can pick it without opening the schema.
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?
Gives concrete trigger phrasings ('how busy is the ER at X?', 'how many emergency visits in the Algarve last month?'), states an explicit when-not ('OFFICIAL MONTHLY STATISTICS ONLY — not the live queue'), and routes the out-of-scope case to https://tempos.min-saude.pt. The exclusion plus redirect is exactly what an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_institutionsA
Find SNS hospitals / local health units (ULS) by name, or the nearest ones to a coordinate.
Use this first when the user names a hospital or a place ("hospitals near Lisbon",
"is there an emergency department near 38.72,-9.14?"), then pass stats_entity to
emergency_stats / surgery_wait_stats / consultation_wait_stats.
Each result: name, its parent ULS, coordinates, distance_km (when lat/lon given), whether
it reports emergency / consultation / surgery data on tempos.min-saude.pt, and
stats_entity — the name under which the official statistics report it (statistics are
per ULS / hospital group, not per building). This list does NOT contain live waiting times;
for live emergency waits send the user to https://tempos.min-saude.pt.
Args:
query: Part of the name, accent-insensitive, e.g. "Santa Maria", "Faro", "ULS Algarve".
lat, lon: Sort by distance from this point (WGS84), e.g. Lisbon 38.7223, -9.1393.
Without query, umbrella ULS entries are skipped (they duplicate a hospital's location).
emergency_only: Only places that report emergency-department data.
limit: Max results (default 10, max 50).
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | ||
| lon | No | ||
| limit | No | ||
| query | No | ||
| emergency_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does so: it discloses the exact result fields, the caveat that statistics are per ULS/group rather than per building, the non-obvious rule that umbrella ULS entries are skipped when only lat/lon is given, and that live wait times are out of scope.
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?
Front-loads the purpose and the when-to-use rule before the result shape and an Args block, so an agent can stop reading early. Slightly long, and the result-shape sentence overlaps with the existing output schema, but nothing is wasted filler.
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?
Covers purpose, ordering relative to siblings, all parameters, result contents, and the important domain caveat that stats attach to ULS/groups. An output schema exists, so the brief return summary is bonus rather than a gap.
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, and it does for all five parameters: query is accent-insensitive with examples, lat/lon are WGS84 with a worked example and a behavioral side effect, emergency_only is defined as 'only places that report emergency-department data', and limit gives default and max.
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?
States a specific verb and resource ('Find SNS hospitals / local health units (ULS)') with both lookup modes — by name or by proximity to a coordinate. It is clearly distinguishable from the sibling *_stats tools, which it explicitly routes to rather than duplicating.
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?
Gives explicit sequencing: 'Use this first when the user names a hospital or a place', with two concrete example queries, then instructs passing `stats_entity` into emergency_stats / surgery_wait_stats / consultation_wait_stats. It also states an exclusion — no live waiting times, send the user to the external URL instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_datasetA
Run an ODSQL query on any SNS Transparency portal dataset (Opendatasoft Explore API v2.1).
Use after search_datasets for anything the curated tools don't cover. Clauses are ODSQL:
where:
instituicao like "santa maria" and tempo >= date'2026-01-01'(likeis a case- and accent-insensitive "contains"; dates use date'YYYY-MM-DD')select:
tempo, instituicao, total_urgenciasor aggregatessum(total_urgencias) as totalgroup_by:
regiaoortempo(combine with aggregates in select)order_by:
tempo descMost hospital-activity datasets (fieldtempo, monthly) store YEAR-TO-DATE CUMULATIVE values: December is the annual total; a single month = this month minus the previous one. Many datasets have aregiaoand aninstituicao(orentidade) field. Official statistics, not live data.
Args: dataset_id: e.g. "ocupacao-do-internamento" (from search_datasets). where, select, group_by, order_by: ODSQL clauses (optional). limit: Rows to return (default 20, max 100). offset: Skip rows, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| where | No | ||
| offset | No | ||
| select | No | ||
| group_by | No | ||
| order_by | No | ||
| dataset_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the whole burden and does substantial work: it discloses the YTD-cumulative semantics of the `tempo` field (December = annual total, single month = delta), which is a genuine data-shape trap an agent would otherwise fall into. It also states limits (default 20, max 100) and that this is official statistics, not live data. It stops short of stating read-only/safety or error behavior explicitly, keeping it just below a 5.
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?
Front-loaded with purpose and use-condition, then clause reference, then args — good ordering with no repetition of the schema. The clause examples are long but each demonstrates syntax the schema cannot express; the leftover argparse-style 'Args:' block is mildly redundant given the schema fields exist.
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?
Output schema exists, so return-format explanation is unnecessary; the description instead supplies what the schema can't — query language semantics, dataset discovery path, field conventions (`tempo`, `regiao`, `instituicao`/`entidade`), and the cumulative-value caveat. Nothing essential for a correct call is missing.
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 entirely, and it does: each ODSQL clause gets a concrete example (`instituicao like "santa maria" and tempo >= date'2026-01-01'`) including the non-obvious case/accent-insensitive `like` and date literal syntax, plus aggregate form for select. limit/offset/dataset_id semantics and paging purpose are all spelled out.
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?
States a specific verb and resource — 'Run an ODSQL query on any SNS Transparency portal dataset' — and names the API behind it (Opendatasoft Explore API v2.1). It also distinguishes itself from the curated siblings ('anything the curated tools don't cover'), so an agent can route correctly without opening other schemas.
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?
'Use after search_datasets for anything the curated tools don't cover' gives an explicit precondition plus the alternative tools it supersedes. The dataset_id arg reinforces the ordering by pointing back to search_datasets as the discovery step.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_datasetsA
Search the ~150 datasets of the SNS Transparency portal (titles and descriptions are in Portuguese).
Use when the curated tools don't cover the question — e.g. hospital bed occupancy ("ocupação"), births/caesareans ("partos"), INEM pre-hospital calls, SNS 24 calls, family doctor coverage ("médico de família", "inscritos"), medicines spending, staff ("trabalhadores"), cancer screening ("rastreios"). Then call query_dataset with the dataset_id and the field names returned here. Portuguese keywords work best; matching is accent-insensitive.
Args: query: Keywords, e.g. "ocupação internamento", "partos", "urgência". Empty = list all (id + title). limit: Max results (default 10, max 50; ignored when listing all).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses Portuguese-language content, accent-insensitive matching, empty-query behavior, and that limit is ignored when listing all datasets. It could still state explicitly that this is a read-only search with no side effects, but the behavior is otherwise well explained.
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 front-loaded with purpose and usage, then gives concrete example keywords and parameter semantics. Although longer than a minimal description, every section earns its place because the schema itself has no parameter descriptions.
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?
An output schema exists, so return-value details are not required. The description still explains the search scope, language behavior, empty-query listing behavior, limit semantics, and the follow-up query_dataset call, making it complete for an agent to use correctly.
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, and it does: query is explained as Portuguese keywords with examples and an empty value listing all datasets; limit is explained with default 10, max 50, and ignored-when-listing-all behavior. This adds substantial meaning beyond the bare 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?
States a specific verb and resource: search the SNS Transparency portal's ~150 datasets. It clearly distinguishes itself from curated siblings by saying to use it when curated tools do not cover the question, and it names query_dataset as the follow-up step.
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 defines when to use this tool versus the curated alternatives: when the curated tools do not cover the question, with concrete example domains such as hospital bed occupancy, births, INEM calls, and medicines spending. It also states the next action: call query_dataset with the returned dataset_id and field names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
surgery_wait_statsA
Surgery access indicators per month: surgical waiting list, % within the guaranteed maximum time, mean days from admission to surgery, and surgeries performed.
Use for "how long is the wait for surgery at X?", "how many people are on the surgery list in the Norte region?", "how many operations did hospital Y do?". Official monthly statistics (latest month usually 2-3 months back, provisional). The open data has NO breakdown by specialty or procedure — say so if asked for one.
Per period (latest first):
waiting_list: patients on the surgical waiting list (LIC) at month end, how many are still within the legal maximum guaranteed response time (TMRG, 180 days for normal priority since 2018) and the % within it.
mean_days_before_surgery_in_month / _year_to_date: average days between hospital admission and the operation for scheduled inpatient surgery (this is NOT the time on the waiting list).
surgeries_in_month / surgeries_year_to_date: scheduled (= inpatient + day surgery) and urgent.
Args: institution: Hospital or ULS name ("Santa Maria", "Coimbra", "IPO Porto"); mapped to its ULS. region: Norte | Centro | LVT (Lisboa) | Alentejo | Algarve. Ignored if institution is given. period: Latest month to include, "YYYY-MM" (default: newest available). months: How many months back (default 6, max 24).
| Name | Required | Description | Default |
|---|---|---|---|
| months | No | ||
| period | No | ||
| region | No | ||
| institution | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does well: it discloses that the data are official monthly statistics, usually 2-3 months behind, provisional, and lacking specialty/procedure breakdown. It also defines key metrics such as TMRG and clarifies that mean days before surgery is not waiting-list time. It does not explicitly state read-only/access constraints, but the statistical nature makes that largely inferable.
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 long but well-structured and front-loaded: purpose and use cases first, then metric definitions, then argument semantics. Given the complexity of the indicators and the lack of schema descriptions, every section 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?
An output schema exists, so return values need not be explained in the description. The description covers data vintage, provisional status, metric definitions, limitations, and all four parameters, leaving an agent with enough context to call the tool correctly.
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, and it does: institution examples and ULS mapping, region enum values with the rule that region is ignored when institution is given, period format/default, and months default/max are all documented. This adds substantial meaning beyond the bare schema types and defaults.
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 names a specific resource and metric set: monthly surgery access indicators including waiting list, TMRG compliance, mean days to surgery, and surgeries performed. It is clearly distinguishable from siblings such as emergency_stats and consultation_wait_stats by its surgery-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?
It gives explicit example questions ("how long is the wait for surgery at X?", "how many operations did hospital Y do?") and a clear limitation about no specialty/procedure breakdown. It would be stronger if it explicitly named alternatives such as consultation_wait_stats for consultation waits or find_institutions for resolving institution names.
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.
6 tool updates
v0.1.0- First observed
consultation_wait_stats - First observed
emergency_stats - First observed
find_institutions - First observed
query_dataset - First observed
search_datasets - First observed
surgery_wait_stats
TDQS
Scored across 6 tools
Each tool has a clearly distinct role: find_institutions resolves names/places, the three *_stats tools cover separate official-statistics domains, and search_datasets/query_dataset form a clear metadata-search-then-query pattern. The descriptions explicitly guide agents to start with curated tools and fall back to generic dataset tools only when needed, so overlap is minimal.
All names use snake_case and are readable, but the set mixes two patterns: verb_noun action tools (find_institutions, search_datasets, query_dataset) and noun_stats statistics tools (emergency_stats, surgery_wait_stats, consultation_wait_stats). The conventions are internally predictable within each group, with only minor deviation from a single uniform pattern.
Six tools is well-scoped for an official SNS statistics server: one resolver, three curated statistics endpoints, and two generic dataset tools. None of the tools appear redundant, and the count is far from thin or unwieldy.
The surface covers institution lookup, the main curated hospital-activity domains (emergency, surgery, consultations), and arbitrary access to the remaining SNS Transparency datasets via search_datasets and query_dataset. Live waiting times are explicitly out of scope and users are directed to the official website, so there are no obvious dead ends for the stated purpose.
Maintenance
Related MCP Connectors
Official public data as MCP tools: EU/US tenders, NPI Registry, UK Companies House, Mexico data.
Experimental MCP providing read-only population statistics from Eurostat.
Keyless MCP access to official Luxembourg public data: laws, statistics, mobility, and more.
Statistics Denmark (Danmarks Statistik / Statbank) MCP. Keyless REST API: https://api.statbank.dk/v1
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceMCP server for accessing BPstat (Banco de Portugal) statistics API without API keys. Enables querying Portuguese central bank data through natural language.432 npmMIT
- AlicenseAqualityAmaintenanceMCP server for loading and querying public data from the Brazilian National Registry of Health Establishments (CNES). It enables natural language searches for health facilities by municipality, CNES code, or state, along with statistics and data loading.6MIT
- AlicenseNot gradedqualityCmaintenanceEnables querying the Brazilian government's transparency portal (Portal da Transparência) to search official public spending and transparency data. Read-only access via natural language from any MCP client, with prepaid pay-per-query usage.MIT

cat.idescat/mcpofficial
AlicenseNot gradedqualityBmaintenanceEnables any MCP client to discover and query official Catalonia statistics through read-only tools and resources, including statistic catalogues, table metadata, filtered JSON-stat data, territorial breakdowns, and Markdown tables with source attribution.MIT