Skip to main content

Self-Hosting the Developer MCP

For teams that want to run their own MCP server instance instead of using the hosted endpoint at dev-mcp.waxell.dev.

Docker

Build and run the MCP server as a standalone container:

# From the agentforge repo root
docker build -f docker/developer-mcp/Dockerfile -t waxell-dev-mcp .

docker run -p 8004:8004 \
-e WAXELL_DEV_TRANSPORT=sse \
-e WAXELL_DEV_API_URL=https://app.your-domain.com \
waxell-dev-mcp

The server starts in SSE mode on port 8004 with a health check at /health.

Docker Compose

services:
developer-mcp:
build:
context: .
dockerfile: docker/developer-mcp/Dockerfile
ports:
- "8004:8004"
environment:
WAXELL_DEV_TRANSPORT: "sse"
WAXELL_DEV_API_URL: "https://app.your-domain.com"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8004/health"]
interval: 10s
timeout: 5s
retries: 3

Terraform (AWS Fargate)

The agentforge repo includes a Terraform module that deploys the MCP server to ECS Fargate with ALB routing.

What it provisions

  • ECS Fargate task — ARM64 architecture, configurable CPU/memory
  • ECS service — with load balancer integration and health check grace period
  • ALB target group — routes dev-mcp.{domain} to port 8004
  • ALB listener rule — HTTPS termination at the ALB, HTTP to the container
  • ECR repository — for storing Docker images with scan-on-push
  • CloudWatch Logs — log group with developer-mcp stream prefix

Key files

FilePurpose
terraform/modules/ecs/developer-mcp-task.tfECS task definition and service
terraform/modules/alb/main.tfALB target group and listener rule
terraform/main.tfECR repository and module wiring
terraform/modules/ecs/variables.tfCPU, memory, image, and target group variables

Configuration

The Terraform module accepts these variables:

VariableDescription
developer_mcp_imageECR image URI (e.g., 123456789.dkr.ecr.us-west-2.amazonaws.com/waxell-dev-developer-mcp:latest)
developer_mcp_cpuCPU units for the Fargate task
developer_mcp_memoryMemory in MB for the Fargate task
developer_mcp_target_group_arnARN of the ALB target group
domainYour domain (creates dev-mcp.{domain} ALB rule)

Environment variables set on the task

environment = [
{ name = "WAXELL_DEV_API_URL", value = "https://app.${var.domain}" },
{ name = "WAXELL_DEV_TRANSPORT", value = "sse" },
{ name = "WAXELL_DEV_HOST", value = "0.0.0.0" },
{ name = "WAXELL_DEV_PORT", value = "8004" },
]

Note: WAXELL_DEV_API_KEY is intentionally not set on the task. In SSE mode, each connected client sends their own API key via the Authorization header.

Connecting Clients to Your Instance

Point your MCP client at your self-hosted SSE endpoint:

{
"mcpServers": {
"waxell": {
"type": "sse",
"url": "https://dev-mcp.your-domain.com/sse",
"headers": {
"Authorization": "Bearer wax_sk_your_key_here"
}
}
}
}

Health Check

The server exposes a GET /health endpoint that returns:

{"status": "ok", "service": "waxell-dev-mcp"}

This is used by Docker health checks, ALB target group health checks, and ECS service stability monitoring.