Skip to main content

Overview

Run the complete MCP Server with LangGraph stack locally with Docker Compose for development and testing. Includes all services: agent, OpenFGA, OpenTelemetry, Jaeger, Prometheus, and Grafana.
Quick Setup: Get the full stack running in 2 minutes with one script.

Quick Start

One-Command Setup

./scripts/setup/docker-compose-quickstart.sh
This script will:
  1. Check prerequisites (Docker, Docker Compose)
  2. Create .env from template if needed
  3. Validate configuration
  4. Build and start all services
  5. Wait for health checks
  6. Display service URLs
All services running! Agent, OpenFGA, Jaeger, Prometheus, and Grafana are now available.

Manual Setup

1

Create .env file

cp .env.example .env
Edit .env and add your API keys:
# At minimum, add one LLM API key
GOOGLE_API_KEY=your-key-here
# or
ANTHROPIC_API_KEY=sk-ant-your-key
# or
OPENAI_API_KEY=sk-your-key
2

Start services

docker compose up -d
First build takes 2-3 minutes. Subsequent starts are under 30 seconds.
3

Verify health

curl http://localhost:8000/health
Expected response:
{
  "status": "healthy",
  "service": "mcp-server-langgraph",
  "version": "1.0.0"
}

Services

Agent API

Port: 8000Main MCP agent service with LangGraphhttp://localhost:8000

OpenFGA

Port: 8080 (API)Authorization service (Playground disabled)http://localhost:8080

Jaeger

Port: 16686Distributed tracing UIhttp://localhost:16686

Prometheus

Port: 9090Metrics collectionhttp://localhost:9090

Grafana

Port: 3001Visualization dashboardshttp://localhost:3001

PostgreSQL

Port: 5432OpenFGA databaseInternal use

Development Mode

Use development mode for hot reload and debugging:
docker compose -f docker-compose.yml -f docker/docker-compose.dev.yml up
Development features:
  • 🔄 Hot reload - Code changes restart server automatically
  • 🐛 Debug logging - LOG_LEVEL=DEBUG
  • 📁 Volume mounts - Local code mounted in container
  • 🔍 Debugger port - Port 5678 for debugpy

Hot Reload Example

## Start in dev mode
docker compose -f docker-compose.yml -f docker/docker-compose.dev.yml up

## In another terminal, edit code
vim agent.py

## Save file - server automatically reloads!
## Check logs to see reload
docker compose logs -f agent

Testing

Run Tests

## Install test dependencies
uv sync

## Start services
docker compose up -d

## Wait for health
./scripts/wait-for-health.sh

## Run tests
pytest tests/

## Stop services
docker compose down

Test Agent Endpoint

## Simple health check
curl http://localhost:8000/health

## Test agent with message
curl -X POST http://localhost:8000/message \
  -H 'Content-Type: application/json' \
  -d '{
    "messages": [{
      "role": "user",
      "content": "What is the weather like?"
    }]
  }'

## Test with authentication (if enabled)
curl -X POST http://localhost:8000/message \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_JWT_TOKEN' \
  -d '{
    "messages": [{
      "role": "user",
      "content": "Hello!"
    }]
  }'

Configuration

Environment Variables

Configure via .env file:
## LLM Provider
LLM_PROVIDER=google
MODEL_NAME=gemini-2.5-flash-002
GOOGLE_API_KEY=your-key-here

## Authentication
JWT_SECRET_KEY=your-secret-key

## Observability
OBSERVABILITY_BACKEND=both  # opentelemetry, langsmith, both
LANGSMITH_TRACING=false  # Enable for LangSmith

Service URLs (Docker Compose)

Services communicate via Docker network:
## In docker-compose.yml, agent uses internal URLs:
OPENFGA_API_URL=http://openfga:8080
OTLP_ENDPOINT=http://otel-collector:4317

Custom Configuration

Override settings with environment variables:
## Use different model
MODEL_NAME=claude-sonnet-4-5-20250929 docker compose up

## Enable debug logging
LOG_LEVEL=DEBUG docker compose up

## Use OpenAI instead of Google
LLM_PROVIDER=openai MODEL_NAME=gpt-5.1 docker compose up

Observability

View Traces in Jaeger

1

Open Jaeger UI

2

Select Service

Choose mcp-server-langgraph from dropdown
3

Find Traces

Click “Find Traces” to see all requests with timing
4

Analyze

Click on trace to see:
  • LLM calls with prompts
  • Tool invocations
  • Timing breakdown
  • Error details

Prometheus Metrics

View metrics at http://localhost:9090:
## Request rate
rate(http_requests_total[5m])

## Error rate
rate(http_requests_total{status=~"5.."}[5m])

## Request duration
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

## LLM token usage
sum(llm_tokens_total) by (model)

Grafana Dashboards

Access at http://localhost:3001 (admin/admin): Pre-configured datasources:
  • Prometheus - Metrics
  • Jaeger - Traces
Create dashboards for:
  • Request volume and latency
  • Error rates
  • LLM token usage
  • System resources

OpenFGA Setup

Set up authorization model:
## Start services
docker compose up -d

## Wait for OpenFGA
sleep 5

## Run setup script
python scripts/setup_openfga.py

## Copy store and model IDs to .env
## OPENFGA_STORE_ID=...
## OPENFGA_MODEL_ID=...

## Restart agent to use new IDs
docker compose restart agent

Common Commands

# Production mode
docker compose up -d

# Development mode with hot reload
docker compose -f docker-compose.yml -f docker/docker-compose.dev.yml up

# Build from scratch
docker compose up -d --build

# Start specific service
docker compose up -d agent
# All services
docker compose logs -f

# Specific service
docker compose logs -f agent

# Last 100 lines
docker compose logs --tail=100 agent

# Since timestamp
docker compose logs --since 2025-10-10T10:00:00
# Stop all
docker compose down

# Stop and remove volumes (clean slate)
docker compose down -v

# Stop specific service
docker compose stop agent
# Execute shell in running container
docker compose exec agent /bin/bash

# View environment variables
docker compose exec agent env

# Check Python packages
docker compose exec agent pip list

# Run Python script
docker compose exec agent python -c "import sys; print(sys.version)"
# Restart agent after code changes (production mode)
docker compose restart agent

# Rebuild and restart
docker compose up -d --build agent
# Run 3 agent replicas (requires load balancer)
docker compose up -d --scale agent=3

# Note: Need to configure load balancer for multiple replicas

Troubleshooting

Check logs:
docker compose logs agent
Common causes:
  • Missing API key in .env
  • Invalid API key
  • Port 8000 already in use
  • OpenFGA not ready
Solutions:
# Verify .env has API key
grep API_KEY .env

# Check port
lsof -i :8000

# Restart with fresh build
docker compose down
docker compose up -d --build
Symptom: Bind for 0.0.0.0:8000 failed: port is already allocatedSolution: Change ports in docker-compose.yml:
agent:
  ports:
    - "8001:8000"  # Map 8001 external to 8000 internal
Symptom: Connection refused errorsCheck:
# Verify all services on same network
docker network inspect mcp_server_langgraph_observability

# Verify service names resolve
docker compose exec agent ping openfga
Solution: Ensure all services use networks: [observability]
Solutions:
  • Use BuildKit: DOCKER_BUILDKIT=1 docker compose build
  • Cache dependencies: Mount pip cache
  • Use lighter base images: Already using python:3.12-slim
Clean up:
# Remove unused images
docker image prune -a

# Remove unused volumes
docker volume prune

# Remove all stopped containers
docker container prune

# Nuclear option - remove everything
docker system prune -a --volumes

Production Considerations

Docker Compose is not recommended for production. Use for development and testing only.
For production, use:
  • LangGraph Platform - Serverless, managed hosting
  • Cloud Run - Serverless GCP deployment
  • Kubernetes - Production-grade orchestration

Why Not Docker Compose in Production?

FeatureDocker ComposeProduction Platforms
ScalingManual, single hostAuto-scaling, multi-host
High Availability❌ Single point of failure✅ Replicas, health checks
Load Balancing❌ Limited✅ Built-in
Secrets⚠️ Environment files✅ Encrypted, rotated
Monitoring⚠️ Basic✅ Enterprise-grade
Updates⚠️ Manual, downtime✅ Rolling, zero-downtime

Next Steps


Ready to develop? Run ./scripts/setup/docker-compose-quickstart.sh to start coding!