MCP Server Template
by sh-aidev
README.md
<div align="center">
# Autoplot AI MCP
[](https://www.python.org/)
[](https://modelcontextprotocol.io/)
[](https://github.com/astral-sh/uv)

An MCP (Model Context Protocol) server, managed with [uv](https://github.com/astral-sh/uv), that lets an MCP client discover public datasets (currently [World Bank Open Data](https://data.worldbank.org/)) by keyword ā the first step of an automated data-fetching and visualization pipeline.
</div>
## š Features
- [x] `uv` for dependency management
- [x] TOML + Pydantic based config, with API sources defined declaratively in `configs/api_config.toml`
- [x] `get_datasets_list` tool ā keyword search over a configured data source's datasets
- [x] Multi-source ready: add new APIs by editing config, no code changes
- [x] Centralized logging (loguru)
- [x] Custom exception handling
- [x] Standalone stdio client for manual testing
## š Project Structure
The directory structure of the project looks like this:
```
āāā LICENSE
āāā Makefile
āāā README.md
āāā client.py
āāā main.py
āāā configs
ā āāā config.toml
ā āāā api_config.toml
āāā outputs
āāā pyproject.toml
āāā src
āāā __init__.py
āāā app.py
āāā server
ā āāā __init__.py
ā āāā server.py
āāā tools
ā āāā __init__.py
ā āāā api_sources.py
ā āāā dataset_discovery.py
āāā utils
āāā __init__.py
āāā config.py
āāā exceptions.py
āāā logger.py
āāā models.py
```
## šļø Architecture
`main.py` boots an `App`, which loads config and hands it to a `Server` that wraps `FastMCP`. Tool implementations live under `src/tools/` (one module per tool, or tool family), each exposing a `register(mcp, config)` function; `src/tools/__init__.py` calls all of them so `Server` stays a thin wrapper. MCP clients (like `client.py` or the MCP Inspector) talk to the server over stdio; the tools in turn call out to whichever external data API is configured (e.g. the World Bank REST API).
```mermaid
flowchart LR
subgraph Client
C["client.py<br/>(MCP client)"]
end
subgraph "Autoplot AI MCP Server"
M["main.py"] --> A["App"]
A --> CFG["Config"]
A --> S["Server<br/>(FastMCP)"]
S --> R["tools.register_all"]
R -->|registers| T["dataset_discovery.get_datasets_list"]
T -->|resolves source| API["tools.api_sources.get_api_source"]
end
subgraph "Config Files"
CT["config.toml<br/>(logger, server)"]
AT["api_config.toml<br/>(API sources)"]
end
subgraph "External Data Sources"
WB["World Bank Open Data API"]
end
CFG --> CT
CFG --> AT
C <-->|stdio / MCP protocol| S
T -->|HTTP GET| WB
```
## š Sequence: `get_datasets_list`
```mermaid
sequenceDiagram
participant U as User
participant Cl as client.py
participant Sv as Server (FastMCP)
participant WB as World Bank API
U->>Cl: Enter search text
Cl->>Cl: Split input into keywords
Cl->>Sv: call_tool("get_datasets_list", {keywords, source, limit})
loop each result page
Sv->>WB: GET discovery_endpoint (page, per_page)
WB-->>Sv: indicators (name, sourceNote, id)
Sv->>Sv: match keywords against name / description
end
Sv->>Sv: rank name-matches above description-matches,<br/>shorter names first
Sv-->>Cl: top `limit` matching datasets
Cl-->>U: print dataset id / name / description
```
## š Getting Started
### Step 1: Install dependencies
```bash
uv sync
```
### Step 2: Run the server
```bash
uv run python main.py
# or
make run
```
The server communicates over stdio and is meant to be launched by an MCP client (see Step 3), not run standalone in a terminal.
### Step 3: Try it with the bundled client
```bash
uv run python client.py
# or
make client
```
This spawns `main.py` as a subprocess over stdio, lists the available tools, then prompts you for search text (e.g. `population growth`), splits it into keywords, and calls `get_datasets_list` to print matching datasets.
### Step 4 (optional): Inspect it with the MCP Inspector
```bash
uv run mcp dev main.py:mcp
```
Opens a browser UI to browse and call the registered tools interactively. `main.py` exposes a lazily-built `mcp` attribute for this purpose (see `__getattr__` at the bottom of the file) ā normal runs via `make run` / `make client` don't trigger it.
## āļø Configuration
- `configs/config.toml` ā logger environment (`dev` / `prod`) and the MCP server's advertised name.
- `configs/api_config.toml` ā a list of `[[apis]]`, each describing an external data source: its `name`, `description`, `discovery_endpoint` (lists datasets), `data_endpoint` (downloads one dataset), response `format`, and `per_page` page size. Add a new source by appending another `[[apis]]` block ā no code changes required.
## š References
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
- [uv](https://github.com/astral-sh/uv)
- [World Bank Open Data API](https://datahelpdesk.worldbank.org/knowledgebase/articles/889392)
TDQS
A3.7/5.0
Scored across 5 tools
Disambiguation5/5
Each tool has a clear and distinct purpose. The arithmetic tools (add, subtract, multiply, divide) are well-differentiated, and reverse_string operates on an entirely different domain.
Naming Consistency5/5
All tool names follow a consistent pattern: simple, lowercase, with underscores for multi-word names (reverse_string). No mixed styles or confusing abbreviations.
Tool Count5/5
Five tools is a reasonable count for a small utility server. It's neither too few to be useful nor too many to manage.
Completeness3/5
The arithmetic set covers basic operations but misses common ones like modulus or exponentiation. The string domain has only one operation, leaving gaps for typical string manipulations.
Maintenance
ActivityInactive
ResponsivenessNo issues