Files
APAW/docker/mcp-gitea/docker-compose.yml
NW 06fb0421ef fix(process-continuity): operator-free design for MCP Docker integration
- Resolve service_healthy deadlock by using service_started instead
- Fix 172.28.0.0/16 network collision by removing ipam config
- Add HybridGiteaClient (mcp → rest → bash fallback)
- Create .kilo/rules/process-continuity.md with 5 operator-free principles:
  1. No service_healthy conditions
  2. No hardcoded networks
  3. Automatic fallback chains
  4. Pre-flight validation
  5. Self-documenting failures
- Update docker-compose.yml with resilient config:
  - start_period: 60s, retries: 5, restart: on-failure:3
  - /tools healthcheck (guaranteed endpoint)
  - tmpfs for Node.js /tmp
  - Resource limits: 256M RAM, 0.5 CPU
- MCP/REST integration test passed (issue #109)

Refs: Milestone #67, Issues #107, #109
2026-05-08 22:31:59 +01:00

88 lines
2.7 KiB
YAML

# GNS-2: MCP Gitea Integration Container
# Operator-Free Design — lessons learned from Phase 8 failures
# See: .kilo/rules/process-continuity.md
#
# FIXED: No service_healthy deadlock, no hardcoded IP, no SSE-only transport
# Uses Hybrid MCP↔REST client with automatic fallback
# MCP SSE supported for clients that support it; REST fallback for shell
services:
mcp-gitea:
build:
context: https://github.com/Sqcows/forgejo-mcp.git#main
dockerfile: Dockerfile
container_name: mcp-gitea
environment:
# Gitea/Forgejo instance config
FORGEJO_URL: https://git.softuniq.eu
# Fallback dummy token allows container startup; replace in .env
FORGEJO_TOKEN: ${FORGEJO_TOKEN:-dummy-fallback-token}
# MCP server HTTP mode
PORT: 3001
FORGEJO_MCP_API_KEY: ${FORGEJO_MCP_API_KEY:-changeme}
RATE_LIMIT_MAX: 1000
RATE_LIMIT_WINDOW_MS: 60000
LOG_LEVEL: info
ports:
- "3001:3001"
networks:
- gns-network
# Resilience: on-failure with generous start window
restart: on-failure:3
stop_grace_period: 10s
healthcheck:
# /tools is always available (list of 103 tools)
test: ["CMD", "wget", "-qO-", "http://localhost:3001/tools"]
interval: 15s
timeout: 10s
retries: 5
start_period: 60s
# Security: non-root user built into Dockerfile; no new privileges
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
# tmpfs for Node.js /tmp needs (read-write, but noexec)
tmpfs:
- /tmp:noexec,nosuid,size=50m
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
# Optional metrics sidecar — NO service_health dependency
# Starts even if main container unhealthy; checks periodically
mcp-gitea-health:
image: busybox:latest
container_name: mcp-gitea-health
command: >
sh -c "
sleep 30; # Wait for main container to start
while true; do
if wget -qO- http://mcp-gitea:3001/tools > /dev/null 2>&1; then
echo '$(date -u +%Y-%m-%dT%H:%M:%SZ) MCP Gitea: HEALTHY';
else
echo '$(date -u +%Y-%m-%dT%H:%M:%SZ) MCP Gitea: UNHEALTHY';
fi;
sleep 30;
done
"
networks:
- gns-network
depends_on:
mcp-gitea:
condition: service_started # Just wait for start, not healthy
restart: on-failure:3
networks:
gns-network:
driver: bridge
# --- Operator check after start ---
# Run: docker compose -f docker/mcp-gitea/docker-compose.yml logs -f mcp-gitea
# Look for: "HTTP server listening on port 3001"
# Then test: curl http://localhost:3001/tools | head