Agents-MCP-Hackathon/owid-catalog-mcp
OWID Catalog MCP
This repository contains the Model Context Protocol (MCP) server for Our World in Data's public catalog. It exposes functionalities to programmatically search and query data from the OWID catalog, making it accessible for various applications and analyses.
Features
The OWID Catalog MCP server provides the following key functionalities:
- Search OWID Catalog: Search for datasets and tables within the OWID catalog using keywords.
- Query OWID Table SQL: Execute read-only SQL queries directly against tables loaded from the OWID catalog, enabling flexible data retrieval and manipulation.
- Describe OWID Table Schema: Describes the schema of a table loaded from the OWID catalog.
For more information, consult the Python API documentation: https://docs.owid.io/projects/etl/api/python/
Demo
Here's a demo of using the tools via Cline
Installation
To set up and run the OWID Catalog MCP server locally, follow these steps:
- Clone the repository:
git clone https://github.com/your-repo/owid-catalog-mcp.git
cd owid-catalog-mcp- Create and activate a virtual environment:
python3 -m venv .venv
source .venv/bin/activate- Install dependencies using `uv`:
uv syncUsage
The MCP server can be launched as a Gradio application, which provides a user interface to interact with the exposed tools.
To run the server:
python3 app.pyOnce the server is running, you can access the Gradio interface in your web browser (usually at http://localhost:7860). The interface allows you to:
Example: Using the search_owid_catalog tool
# Example Python code to interact with the MCP server (assuming it's running)
from mcp.client import Client
client = Client("http://localhost:7860") # Replace with your server URL if different
async def main():
results = await client.call(
"search_owid_catalog",
query="population"
)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(main())Example: Using the query_owid_table_sql tool
# Example Python code to interact with the MCP server (assuming it's running)
from mcp.client import Client
import json
client = Client("http://localhost:7860") # Replace with your server URL if different
async def main():
table_references = [
{"path": "owid/latest/key_indicators/population", "table_name_in_sql": "population_data"}
]
sql_query = "SELECT * FROM population_data WHERE entity = 'World' LIMIT 5"
results = await client.call(
"query_owid_table_sql",
table_references_json=json.dumps(table_references),
sql_query=sql_query
)
print(results)
if __name__ == "__main__":
import asyncio
asyncio.run(main())Project Structure
The project is organized as follows:
.
├── app.py # Main application file, defines and exposes MCP tools via Gradio.
├── connectors/ # Contains modules for connecting to data sources.
│ ├── __init__.py
│ ├── duckdb_handler.py # Handles DuckDB interactions for SQL queries.
│ └── owid_connector.py # Connects to and retrieves data from the OWID catalog.
├── services/ # Contains business logic for OWID catalog operations.
│ ├── __init__.py
│ └── owid_service.py # Implements the core logic for searching and querying the OWID catalog.
├── pyproject.toml # Project metadata and dependency management (using uv).
├── uv.lock # Lock file for uv, ensuring reproducible builds.
└── README.md # This README file.License
This project is licensed under the MIT License.
