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:

  1. Builder Stage: Uses ghcr.io/astral-sh/uv:python3.10-bookworm-slim to install dependencies via uv sync. This stage leverages caching for the virtual environment and dependency resolution.
  2. Final Stage: Copies the built virtual environment into a lightweight python:3.10-slim image and sets ENTRYPOINT ["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.yml triggers on relevant code changes, ensuring the Docker image stays synchronized with the repository.
  • Multi-Architecture Support: The pipeline builds for both linux/amd64 and linux/arm64, making the MCP server compatible with diverse deployment targets.
  • Optimized Containers: The multi-stage Dockerfile uses uv for 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-wordle entry point defined in pyproject.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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →