DEV Community

Gabriel Mahia
Gabriel Mahia

Posted on

Build Your First East Africa MCP Server in 30 Minutes

Every tool in the East Africa coordination infrastructure stack started from the same scaffold. Here's exactly how to build and publish one yourself.

What You're Building

An MCP server is a Python package that exposes tools to AI assistants. When a user installs it and connects it to Claude, the AI can call your tools as naturally as answering a question.

pip install your-mcp-server
# Then Claude can:
# "Check NHIF coverage for outpatient surgery" → calls your tool → returns structured result
Enter fullscreen mode Exit fullscreen mode

Step 1: Set Up the Project (2 min)

your-mcp-server/
├── src/
│   └── your_package/
│       ├── __init__.py
│       └── main.py
├── pyproject.toml
├── README.md
└── .github/
    └── workflows/
        └── publish.yml
Enter fullscreen mode Exit fullscreen mode
mkdir your-mcp-server && cd your-mcp-server
mkdir -p src/your_package
touch src/your_package/__init__.py src/your_package/main.py
Enter fullscreen mode Exit fullscreen mode

Step 2: Write Your Tool (10 min)

# src/your_package/main.py
from __future__ import annotations
from typing import Annotated
from fastmcp import FastMCP

mcp = FastMCP(
    name="your-mcp-server",
    instructions="Describe what your server does in one paragraph.",
)

@mcp.tool(
    description=(
        "What this tool does in plain language. "
        "Include the Western parallel if applicable. "
        "Note if it uses DEMO data."
    )
)
def your_tool(
    param1: Annotated[str, "Description of param1"],
    param2: Annotated[int, "Description of param2"] = 0,
) -> dict:
    # Your logic here
    return {
        "result": f"Processed {param1}",
        "note": "DEMO — replace with real data source in production",
        "source": "your-mcp-server",
    }

def main():
    mcp.run()

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

Step 3: Configure pyproject.toml (3 min)

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"  # ← exact string, no variation

[project]
name = "your-mcp-server"
version = "0.1.0"
description = "One-line description"
authors = [{name = "Your Name", email = "you@example.com"}]
license = {text = "MIT"}
readme = "README.md"
requires-python = ">=3.9"
dependencies = ["fastmcp>=2.0.0"]

[project.scripts]
your-mcp-server = "your_package.main:main"  # CLI entry point

[tool.setuptools.packages.find]
where = ["src"]  # ← required for src/ layout
Enter fullscreen mode Exit fullscreen mode

Common mistake: build-backend = "setuptools.backends.legacy:build" is not valid. Use exactly "setuptools.build_meta". This error causes python -m build to fail silently in CI.

Step 4: Set Up CI Publishing (5 min)

Option A: API Token (faster)

  1. Create a PyPI API token at pypi.org/manage/account/#api-tokens
  2. Add as PYPI_API_TOKEN in your GitHub repo → Settings → Secrets

Option B: OIDC Trusted Publisher (more secure, recommended)

  1. Create the package on PyPI first (one push via token)
  2. Go to pypi.org/manage/project/{name}/settings/publishing/
  3. Add GitHub Actions publisher: owner, repo, publish.yml, environment pypi

.github/workflows/publish.yml:

name: Publish to PyPI
on:
  push:
    tags: ["v*"]
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: {python-version: "3.11"}
      - run: pip install build
      - run: python -m build
      - uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_API_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Step 5: Publish (2 min)

git init && git add . && git commit -m "initial commit"
git remote add origin https://github.com/yourusername/your-mcp-server
git push -u origin main

git tag v0.1.0 && git push origin v0.1.0
# → GitHub Actions runs → pip install your-mcp-server works in 2-3 minutes
Enter fullscreen mode Exit fullscreen mode

Step 6: Connect to Claude (1 min)

# Install
pip install your-mcp-server

# Add to Claude Code
claude mcp add myserver -- your-mcp-server

# Test
claude "Use myserver to process X"
Enter fullscreen mode Exit fullscreen mode

East Africa Design Patterns

A few patterns specific to building for this context:

Trust integrity:

return {
    "result": result,
    "note": "DEMO — Synthetic data for educational purposes. Not operational guidance.",
    "source": "your-mcp-server. Research basis: [cite your source]",
}
Enter fullscreen mode Exit fullscreen mode

Swahili/English bilingual errors:

except Exception as e:
    return {"error": f"Hitilafu / Error: {str(e)[:60]}. Jaribu tena / Try again."}
Enter fullscreen mode Exit fullscreen mode

Version bump workflow:

# Edit pyproject.toml → version = "0.2.0"
git commit -am "bump: v0.2.0"
git tag v0.2.0 && git push origin main --tags
Enter fullscreen mode Exit fullscreen mode

That's the complete cycle. Every MCP server in the East Africa coordination stack was built and published with exactly this scaffold.


Full portfolio and all 12 packages: gabrielmahia.github.io

Top comments (0)