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
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
mkdir your-mcp-server && cd your-mcp-server
mkdir -p src/your_package
touch src/your_package/__init__.py src/your_package/main.py
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()
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
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)
- Create a PyPI API token at pypi.org/manage/account/#api-tokens
- Add as
PYPI_API_TOKENin your GitHub repo → Settings → Secrets
Option B: OIDC Trusted Publisher (more secure, recommended)
- Create the package on PyPI first (one push via token)
- Go to
pypi.org/manage/project/{name}/settings/publishing/ - Add GitHub Actions publisher: owner, repo,
publish.yml, environmentpypi
.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 }}
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
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"
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]",
}
Swahili/English bilingual errors:
except Exception as e:
return {"error": f"Hitilafu / Error: {str(e)[:60]}. Jaribu tena / Try again."}
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
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 (1)
You've done a fantastic job of breaking down the complex process of building an MCP server into manageable, bite-sized chunks, making it incredibly accessible to newcomers. Your unique perspective on the East Africa coordination infrastructure stack would really resonate with our community at ZyVOP, and we'd love to have you cross-post your content to help you reach an even wider audience.