Skip to main content
Glama
unesco-mcp

unesco-mcp

by lpicci96

codecov PyPI Python

unesco-mcp

A Model Context Protocol (MCP) server for UNESCO Institute for Statistics (UIS) data. Bring the UIS Data Browser into any MCP-compatible client (Claude Desktop, Claude Code, Cursor, Windsurf, etc.).

What it does

This server connects AI assistants to the UIS API, enabling them to search indicators, retrieve data values, compare countries, and explore available breakdowns — all through natural conversation. Data is cached locally in SQLite for fast indicator discovery, while live API calls fetch the actual data values.

Related MCP server: OECD-Search

Available tools

Discovery

Tool

Description

list_themes

List all UNESCO data themes (education, science, culture, etc.)

list_disaggregation_types

List available data breakdowns (by sex, age, education level, etc.)

get_disaggregation_values

Get specific values for a breakdown type (e.g. "Male", "Female" for SEX)

search_indicators

Search indicators by text query and structured filters

count_indicators

Count indicators matching filters, with year range support

get_indicator_metadata

Get full definition, methodology, and data sources for an indicator

get_indicator_summary

Quick overview of multiple indicators from local cache

Geography

Tool

Description

search_geo_units

Search countries and regions by name or ISO3 code, with grouping disambiguation

Data retrieval

Tool

Description

get_latest_value

Get a single data point for an indicator and geography

get_time_series

Get the full time series for an indicator and geography

get_country_ranking

Rank countries by indicator value (top N / bottom N)

compare_geographies

Compare an indicator across up to 20 specific geographies

Utility

Tool

Description

server_status

Health check with server name and UTC timestamp

Installation

Run the server locally from the published Python package. This requires Python 3.10+ and uv.

Claude Code:

claude mcp add unesco-mcp -- uvx unesco-mcp

Claude Desktop — add to your config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):

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

Local (from source)

Use this path when developing locally or testing unreleased changes:

git clone https://github.com/lpicci96/unesco-mcp.git
cd unesco-mcp
uv sync
uv run unesco-mcp

For Claude Desktop, point the client at the checkout:

{
  "mcpServers": {
    "unesco-mcp": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/unesco-mcp", "unesco-mcp"]
    }
  }
}

Claude Code:

claude mcp add unesco-mcp -- uv run --directory /path/to/unesco-mcp unesco-mcp

Example usage

Once installed, you can ask your AI assistant things like:

  • "What is the primary completion rate in Kenya?"

  • "Compare literacy rates across East African countries"

  • "Which countries have the highest out-of-school rates?"

  • "What education indicators are available broken down by sex and wealth quintile?"

  • "Show me the trend in secondary enrollment for Brazil over the last 10 years"

Available Tools

13 tools
compare_geographiesA

Compare a UNESCO UIS indicator across a specific list of countries or regions.

Retrieves the indicator value for each supplied geo unit code and ranks them by value. Use this to directly compare a set of countries or regions you already know the codes for (e.g. from prior searches or elicitations).

Year handling:

  • strict_year=True (default): year must be provided; if a geography has no value in that year, it is reported in missing_codes (no fallback year used).

  • strict_year=False:

    • year provided: falls back to the nearest available year per geography.

    • year omitted: uses the most recent available year per geography (mixed years possible).

Args: indicator_code: The indicator code (e.g. "LR.AG15T99"). geo_unit_codes: List of geo unit codes to compare (max 20, e.g. ["KEN", "TZA", "UGA"]). Codes must already be known — use search_geo_units to find them. year: Optional. The year to compare. If omitted, the most recent available value for each geography is used only when strict_year=False. strict_year: If True, require an explicit year and disallow fallback years.

Returns: A dictionary with: - "indicator_code", "indicator_name": Indicator identity. - "comparison": [{rank, code, name, value, year, qualifier}, ...] sorted by value desc. - "missing_codes": Geo unit codes for which no data was found. - "note": Context (e.g. mixed years warning, missing codes).

Inputs: indicator_code (required), geo_unit_codes (required), year, strict_year. Returns: object

count_indicatorsA

Count UNESCO UIS indicators matching precise filter criteria.

Use this tool when the user wants to know how many indicators exist for a given combination of filters, including year coverage or update date constraints. Unlike search_indicators, this tool returns an exact count and accepts year range filters.

All provided filters are combined with AND logic. If no filters are provided, returns the total count of all indicators in the database.

Args: theme: Exact theme code (from list_themes). disaggregation_types: List of disaggregation type codes. Indicators must support ALL listed types. disaggregation_values: List of disaggregation value codes. Indicators must match ALL listed values. coverage_start_year: Only count indicators whose data begins by this year (i.e. timeLine_min <= year). coverage_end_year: Only count indicators whose data extends through this year (i.e. timeLine_max >= year). updated_since: ISO date string (e.g. "2024-01-01"). Only count indicators updated on or after this date.

Returns: A dictionary with: - "count": The exact number of indicators matching all provided filters. - "filters_applied": A summary of which filters were used.

Inputs: theme, disaggregation_types, disaggregation_values, coverage_start_year, +2 more. Returns: object

get_country_rankingA

Rank countries (not regions) by their value for a UNESCO UIS indicator.

Returns the top-N and bottom-N countries for a given indicator in a specific year. Uses dense ranking (tied countries share the same rank).

Year handling:

  • strict_year=True (default): year must be provided explicitly.

  • strict_year=False and year omitted: uses the year with the most country coverage.

Args: indicator_code: The indicator code (e.g. "LR.AG15T99"). year: Optional. The year to rank countries for. If omitted, the year with the most data points is used only when strict_year=False. top_n: Number of top-ranked countries to return (default 10, max 200). bottom_n: Number of bottom-ranked countries to return (default 10, max 200). strict_year: If True, require an explicit year to avoid implicit year selection.

Returns: A dictionary with: - "indicator_code", "indicator_name": Indicator identity. - "year_used": The year the ranking is based on. - "total_countries_with_data": Countries with non-null values that year. - "top": [{rank, code, name, value}, ...] — highest-value countries. - "bottom": [{rank, code, name, value}, ...] — lowest-value countries. - "note": Context (e.g. year selection rationale, overlap explanation).

Inputs: indicator_code (required), year, top_n, bottom_n, +1 more. Returns: object

get_disaggregation_valuesA

Get the available values for a specific disaggregation type.

Given a disaggregation type code (e.g. 'SEX', 'AGE', 'EDU_LEVEL'), return all possible values that indicators can be broken down by.

Args: type_code: The disaggregation type code (from list_disaggregation_types).

Returns: A dictionary with: - "type_code": The requested type code. - "type_name": The human-readable name of the disaggregation type. - "values": A list of dicts, each with 'code', 'name', and 'description'. - "count": The total number of values.

Inputs: type_code (required). Returns: object

get_indicator_metadataA

Get detailed metadata for a specific UNESCO UIS indicator.

Returns definitional and methodological information for an indicator, including its glossary definition, purpose, calculation method, data sources, and available disaggregations. Use this after finding indicator codes via search_indicators.

Args: indicator_code: The indicator code (e.g. "CR.1", "ROFST.1.cp").

Returns: A dictionary with: - "code": Indicator code. - "name": Full indicator name. - "theme": Theme code. - "last_update": Date and description of the most recent data release. - "data_availability": Time coverage (min/max year), total record count, and geographic unit types. - "definition": Glossary entry with definition, purpose, calculation method, data source, interpretation, and limitations (if available). - "disaggregations": List of available disaggregation breakdowns (code, name, type).

Inputs: indicator_code (required). Returns: object

get_indicator_summaryA

Get a lightweight summary for one or more UNESCO UIS indicators.

Returns key fields from the local database without making API calls. Much faster than get_indicator_metadata — use this when you need a quick overview of multiple indicators (e.g. after a search) rather than full definitional detail.

Use get_indicator_metadata when you need glossary definitions, methodology, or detailed disaggregation breakdowns for a single indicator.

Args: indicator_codes: List of indicator codes (1–10). Use codes from search_indicators results.

Returns: A dictionary with: - "indicators": List of summaries, each with code, name, theme, timeLine_min/max, totalRecordCount, geoUnitType, lastDataUpdate, and disaggregation_types (list of type names). - "returned": Number of indicators found. - "not_found": List of requested codes that were not in the database.

Inputs: indicator_codes (required). Returns: object

get_latest_valueA

Get the value of a UNESCO UIS indicator for a specific country or region.

Returns a single data point — either the most recent available value, or the value for a specific year. Use this for answering questions like: "What is the literacy rate in Kenya?" or "What was the completion rate in Sub-Saharan Africa in 2015?"

GEOGRAPHY RULES:

  • For countries: pass the ISO3 code directly (e.g. "KEN", "FRA").

  • For regions: ALWAYS call search_geo_units first — it will ask the user which grouping system to use. Regional names map to multiple codes with different country compositions; using the wrong one gives silently wrong data.

  • If omitted, the tool will interactively ask the user for the geography.

To find indicator codes, use search_indicators. Always show the user the year alongside the value, since data is not always available for the most recent years.

Args: indicator_code: The indicator code (e.g. "CR.1", "LR.AG15T99"). geo_unit_code: ISO3 code for countries, or a confirmed code from search_geo_units for regions. Omit to trigger interactive geography lookup. year: Optional. The specific year to retrieve. If omitted, returns the most recent available value. If no data exists for the requested year, returns the nearest available year instead, with a note.

Returns: A dictionary with: - "indicator_code": The indicator code. - "indicator_name": Full name of the indicator. - "geo_unit_code": The geo unit code. - "geo_unit_name": Human-readable geography name. - "year": The year of the returned value. - "value": The numeric data value. - "qualifier": Data quality flag if present (e.g. "<", "~"), else null. - "note": Context about the data point (e.g. year range, year substitution).

Inputs: indicator_code (required), geo_unit_code, year. Returns: object

get_time_seriesA

Get the full time series for a UNESCO UIS indicator for one country or region.

Returns all data points for the indicator × geography combination, optionally filtered to a year range. Ideal for trend analysis and time-series visualisation.

GEOGRAPHY RULES:

  • For countries: pass the ISO3 code directly (e.g. "KEN", "FRA").

  • For regions: ALWAYS call search_geo_units first — it will ask the user which grouping system to use. Regional names map to multiple codes with different country compositions; using the wrong one gives silently wrong data.

  • If omitted, the tool will interactively ask the user for the geography.

Args: indicator_code: The indicator code (e.g. "LR.AG15T99"). geo_unit_code: ISO3 code for countries, or a confirmed code from search_geo_units for regions. Omit to trigger interactive geography lookup. start_year: Optional. First year to include (inclusive). end_year: Optional. Last year to include (inclusive).

Returns: A dictionary with: - "indicator_code", "indicator_name": Indicator identity. - "geo_unit_code", "geo_unit_name": Geography identity. - "data_points": Chronological list of {year, value, qualifier}. - "summary": {total_data_points, min_value, max_value, latest_year, note}.

Inputs: indicator_code (required), geo_unit_code, start_year, end_year. Returns: object

list_disaggregation_typesA

Find all available disaggregation types for UNESCO UIS indicators.

Disaggregation types describe how indicator data can be broken down (e.g. by sex, age group, education level, wealth quintile, etc.).

Returns: A dictionary with: - "disaggregation_types": A list of dicts, each with 'type_code' and 'type_name'. - "count": The total number of disaggregation types. - "hint": Guidance on how to use the type codes.

Inputs: no named parameters. Returns: object

list_themesA

Find all available UNESCO data themes and basic information about them.

UIS themes are the highest-level topical groups used to organize indicators.

Returns: A dictionary with three keys: - "theme information": A list containing each theme code, name, last update date, description of the update, and the count of indicators in that theme. - "theme count": The total number of themes available. - "hint": A string providing guidance on how to use the theme codes for searching indicators

Inputs: no named parameters. Returns: object

search_geo_unitsA

Search for UNESCO UIS geographic units (countries and regions) by name or code.

Use this to find the geo unit code needed for get_latest_value. Accepts either a country/region name (e.g. "Kenya", "Sub-Saharan Africa") or an ISO3 code directly (e.g. "KEN", "ZWE"). When multiple grouping systems match a region (WB, SDG, UNICEF, etc.), the tool will elicit a choice from the user directly.

Args: query: Country or region name, or ISO3 code (e.g. "Kenya", "ZWE", "Sub-Saharan Africa"). type_filter: Optional. "NATIONAL" to show only countries, "REGIONAL" for aggregates only. region_group: Optional. Restrict to a specific grouping system (e.g. "WB", "SDG", "UNICEF").

Returns: A dictionary with: - "geo_units": List of matches, each with code, name, type, and region_group. - "count": Number of results returned. - "hint": Guidance on next steps.

Inputs: query (required), type_filter, region_group. Returns: object

search_indicatorsA

Search UNESCO UIS indicators by relevance using text and structured filters.

Use this tool to discover which indicators exist for a topic. Results are capped (default 20, max 50) and intended for interactive exploration. For counting indicators with precise year or date filters, use count_indicators.

Suggested workflow for complex queries:

  1. Call list_themes to find the theme code if the user mentions a thematic area.

  2. Call list_disaggregation_types and get_disaggregation_values to find codes for concepts like "sex", "primary education", "age group". Do not pass these as the query parameter — use the structured filter parameters instead.

  3. Pass discovered codes as structured filters. Only use query for name-based narrowing after applying structured filters.

All provided filters are combined with AND logic. At least one filter must be provided. Results default to 20. If more exist, suggest narrowing with additional filters rather than increasing the limit.

Args: query: Full-text search on indicator name (supports stemming, e.g. "completing" matches "completion"). Secondary refinement only — do not use for concepts that map to themes or disaggregations. theme: Exact theme code (from list_themes). disaggregation_types: List of disaggregation type codes (from list_disaggregation_types). Indicators must support ALL listed types. disaggregation_values: List of disaggregation value codes (from get_disaggregation_values). Indicators must match ALL listed values. limit: Maximum number of results to return (default 20, max 50). Prefer narrowing filters over increasing limit.

Returns: A dictionary with: - "indicators": List of matching indicators, each with: code, name, theme, timeLine_min, timeLine_max. - "query_matches": Number of indicators matched by this query. This is NOT the total count of all UNESCO indicators — it only reflects how many matched these specific filters. Some relevant indicators may be missing if the query is too narrow or the text search didn't capture them. - "returned": Number of indicators included in this response (may be less than query_matches if truncated). - "hint": Guidance on next steps.

Inputs: query, theme, disaggregation_types, disaggregation_values, +1 more. Returns: object

server_statusA

Return basic runtime metadata for smoke tests and client wiring.

Inputs: no named parameters. Returns: object

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A4.5/5.0

    Scored across 13 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: compare geographies, count indicators, get rankings, retrieve metadata/summary, get single value or time series, list themes/disaggregation types, and search geo units or indicators. No two tools overlap in functionality.

    Naming Consistency4/5

    Most tools follow the verb_noun pattern (e.g., compare_geographies, get_latest_value, list_themes). The only exception is server_status, which uses noun_noun. Overall, the naming is clear and predictable.

    Tool Count5/5

    With 13 tools, the set is well-scoped for covering UNESCO UIS data exploration and retrieval without being overwhelming. Each tool serves a specific, necessary function.

    Completeness5/5

    The tool surface covers the full lifecycle of data discovery (search, list, metadata) and retrieval (single value, time series, comparison, ranking). No obvious gaps for a read-only statistical API.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers