From 61f5f35e66d98b4063885873cea5569483f232f1 Mon Sep 17 00:00:00 2001 From: Shashank Shekhar Singh Date: Tue, 12 May 2026 01:41:21 +0530 Subject: [PATCH] initial tests for docker setup --- .dockerignore | 42 ++++++++++++++++++++++++++++++ Dockerfile | 65 ++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 20 +++++++++----- README.md | 43 +++++++++++++++++++++++++++++- docker-compose.yml | 38 +++++++++++++++++++++++++++ 5 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..067ab516 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,42 @@ +# Version control +.git +.github + +# Python caches +__pycache__ +*.pyc +*.pyo +.pytest_cache +.ruff_cache + +# Virtual environments +.venv +venv +env + +# IDE / editor +.vscode +.idea +*.swp +*.swo + +# Build artifacts +dist/ +*.egg-info +build/ + +# Documentation +docs/_build/ +docs/build/ + +# Project-specific ignores +mcp_server.log +.ignore/ +TODO.md +.pre-commit-config.yaml +.readthedocs.yaml + +# Docker (prevent recursive context) +Dockerfile +docker-compose.yml +.dockerignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..354e84d3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,65 @@ +# ============================================================================= +# Dockerfile for sktime-mcp +# +# Multi-stage build: +# 1. Builder – installs build tools and Python dependencies +# 2. Runtime – slim image with only the installed packages +# +# Usage: +# docker build -t sktime-mcp . +# docker run -i sktime-mcp # stdio transport (default) +# docker run -i -e SKTIME_MCP_LOG_LEVEL=DEBUG sktime-mcp +# ============================================================================= + +# --------------------------------------------------------------------------- +# Stage 1: Builder +# --------------------------------------------------------------------------- +FROM python:3.12-slim AS builder + +# Avoid interactive prompts during package install +ENV DEBIAN_FRONTEND=noninteractive + +# Install minimal build dependencies required by some scientific packages +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + gfortran \ + libopenblas-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /build + +# Copy only dependency-related files first to maximise Docker layer caching +COPY pyproject.toml README.md LICENSE ./ +COPY src/ src/ + +# Install the project in production mode (no dev/test extras) +RUN pip install --no-cache-dir --prefix=/install . + +# --------------------------------------------------------------------------- +# Stage 2: Runtime +# --------------------------------------------------------------------------- +FROM python:3.12-slim AS runtime + +# Runtime library needed by numpy/scipy linked against OpenBLAS +RUN apt-get update && apt-get install -y --no-install-recommends \ + libopenblas0 \ + && rm -rf /var/lib/apt/lists/* + +# Copy installed Python packages from the builder stage +COPY --from=builder /install /usr/local + +# Create a non-root user for security +RUN useradd --create-home --shell /bin/bash mcp +USER mcp +WORKDIR /home/mcp + +# Environment defaults (overridable at runtime) +ENV SKTIME_MCP_LOG_LEVEL=WARNING +ENV PYTHONUNBUFFERED=1 + +# Health-check: verify the package is importable +HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ + CMD python -c "import sktime_mcp; print('ok')" || exit 1 + +# MCP servers communicate over stdio, so the entrypoint is the CLI command +ENTRYPOINT ["sktime-mcp"] diff --git a/Makefile b/Makefile index b0ed815f..091831cc 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,14 @@ -.PHONY: check test lint format help format-fix install-hooks +.PHONY: check test lint format help format-fix install-hooks docker-build docker-run help: @echo "Available commands:" - @echo " make check - Run all CI checks (format check, lint, test)" - @echo " make lint - Run ruff linter" - @echo " make format - Run ruff format checker (check only)" - @echo " make test - Run pytest" - @echo " make format-fix - Auto-fix formatting and fixable lint issues" + @echo " make check - Run all CI checks (format check, lint, test)" + @echo " make lint - Run ruff linter" + @echo " make format - Run ruff format checker (check only)" + @echo " make test - Run pytest" + @echo " make format-fix - Auto-fix formatting and fixable lint issues" + @echo " make docker-build - Build the Docker image" + @echo " make docker-run - Run the MCP server in Docker (stdio)" check: format lint test @@ -26,3 +28,9 @@ format-fix: install-hooks: pip install pre-commit pre-commit install + +docker-build: + docker build -t sktime-mcp . + +docker-run: docker-build + docker run -i --rm sktime-mcp diff --git a/README.md b/README.md index 728ffab4..a6e30b59 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,44 @@ For development (editable install from source): pip install -e ".[dev]" ``` +### 🐳 Docker + +Run without installing anything locally (only Docker required): + +```bash +# Build the image +docker build -t sktime-mcp . + +# Run the MCP server (stdio transport) +docker run -i sktime-mcp +``` + +Or use Docker Compose: + +```bash +docker compose build +docker compose run sktime-mcp +``` + +**Claude Desktop** β€” use Docker as the MCP server command: + +```json +{ + "mcpServers": { + "sktime": { + "command": "docker", + "args": ["run", "-i", "--rm", "sktime-mcp"] + } + } +} +``` + +Environment variables can be passed at runtime: + +```bash +docker run -i -e SKTIME_MCP_LOG_LEVEL=DEBUG sktime-mcp +``` + For a more detailed first-time setup flow, including MCP server verification and troubleshooting, see [Beginner Setup](#-beginner-setup-firsttime-users). ## 🧭 Beginner Setup (First‑Time Users) @@ -527,7 +565,10 @@ sktime-mcp/ β”‚ └── tools/ # MCP tool implementations β”œβ”€β”€ docs/ # Sphinx documentation source β”œβ”€β”€ examples/ # Usage examples -└── tests/ # Test suite +β”œβ”€β”€ tests/ # Test suite +β”œβ”€β”€ Dockerfile # Multi-stage container build +β”œβ”€β”€ docker-compose.yml # Compose service definition +└── .dockerignore # Docker build context filter ``` ## πŸ§ͺ Running Tests diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..4be737e4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +# ============================================================================= +# Docker Compose for sktime-mcp +# +# Usage: +# docker compose build # build the image +# docker compose run sktime-mcp # run with stdio (interactive, for MCP clients) +# +# Notes: +# - MCP uses stdio transport, so `docker compose run` (with TTY) is the +# correct invocation rather than `docker compose up` (which is for daemons). +# - The models volume persists saved models across container restarts. +# ============================================================================= + +services: + sktime-mcp: + build: + context: . + dockerfile: Dockerfile + image: sktime-mcp:latest + container_name: sktime-mcp + + # stdin_open + tty are required for stdio-based MCP transport + stdin_open: true + tty: false # MCP JSON-RPC needs raw stdin, not a pseudo-TTY + + environment: + - SKTIME_MCP_LOG_LEVEL=${SKTIME_MCP_LOG_LEVEL:-WARNING} + - SKTIME_MCP_AUTO_FORMAT=${SKTIME_MCP_AUTO_FORMAT:-true} + - SKTIME_MCP_JOB_MAX_AGE_HOURS=${SKTIME_MCP_JOB_MAX_AGE_HOURS:-24} + - SKTIME_MCP_JOB_CLEANUP_INTERVAL=${SKTIME_MCP_JOB_CLEANUP_INTERVAL:-3600} + + volumes: + # Persist saved models outside the container + - sktime-models:/home/mcp/models + +volumes: + sktime-models: + driver: local