This is Our World in Data's MCP (Model Context Protocol) server providing access to charts, indicators, and data from Our World in Data. It's built using fastMCP and provides direct indicator access.
Tools:
search_indicator(query, limit?)- Search for OWID indicators by name or descriptionrun_sql(query, max_rows?)- Execute read-only SQL queries against the OWID public Datasette
Resources:
ind://{indicator_id}- Get indicator data and metadata for all entitiesind://{indicator_id}/{entity}- Get indicator data filtered for specific country/entity
Tools:
fetch_post(identifier, include_metadata?)- Fetch markdown content for posts by slug or Google Doc IDsearch_posts(query, limit?)- Search for posts by title or content
Functions:
make_algolia_request(query, limit)- Make requests to Algolia search APIcountry_name_to_iso3(name)- Convert country names to ISO-3 codes using OWID regions mappingrun_sql(query, max_rows)- Execute read-only SQL queries against the OWID public Datasettesmart_round(value)- Apply smart rounding to reduce context waste while preserving precision- Various data processing utilities for CSV conversion and metadata handling
# Activate virtual environment
source .venv/bin/activate
# Run the OWID MCP server
fastmcp run owid_mcp/server.py
# Or run with development options
python -m mcp.server.stdio owid_mcp.server:mcp# Search for GDP indicators
indicators = await search_indicator("GDP per capita", limit=5)
# Access indicator data via resource
indicator_data = await client.read_resource("ind://2118") # GDP per capita
# Get data for specific country
usa_data = await client.read_resource("ind://2118/USA")# Query the OWID database directly
results = await run_sql("SELECT id, name FROM variables WHERE name LIKE '%population%' LIMIT 10")# Fetch post by slug
post_content = await fetch_post_markdown("poverty")
# Search for posts about climate change
search_results = await search_posts("climate change", limit=5)The server uses a modular architecture:
server.py- Main FastMCP server that imports and combines modulesindicators.py- Direct indicator search and data accesscharts.py- Chart search and data retrieval functionalityposts.py- Post markdown content retrieval and searchdata_utils.py- Shared utilities for data processing and API requestsconfig.py- Configuration constants and settings
- Include country names in queries: "population density france", "co2 emissions china"
- Use simple, generic terms: "coal production", "gdp per capita"
- Avoid OWID-specific terms or overly complex queries
- Search by concept only: "population density" (not "population density USA")
- Use
country:filter for specific countries: "population density country:US" - Entity names must match exactly as they appear in OWID
Key environment variables and settings are defined in config.py:
- API endpoints and timeouts
- Database connection settings
- Common entity mappings
- Rate limiting and caching parameters
- We filter explorer views from
search_chartbecause they don't have persistent CSV URLs or images.
The ETL includes an optional MCP (Model Context Protocol) server that provides Claude Code with tools to search OWID indicators, fetch chart data, and query the database directly.
To enable it, add the OWID MCP server to your local Claude Code configuration:
# Production server (hosted)
claude mcp add owid --transport http https://mcp.owid.io/mcp
# Development server (local, requires running the server first)
claude mcp add owid-dev --transport http http://0.0.0.0:8080/mcp/This adds the following tools to Claude Code:
search_indicator- Find indicators using semantic searchfetch_indicator_data/fetch_indicator_metadata- Get indicator data and metadatasearch_chart/fetch_chart_data/fetch_chart_image- Search and fetch chart datarun_sql- Execute read-only SQL queries against the OWID databasesearch_posts/fetch_post- Search and retrieve OWID articles
Note: Enabling MCP adds ~7k tokens to the initial context.