Design for containerizing grist-mcp with: - Multi-stage Dockerfile with Python 3.14 - SSE transport for remote server operation - Docker Compose for local deployment - Single adaptive CI workflow for Gitea and GitHub - Semantic version tagging
2.5 KiB
2.5 KiB
Docker Deployment Design
Overview
Make grist-mcp deployable via Docker Compose with CI workflows for automated image builds on version tag pushes.
Requirements
- Docker Compose for local deployment
- Single CI workflow that works on both Gitea and GitHub
- SSE transport (replacing stdio) for remote server operation
- Port 3000 default, configurable via environment variable
- Python 3.14
- Semantic version tagging (1.2.3, 1.2, 1, latest)
- Config mounted at runtime (not baked into image)
Files to Create
Dockerfile
Multi-stage build:
Stage 1 (builder):
- Base:
python:3.14-slim - Install uv
- Copy
pyproject.tomlanduv.lock - Install dependencies
Stage 2 (runtime):
- Base:
python:3.14-slim - Copy virtual environment from builder
- Copy source code
- Non-root user (
appuser) for security - Expose port 3000
- CMD: run server via uv
docker-compose.yaml
services:
grist-mcp:
build: .
ports:
- "${PORT:-3000}:3000"
volumes:
- ./config.yaml:/app/config.yaml:ro
env_file:
- .env
restart: unless-stopped
.env.example
PORT=3000
GRIST_MCP_TOKEN=your-agent-token-here
.github/workflows/build.yaml
Single workflow that detects platform (Gitea vs GitHub) at runtime:
- Trigger: Push of version tags (
v*.*.*) - Platform detection: Check
GITEA_ACTIONSenvironment variable - Registry:
- Gitea:
${{ github.server_url }}/${{ github.repository }} - GitHub:
ghcr.io/${{ github.repository }}
- Gitea:
- Authentication:
- Gitea:
${{ secrets.REGISTRY_TOKEN }} - GitHub:
${{ secrets.GITHUB_TOKEN }}
- Gitea:
- Tags generated:
1.2.3,1.2,1,latest
Files to Modify
pyproject.toml
Add dependencies:
starlette- ASGI framework for SSEuvicorn- ASGI serversse-starlette- SSE support
src/grist_mcp/main.py
Replace stdio transport with SSE:
- Create Starlette ASGI app with routes:
GET /sse- SSE connection endpointPOST /messages- Client message endpoint
- Run with uvicorn on configurable port (default 3000)
- Keep existing config/auth flow unchanged
.gitignore
Ensure .env is ignored.
Implementation Order
- Update dependencies and main.py for SSE transport
- Create Dockerfile
- Create docker-compose.yaml and .env.example
- Create CI workflow
- Test locally with
docker compose up
Secrets to Configure
- Gitea: Create
REGISTRY_TOKENsecret with registry push access - GitHub: Uses automatic
GITHUB_TOKEN