feat: Add Docker infrastructure with Caddy and startup scripts (#25, #26)

Issue #25 - Docker multi-service infrastructure:
- Create docker/Dockerfile with multi-stage build, git support, port 8080
- Create docker/docker-compose.yml with app + Caddy services
- Create docker/Caddyfile for HTTPS termination and reverse proxy
- Create docker/.env.example with configuration template

Issue #26 - Startup scripts and tests:
- Create scripts/start.sh for production startup with env validation
- Create scripts/healthcheck.sh for Docker health checks
- Add health endpoint tests to test_mcp_endpoints.py
- Fix middleware order (HealthCheckBypass must wrap BearerAuth)
- Fix pyproject.toml testpaths to use 'tests' directory
- Update test_config.py for new defaults (0.0.0.0:8080)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 21:11:29 -05:00
parent 9fea0683f7
commit 88c16c840b
10 changed files with 345 additions and 15 deletions

View File

@@ -1,4 +1,4 @@
"""Tests for MCP protocol endpoints."""
"""Tests for MCP protocol endpoints and health checks."""
import pytest
import json
import re
@@ -26,6 +26,35 @@ def client(mock_env):
return TestClient(app)
# =============================================================================
# Health Endpoint Tests
# =============================================================================
def test_health_endpoint(client):
"""Test GET /health returns status ok."""
response = client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "ok"
def test_health_endpoint_no_auth_required(mock_env):
"""Test health endpoint works even with AUTH_TOKEN set."""
with patch.dict("os.environ", {**mock_env, "AUTH_TOKEN": "secret123"}):
app = create_app()
client = TestClient(app)
# Health should bypass auth
response = client.get("/health")
assert response.status_code == 200
assert response.json()["status"] == "ok"
# =============================================================================
# MCP Protocol Tests
# =============================================================================
def parse_sse_message(sse_text: str) -> dict:
"""Parse SSE message data."""
data_match = re.search(r'data: (.+)', sse_text)