Skip to main content

Build MCP server containers

This guide explains how to use the thv build command to build MCP server containers from protocol schemes without running them. This is useful for pre-building containers for Kubernetes deployments, CI/CD pipelines, and container registry workflows.

Overview

The thv build command allows you to build containers from protocol schemes (uvx://, npx://, go://) without immediately running them. This provides several benefits:

  • Pre-build containers for faster deployment in Kubernetes environments
  • Separate build and run phases in CI/CD pipelines
  • Custom image tagging for container registry workflows
  • Dockerfile generation for inspection and customization
  • Build validation before deployment

Basic usage

To build a container from a protocol scheme:

thv build <PROTOCOL_SCHEME>

For example:

# Build a Python MCP server using uvx
thv build uvx://mcp-server-git

# Build a Node.js MCP server using npx
thv build npx://@modelcontextprotocol/server-filesystem

# Build a Go MCP server
thv build go://github.com/example/my-mcp-server@latest
What's happening?

When you run thv build, ToolHive:

  1. Detects the protocol scheme and extracts the package reference
  2. Generates a Dockerfile based on the appropriate template
  3. Builds a Docker image with the package installed
  4. Tags the image with an auto-generated name or your custom tag
  5. Displays the built image name for use with other tools

Custom image tagging

Use the --tag (or -t) flag to specify a custom name and tag for the built image:

thv build --tag my-custom-name:latest npx://@modelcontextprotocol/server-filesystem

This is particularly useful for:

  • Container registries: Tag images for pushing to registries
  • Kubernetes deployments: Use predictable image names in manifests
  • Version management: Tag images with specific versions

Tagging examples

Build and tag for pushing to a container registry:

# Build and tag for Docker Hub
thv build --tag myusername/mcp-git-server:v1.0.0 uvx://mcp-server-git

# Build and tag for GitHub Container Registry
thv build --tag ghcr.io/myorg/mcp-filesystem:latest npx://@modelcontextprotocol/server-filesystem

# Push to registry
docker push ghcr.io/myorg/mcp-filesystem:latest

Protocol schemes

The thv build command supports the same protocol schemes as thv run:

Python (uvx)

Build Python-based MCP servers using the uv package manager:

# Build with auto-generated name
thv build uvx://mcp-server-git

# Build with custom tag
thv build --tag my-git-server:latest uvx://mcp-server-git@1.2.0

Node.js (npx)

Build Node.js-based MCP servers using npm:

# Build with auto-generated name
thv build npx://@modelcontextprotocol/server-filesystem

# Build with custom tag
thv build --tag filesystem-server:v2.0 npx://@modelcontextprotocol/server-filesystem@2.0.0

Go

Build Go-based MCP servers:

# Build from remote Go module
thv build --tag grafana-mcp:latest go://github.com/grafana/mcp-grafana/cmd/mcp-grafana@latest

# Build from local Go project
thv build --tag my-local-server:dev go://./cmd/my-mcp-server

Dockerfile generation

Use the --dry-run flag to generate the Dockerfile without building the image:

# Output Dockerfile to stdout
thv build --dry-run uvx://mcp-server-git

# Save Dockerfile to a file
thv build --dry-run --output Dockerfile.mcp-git uvx://mcp-server-git

This is useful for:

  • Inspecting the build process before building
  • Customizing Dockerfiles for specific requirements
  • Understanding dependencies and build steps
  • Debugging build issues

Example Dockerfile output

# Generated by: thv build --dry-run uvx://mcp-server-git
FROM python:3.12-slim

# Install uv
RUN pip install uv

# Install the package
RUN uv tool install mcp-server-git

# Set the entrypoint
ENTRYPOINT ["uv", "tool", "run", "mcp-server-git"]

Kubernetes workflows

The thv build command is especially useful for Kubernetes deployments where you want to pre-build containers before deploying them.

Pre-build workflow

  1. Build the container with a specific tag:

    thv build --tag ghcr.io/myorg/mcp-git:v1.0.0 uvx://mcp-server-git@1.0.0
  2. Push to container registry:

    docker push ghcr.io/myorg/mcp-git:v1.0.0
  3. Deploy to Kubernetes using the pre-built image:

    apiVersion: toolhive.stacklok.dev/v1alpha1
    kind: MCPServer
    metadata:
    name: git-server
    namespace: production
    spec:
    image: ghcr.io/myorg/mcp-git:v1.0.0
    transport: stdio
    permissionProfile:
    type: builtin
    name: network

CI/CD integration

Integrate thv build into your CI/CD pipeline for automated container building:

# Example GitHub Actions workflow
name: Build and Deploy MCP Server
on:
push:
tags: ['v*']

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install ToolHive
run: |
# Install ToolHive CLI (replace with your preferred installation method)
# See: https://github.com/stacklok/toolhive/releases
wget https://github.com/stacklok/toolhive/releases/latest/download/toolhive_linux_amd64.tar.gz
tar -xzf toolhive_linux_amd64.tar.gz
sudo install -m 0755 thv /usr/local/bin/

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build MCP server
run: |
thv build --tag ghcr.io/${{ github.repository }}/mcp-server:${{ github.ref_name }} \
uvx://mcp-server-git@${{ github.ref_name }}

- name: Push to registry
run: |
docker push ghcr.io/${{ github.repository }}/mcp-server:${{ github.ref_name }}

For more advanced CI/CD patterns including multi-architecture builds, supply chain security, and change detection, see the Advanced CI/CD with ToolHive guide.

Advanced usage

Build with custom CA certificates

For corporate environments with custom certificate authorities:

# Use global CA certificate configuration
thv config set-ca-cert /path/to/corporate-ca.crt
thv build uvx://internal-mcp-server

# Override CA certificate for specific build
thv build --ca-cert /path/to/special-ca.crt uvx://special-server

Build local Go projects

Build MCP servers from local Go projects:

# Build from current directory
cd my-go-mcp-project
thv build --tag my-server:dev go://.

# Build from relative path
thv build --tag my-server:dev go://./cmd/server

# Build from absolute path
thv build --tag my-server:dev go:///path/to/my-project

Comparison with thv run

Featurethv buildthv run
PurposeBuild containers onlyBuild and run containers
OutputContainer imageRunning MCP server
Use casePre-building, CI/CDDevelopment, testing
KubernetesPre-build for deploymentDirect development
Custom tagging--tag flag❌ Auto-generated names
Dockerfile generation--dry-run flag❌ Not available

Next steps

Troubleshooting

Build fails with network errors

If builds fail with network connectivity issues:

  1. Check internet connectivity for downloading packages
  2. Configure CA certificates for corporate environments:
    thv config set-ca-cert /path/to/corporate-ca.crt
  3. Use proxy settings if required by your network
  4. Verify package names and versions exist in the respective registries
Invalid image tag format

If you get image tag validation errors:

  1. Use valid Docker image tag format: name:tag or registry/name:tag
  2. Avoid special characters except hyphens, underscores, and dots
  3. Use lowercase names for compatibility
  4. Check tag length limits (typically 128 characters)

Example valid tags:

thv build --tag my-server:latest uvx://package
thv build --tag ghcr.io/org/server:v1.0.0 npx://package
Package not found errors

If the build fails because a package cannot be found:

  1. Verify package exists in the respective registry:

    • Python: Check PyPI
    • Node.js: Check npm
    • Go: Verify the module path and version
  2. Check version specifiers:

    # Correct version formats
    thv build uvx://package@1.0.0
    thv build npx://package@latest
    thv build go://github.com/user/repo@v1.0.0
  3. For Go modules, ensure the path includes the correct import path