Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f61a180
spec: Outline docker container implementation
smkohnstamm Sep 22, 2025
2a43501
Merge branch 'spec/feature-docker-container' into impl/feature-docker…
smkohnstamm Sep 22, 2025
6497375
feat: respect transport override in CLI entrypoint
smkohnstamm Sep 22, 2025
067ad40
feat: add docker container with http transport
smkohnstamm Sep 22, 2025
e2fbcd7
feat: publish docker image during release
smkohnstamm Sep 22, 2025
019a545
feat: add docker developer tooling and docs
smkohnstamm Sep 22, 2025
8ee7624
docs: capture docker release notes
smkohnstamm Sep 22, 2025
f58ad19
docs: document http proxy setup for claude
smkohnstamm Sep 22, 2025
9dc31d8
Merge branch 'main' into impl/feature-docker-container
drernie Sep 22, 2025
fc25186
lint
drernie Sep 22, 2025
3d765dc
chore: bump version to 0.6.13 and update CHANGELOG
drernie Sep 22, 2025
b57b966
feat: refactor Docker build workflow for better maintainability
drernie Sep 22, 2025
7b917db
refactor: merge Docker scripts into unified Python implementation
drernie Sep 22, 2025
d6b7371
PR fixes
drernie Sep 23, 2025
181b8f6
docs: clarify ECR_REGISTRY as optional override in env.example
drernie Sep 23, 2025
44f5f65
make docker
drernie Sep 23, 2025
8f7e22e
fix: consolidate Docker operations in create-release action
drernie Sep 23, 2025
8338ef4
feat: add docker info command and consolidate Docker operations
drernie Sep 23, 2025
bba000b
revert CI again
drernie Sep 23, 2025
f527c81
post-release-status
drernie Sep 23, 2025
ba7592d
feat: implement post-release status system
drernie Sep 23, 2025
235dc41
refactor: convert post-release-status to pure function design
drernie Sep 23, 2025
3f2812b
fix: add missing CLI arguments for pure function design
drernie Sep 23, 2025
9bebbc0
no docker on dev
drernie Sep 23, 2025
b25d0c3
stupid version check
drernie Sep 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 80 additions & 2 deletions .github/actions/create-release/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'Create Release'
description: 'Build Python package, MCPB package, and create GitHub release'
description: 'Build Python package, MCPB package, Docker image, and create GitHub release'
inputs:
package-version:
description: 'Version from git tag (e.g., 0.5.9-dev-20250904075318)'
Expand All @@ -12,11 +12,24 @@ inputs:
description: 'Skip existing packages during upload'
required: false
default: 'false'
build-docker:
description: 'Build and push Docker image (true/false)'
required: false
default: 'true'

outputs:
release-id:
description: 'ID of the created release'
value: ${{ steps.create-release.outputs.id }}
release-url:
description: 'URL of the created release'
value: ${{ steps.create-release.outputs.url }}
pypi-url:
description: 'URL of the published PyPI package'
value: ${{ steps.package-urls.outputs.pypi-url }}
docker-image:
description: 'Docker image URI if built'
value: ${{ steps.docker-info.outputs.image-uri }}

runs:
using: 'composite'
Expand All @@ -37,6 +50,23 @@ runs:
skip-existing: ${{ inputs.skip-existing }}
verbose: true

- name: Determine package URLs
id: package-urls
shell: bash
run: |
VERSION="${{ inputs.package-version }}"
if [ -z "${{ inputs.pypi-repository-url }}" ]; then
# Production PyPI
PYPI_URL="https://pypi.org/project/quilt-mcp-server/${VERSION}/"
echo "pypi-url=${PYPI_URL}" >> $GITHUB_OUTPUT
echo "📦 PyPI URL: ${PYPI_URL}"
else
# TestPyPI
PYPI_URL="https://test.pypi.org/project/quilt-mcp-server/${VERSION}/"
echo "pypi-url=${PYPI_URL}" >> $GITHUB_OUTPUT
echo "🧪 TestPyPI URL: ${PYPI_URL}"
fi

- name: Build MCPB package
shell: bash
run: make mcpb
Expand All @@ -49,6 +79,33 @@ runs:
shell: bash
run: make release-zip

- name: Build and push Docker image
if: ${{ inputs.build-docker == 'true' }}
shell: bash
env:
VERSION: ${{ inputs.package-version }}
ECR_REGISTRY: ${{ env.ECR_REGISTRY }}
AWS_ACCOUNT_ID: ${{ env.AWS_ACCOUNT_ID }}
AWS_DEFAULT_REGION: ${{ env.AWS_DEFAULT_REGION }}
run: |
echo "🐳 Building and pushing Docker image with scripts/docker.py"
uv run python scripts/docker.py push --version "$VERSION"

- name: Capture Docker image info
id: docker-info
if: ${{ inputs.build-docker == 'true' }}
shell: bash
env:
VERSION: ${{ inputs.package-version }}
ECR_REGISTRY: ${{ env.ECR_REGISTRY }}
AWS_ACCOUNT_ID: ${{ env.AWS_ACCOUNT_ID }}
AWS_DEFAULT_REGION: ${{ env.AWS_DEFAULT_REGION }}
run: |
# Use docker.py to get image info for consistency
IMAGE_URI=$(uv run python scripts/docker.py info --version "$VERSION" --output github)
echo "${IMAGE_URI}" >> $GITHUB_OUTPUT
echo "🐳 Docker Image: ${IMAGE_URI#image-uri=}"

- name: Create GitHub Release
id: create-release
uses: softprops/action-gh-release@v2
Expand All @@ -66,4 +123,25 @@ runs:
with:
name: mcpb-package
path: dist/*.mcpb
retention-days: 90
retention-days: 90

- name: Post release status
shell: bash
run: |
# Determine if this is a production release
IS_PRODUCTION="true"
if [[ "${{ inputs.package-version }}" == *"-dev-"* ]] || [[ "${{ inputs.package-version }}" == *"-dev" ]]; then
IS_PRODUCTION="false"
fi

uv run python scripts/post_release_status.py \
--version "${{ inputs.package-version }}" \
--release-url "${{ steps.create-release.outputs.url }}" \
--pypi-url "${{ steps.package-urls.outputs.pypi-url }}" \
--docker-image "${{ steps.docker-info.outputs.image-uri }}" \
--release-id "${{ steps.create-release.outputs.id }}" \
--sha "${{ github.sha }}" \
--repo "${{ github.repository }}" \
--github-token "${{ github.token }}" \
--is-production "${IS_PRODUCTION}" \
--package-name "quilt-mcp-server"
1 change: 1 addition & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,5 @@ jobs:
with:
package-version: ${{ steps.version.outputs.tag_version }}
pypi-repository-url: https://test.pypi.org/legacy/
build-docker: false
skip-existing: true
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,7 @@ local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache
.uv-cache

# Scrapy stuff:
.scrapy
Expand Down
54 changes: 54 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,12 @@ For this repository's specific commands and permissions, see this CLAUDE.md file
- `make release` - Create and push release tag
- `make release-dev` - Create and push development tag

**Docker Operations (make.deploy):**

- `make docker-build` - Build Docker image locally
- `make docker-push` - Build and push Docker image to ECR (requires VERSION)
- `make docker-push-dev` - Build and push development Docker image

**Coordination & Utilities:**

- `make help` - Show all available targets organized by category
Expand Down Expand Up @@ -412,6 +418,54 @@ The following permissions are granted for this repository:
- `python-dist` builds local artifacts without credentials. `scripts/release.sh python-publish` (via `make python-publish`) requires either `UV_PUBLISH_TOKEN` or `UV_PUBLISH_USERNAME`/`UV_PUBLISH_PASSWORD`, defaults to TestPyPI (`PYPI_PUBLISH_URL`/`PYPI_REPOSITORY_URL` override), and respects `DIST_DIR`.
- GitHub Actions builds dist artifacts via `python-dist`, publishes them with `pypa/gh-action-pypi-publish`, then runs `make mcpb`, `make mcpb-validate`, and `make release-zip` for complete packaging. Secrets supply the PyPI/TestPyPI token (`secrets.PYPI_TOKEN`).

### Docker container + release notes (2025-09-22)

- `src/quilt_mcp/main.py` now honours a pre-set `FASTMCP_TRANSPORT`; container entrypoints should export `FASTMCP_TRANSPORT=http` and `FASTMCP_HOST=0.0.0.0` before invoking `quilt-mcp`.
- The Dockerfile uses the `ghcr.io/astral-sh/uv:python3.11-bookworm-slim` base. Native deps (`build-essential`, `libcurl4(-openssl-dev)`, `zlib1g(-dev)`) are required for `pybigwig`; keep them in sync if the dependency list changes.
- `make docker-build`, `make docker-run`, and `make docker-test` wrap common local workflows. `make docker-test` executes `tests/integration/test_docker_container.py`, which builds the image and probes `http://localhost:*/mcp` for a 30–60s readiness window.
- Release automation logs into ECR via `aws-actions/amazon-ecr-login` and uses `scripts/docker_image.py` to generate version + `latest` tags. Configure either `secrets.ECR_REGISTRY` or fall back to `AWS_ACCOUNT_ID` + `AWS_DEFAULT_REGION`.
- When running the integration test locally, Docker must be available and the build takes ~45s on warm caches. Expect the test to leave behind pulled base images but no running containers.
- Claude Desktop still requires stdio transports; use a FastMCP proxy (`FastMCP.as_proxy(...).run(transport='stdio')`) and pass `--project /path/to/quilt-mcp-server` to `uv run` so `fastmcp` resolves correctly.

### Docker Build and Deployment Refactoring (2025-09-22)

**Script-based Docker Operations:**

- All Docker operations extracted to `scripts/docker.sh` for reusability and local testing
- Script supports both `build` (local testing) and `push` (ECR deployment) commands
- Integrates with existing `scripts/docker_image.py` for consistent tag generation
- Supports dry-run mode via `--dry-run` for testing workflow changes

**GitHub Actions Integration:**

- Production releases (tags matching `v*` but not `v*-dev-*`) build and push Docker images automatically
- Development releases skip Docker builds to reduce CI/CD time and resource usage
- PR builds test Docker image building without pushing (build-only validation)
- Docker operations moved from `push.yml` workflow into `create-release` action for better encapsulation

**Makefile Integration:**

- `make docker-build` - Build locally for development and testing
- `make docker-push` - Build and push to ECR (requires VERSION environment variable)
- `make docker-push-dev` - Build and push with timestamp-based development tags
- All Docker targets include proper dependency checking for Docker daemon and required tools

**GitHub Secrets Configuration:**

Required secrets for Docker operations:

- `ECR_REGISTRY` - ECR registry URL (preferred)
- `AWS_ACCOUNT_ID` - AWS account ID (fallback for registry construction)
- `AWS_DEFAULT_REGION` - AWS region (defaults to us-east-1)
- Existing AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`) for ECR login

**Environment Variable Support:**

- `scripts/docker.sh` respects all environment variables from `env.example`
- `ECR_REGISTRY`, `AWS_ACCOUNT_ID`, `AWS_DEFAULT_REGION` for registry configuration
- `VERSION` for overriding image version tags
- `DOCKER_IMAGE_NAME` for custom image naming (defaults to `quilt-mcp-server`)

## important-instruction-reminders

Do what has been asked; nothing more, nothing less.
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.13] - 2025-09-22

### Added

- **Docker Container Support**: Complete HTTP transport implementation for containerized deployment (#195)
- New Docker image with FastMCP HTTP transport support (`FASTMCP_TRANSPORT=http`)
- Automated Docker image publishing to ECR during releases
- Developer tooling: `make docker-build`, `make docker-run`, `make docker-test`
- Integration test suite validating container readiness and HTTP endpoints
- Support for HTTP proxy configuration in Claude Desktop

### Changed

- **CLI Entrypoint**: Enhanced to respect pre-set `FASTMCP_TRANSPORT` environment variable
- Enables flexible transport configuration for container deployments
- Maintains backward compatibility with stdio transport for local usage

### Documentation

- **Docker Setup Guide**: Added comprehensive documentation for Docker deployment
- HTTP proxy configuration instructions for Claude Desktop
- Container usage examples and troubleshooting
- Release notes capturing Docker implementation details

## [0.6.12] - 2025-09-22

### Fixed
Expand Down
53 changes: 53 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# syntax=docker/dockerfile:1.6

FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim AS builder
WORKDIR /app

# Copy project metadata and lockfile first for better caching
COPY pyproject.toml uv.lock ./
COPY Makefile make.dev make.deploy ./

# Install build dependencies required for native extensions (e.g., pybigwig)
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
build-essential \
libcurl4-openssl-dev \
zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*

# Copy source and supporting files
COPY src ./src
COPY scripts ./scripts
COPY docs ./docs
COPY spec ./spec

# Install project dependencies into a virtual environment
RUN uv sync --frozen --no-dev

FROM ghcr.io/astral-sh/uv:python3.11-bookworm-slim AS runtime
WORKDIR /app

ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
UV_PROJECT_ENVIRONMENT=/app/.venv \
FASTMCP_TRANSPORT=http \
FASTMCP_HOST=0.0.0.0 \
FASTMCP_PORT=8000

RUN apt-get update \
&& apt-get install --no-install-recommends -y \
libcurl4 \
zlib1g \
&& rm -rf /var/lib/apt/lists/*

# Copy virtual environment and application code
COPY --from=builder /app/.venv /app/.venv
COPY --from=builder /app/src /app/src
COPY --from=builder /app/pyproject.toml /app/pyproject.toml
COPY --from=builder /app/spec/feature-docker-container /app/spec/feature-docker-container

ENV PATH="/app/.venv/bin:$PATH"

EXPOSE 8000

CMD ["quilt-mcp"]
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Quilt MCP Server - Consolidated Build System
#
#
# This Makefile consolidates all build workflows into organized includes.
# Development targets are in make.dev, production targets are in make.deploy.

Expand Down Expand Up @@ -38,6 +38,11 @@ help:
@echo " make release - Create and push release tag"
@echo " make release-dev - Create and push development tag"
@echo ""
@echo "🐳 Docker Operations (make.deploy):"
@echo " make docker-build - Build Docker image locally"
@echo " make docker-push - Build and push Docker image to ECR (requires VERSION)"
@echo " make docker-push-dev - Build and push development Docker image"
@echo ""
@echo "🔢 Version Management:"
@echo " make bump-patch - Bump patch version (1.2.3 → 1.2.4)"
@echo " make bump-minor - Bump minor version (1.2.3 → 1.3.0)"
Expand Down Expand Up @@ -130,4 +135,4 @@ release-major: bump-major
git commit -m "bump: major version to $$VERSION"; \
echo "✅ Committed version bump to $$VERSION"
@echo "🏷️ Creating release tag..."
@scripts/release.sh release
@scripts/release.sh release
Loading