CI/CD Pipeline Configuration for MCP Server Projects: A Production-Ready Guide
A robust CI/CD pipeline for MCP server projects automates multi-architecture Docker builds and publishes to GitHub Container Registry using GitHub Actions, enabling seamless deployment of FastMCP-based servers.
The cr2007/mcp-wordle-python repository demonstrates a complete CI/CD pipeline configuration for MCP server projects using GitHub Actions. This Python-based Wordle solver leverages the FastMCP framework to expose NYTimes Wordle data as an MCP tool, with automated container builds that publish multi-architecture images to GHCR whenever source code changes.
Understanding the MCP Server Architecture
Before diving into pipeline configuration, it is essential to understand the deployment target. The Wordle MCP server is built on fastmcp, a lightweight framework that transforms Python functions into MCP tools.
In src/mcp_wordle/main.py, the server initializes with FastMCP("WordleMCP") and registers the get_wordle_data tool, which fetches JSON data from the NYTimes Wordle API. The pyproject.toml defines the CLI entry point mcp-wordle, enabling the server to start via command line or container execution.
CI/CD Pipeline Structure for MCP Servers
The repository implements a three-stage CI/CD strategy optimized for Python-based MCP servers: automated triggering, multi-stage container builds, and multi-architecture publishing.
Workflow Triggers and Concurrency Control
The pipeline defined in .github/workflows/publish-image.yml triggers on pushes to master that modify source files, the uv.lock file, the Dockerfile, or the workflow itself. This ensures builds occur only when relevant changes are detected.
The workflow implements concurrency controls to cancel in-flight runs for the same branch, preventing redundant builds and ensuring only the latest image version is published.
Multi-Stage Docker Build Configuration
The Dockerfile employs a multi-stage build strategy to minimize image size and maximize build speed:
- Builder Stage: Uses
ghcr.io/astral-sh/uv:python3.10-bookworm-slimto install dependencies viauv sync. This stage leverages caching for the virtual environment and dependency resolution. - Final Stage: Copies the built virtual environment into a lightweight
python:3.10-slimimage and setsENTRYPOINT ["mcp-wordle"]to launch the FastMCP server immediately upon container start.
This approach reduces the final image size by excluding build tools and caches, while ensuring the server starts correctly via the CLI entry point defined in pyproject.toml.
Multi-Architecture Image Publishing
The pipeline builds and publishes images for both linux/amd64 and linux/arm64 architectures using Docker Buildx. This ensures compatibility across Intel/AMD servers and ARM-based systems like Apple Silicon Macs or AWS Graviton instances.
The workflow authenticates to GitHub Container Registry (GHCR) using the built-in GITHUB_TOKEN, then pushes the multi-arch manifest to ghcr.io/${{ github.repository }}:latest.
Implementing the GitHub Actions Workflow
The complete workflow configuration demonstrates production-grade practices for MCP server deployment:
name: Build and Publish Docker Image
on:
push:
branches:
- master
paths:
- 'src/**'
- 'uv.lock'
- 'Dockerfile'
- '.github/workflows/publish-image.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
This configuration leverages GitHub Actions cache (type=gha) for Docker layer caching and Buildx for efficient multi-architecture builds.
Docker Optimization for MCP Servers
The Dockerfile in this repository exemplifies best practices for containerizing Python MCP servers:
# Builder stage
FROM ghcr.io/astral-sh/uv:python3.10-bookworm-slim AS builder
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen --no-install-project --no-dev
ADD . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Final stage
FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
ENTRYPOINT ["mcp-wordle"]
Key optimizations include using uv for fast dependency resolution, compile bytecode for faster startup, and copying only the virtual environment to the final image rather than the entire build context.
Deployment and Client Configuration
Once the CI/CD pipeline publishes the image to GHCR, configure your MCP client to use the containerized server:
{
"mcpServers": {
"Wordle MCP (Python)": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"-e",
"DOCKER_CONTAINER=true",
"ghcr.io/cr2007/mcp-wordle-python:latest"
]
}
}
}
This configuration pulls the latest multi-arch image built by the CI/CD pipeline and executes the mcp-wordle entry point, exposing the get_wordle_solution tool to your MCP client.
Summary
- Automated Builds: The GitHub Actions workflow in
.github/workflows/publish-image.ymltriggers on relevant code changes, ensuring the Docker image stays synchronized with the repository. - Multi-Architecture Support: The pipeline builds for both
linux/amd64andlinux/arm64, making the MCP server compatible with diverse deployment targets. - Optimized Containers: The multi-stage
Dockerfileusesuvfor fast builds and produces minimal images by copying only the virtual environment to the final stage. - GHCR Publishing: Images are automatically published to GitHub Container Registry using the built-in
GITHUB_TOKEN, requiring no additional secrets configuration. - FastMCP Integration: The resulting container executes the
mcp-wordleentry point defined inpyproject.toml, immediately starting the FastMCP server for client connections.
Frequently Asked Questions
How do I manually trigger the CI/CD pipeline for the MCP server?
While the workflow triggers automatically on pushes to master, you can manually trigger it by navigating to the Actions tab in the GitHub repository, selecting the Build and Publish Docker Image workflow, and clicking Run workflow. Ensure you have permissions to write to the GitHub Container Registry.
What architectures does the published Docker image support?
The CI/CD pipeline builds and publishes multi-architecture images supporting both linux/amd64 (Intel/AMD servers) and linux/arm64 (Apple Silicon, AWS Graviton). This ensures the Wordle MCP server runs natively on diverse hardware without emulation overhead.
How do I configure my MCP client to use the containerized server from GHCR?
Add the following configuration to your MCP client settings (e.g., Claude Desktop), replacing the server name if desired:
{
"mcpServers": {
"Wordle MCP (Python)": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"--init",
"ghcr.io/cr2007/mcp-wordle-python:latest"
]
}
}
}
This pulls the latest image built by the CI/CD pipeline and executes the mcp-wordle entry point.
Why does the Dockerfile use uv instead of standard pip?
The Dockerfile uses uv (from Astral) because it provides significantly faster dependency resolution and installation compared to standard pip, reducing build times in CI/CD pipelines. Additionally, uv supports advanced caching mechanisms and compile bytecode options (UV_COMPILE_BYTECODE=1) that improve container startup performance, which is critical for MCP servers that need to initialize quickly when invoked by clients.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →