cf-integration 0.3.1

Integration and conformance harness for ContextForge control-plane and data-plane services
Documentation
# Integration helpers for cf-controlplane + cf-dataplane.
#
# Combine with cf-controlplane docker-compose.yml and docker-compose.cf-dataplane.yaml.

services:
  # Fast Time registration is stock upstream; the dataplane waits for it so
  # the publisher has the fixed virtual server to publish.
  dataplane:
    depends_on:
      redis:
        condition: service_started
      register_fast_time:
        condition: service_completed_successfully

  locust:
    volumes:
      # Harness locustfile with streamable-HTTP content negotiation; the
      # upstream locustfile_mcp_protocol.py sends Accept: application/json
      # and gets HTTP 406 from the dataplane route. Mounted in its own
      # directory because /mnt/locust is a read-only bind mount.
      - ${CF_INTEGRATION_ROOT:?Set CF_INTEGRATION_ROOT to the integration harness root}/scripts/locustfile_mcp.py:/mnt/locust-cf/locustfile_mcp.py:ro
    environment:
      - MCPGATEWAY_BEARER_TOKEN=${MCPGATEWAY_BEARER_TOKEN:-}
      - PLATFORM_ADMIN_EMAIL=${PLATFORM_ADMIN_EMAIL:-admin@example.com}
      - LOCUST_MODE=${LOCUST_MODE:-headless}
      - LOCUST_LOCUSTFILE=${LOCUST_LOCUSTFILE:-locustfile_mcp.py}
      - LOCUST_USERS=${LOCUST_USERS:-100}
      - LOCUST_SPAWN_RATE=${LOCUST_SPAWN_RATE:-10}
      - LOCUST_RUN_TIME=${LOCUST_RUN_TIME:-5m}
      - LOCUST_REQUEST_TIMEOUT_SECONDS=${LOCUST_REQUEST_TIMEOUT_SECONDS:-60}
      - MCP_SERVER_ID=${MCP_SERVER_ID:-}
      - MCP_SERVER_IDS=${MCP_SERVER_IDS:-}
      - MCP_TOOL_NAMES=${MCP_TOOL_NAMES:-}
      - MCP_SKIP_TOOL_LIST=${MCP_SKIP_TOOL_LIST:-false}
      - MCP_PROTOCOL_VERSION=${MCP_PROTOCOL_VERSION:-2026-07-28}
      - LOCUST_LOG_LEVEL=${LOCUST_LOG_LEVEL:-INFO}
    command:
      - |
        set -eu
        if [ -z "$${MCPGATEWAY_BEARER_TOKEN:-}" ]; then
          echo "MCPGATEWAY_BEARER_TOKEN is required" >&2
          exit 2
        fi

        # Defaults come from the environment section above.
        if [ -f "/mnt/locust-cf/$$LOCUST_LOCUSTFILE" ]; then
          LOCUSTFILE="/mnt/locust-cf/$$LOCUST_LOCUSTFILE"
        else
          LOCUSTFILE="/mnt/locust/$$LOCUST_LOCUSTFILE"
        fi

        if [ "$$LOCUST_MODE" = "headless" ]; then
          exec locust -f "$$LOCUSTFILE" \
            --host=http://nginx:80 \
            --users="$$LOCUST_USERS" \
            --spawn-rate="$$LOCUST_SPAWN_RATE" \
            --run-time="$$LOCUST_RUN_TIME" \
            --headless \
            --html=/mnt/reports/locust_report.html \
            --csv=/mnt/reports/locust \
            --only-summary
        fi

        exec locust -f "$$LOCUSTFILE" \
          --host=http://nginx:80 \
          --web-host=0.0.0.0 --web-port=8089 \
          --master --expect-workers="$${LOCUST_EXPECT_WORKERS:-1}" \
          --class-picker