#!/usr/bin/env bash # Start 4 web-dev-mcp containers (one workspace each) for Codex, and merge # examples/codex/config.toml into ~/.codex/config.toml (idempotent managed block). # # Edit the WORKSPACE_* paths below, then run: # chmod +x examples/codex/run-workspaces.sh # ./examples/codex/run-workspaces.sh set -euo pipefail IMAGE='192.168.3.80/melabidi/mcp_web_dev_server:latest' SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" EXAMPLE_CONFIG="${SCRIPT_DIR}/config.toml" CODEX_DIR="${HOME}/.codex" CODEX_CONFIG="${CODEX_DIR}/config.toml" MANAGED_BEGIN='# BEGIN web-dev-mcp managed block' MANAGED_END='# END web-dev-mcp managed block' # --- edit these four absolute paths --- WORKSPACE_1='/Volumes/ExternalApps/repos/car_management_system' WORKSPACE_2='/Volumes/ExternalApps/repos/alrahma_sunday_school' WORKSPACE_3='/Volumes/ExternalApps/repos/alrahma_sunday_school_api' WORKSPACE_4='/Volumes/ExternalApps/repos/alrahma_web_client' NAMES=(web-dev-ws1 web-dev-ws2 web-dev-ws3 web-dev-ws4) PORTS=(3939 3940 3941 3942) PATHS=("$WORKSPACE_1" "$WORKSPACE_2" "$WORKSPACE_3" "$WORKSPACE_4") merge_codex_config() { if [[ ! -f "$EXAMPLE_CONFIG" ]]; then echo "error: missing example config: $EXAMPLE_CONFIG" >&2 exit 1 fi mkdir -p "$CODEX_DIR" if [[ ! -f "$CODEX_CONFIG" ]]; then : > "$CODEX_CONFIG" fi local block_file out_file block_file="$(mktemp)" out_file="$(mktemp)" # shellcheck disable=SC2064 trap "rm -f '$block_file' '$out_file'" RETURN { printf '%s\n' "$MANAGED_BEGIN" printf '%s\n' '# Managed by examples/codex/run-workspaces.sh — do not edit by hand.' # Keep only [mcp_servers.*] tables (drop leading comment preamble). awk '/^\[mcp_servers\./ { keep=1 } keep { print }' "$EXAMPLE_CONFIG" printf '%s\n' "$MANAGED_END" } > "$block_file" if ! grep -q '^\[mcp_servers\.' "$block_file"; then echo "error: no [mcp_servers.*] tables found in $EXAMPLE_CONFIG" >&2 exit 1 fi if grep -Fq "$MANAGED_BEGIN" "$CODEX_CONFIG" && grep -Fq "$MANAGED_END" "$CODEX_CONFIG"; then awk -v begin="$MANAGED_BEGIN" -v end="$MANAGED_END" -v block_file="$block_file" ' $0 == begin { while ((getline line < block_file) > 0) print line close(block_file) skip=1 next } $0 == end { skip=0; next } !skip { print } ' "$CODEX_CONFIG" > "$out_file" echo "Updated managed MCP block in ${CODEX_CONFIG}" else # Drop any prior unmanaged copies of these server tables, then append. awk ' /^\[mcp_servers\.web-dev-ws[1-4]\]/ { skip=1; next } /^\[/ { skip=0 } !skip { print } ' "$CODEX_CONFIG" > "$out_file" if [[ -s "$out_file" ]] && [[ -n "$(tail -c1 "$out_file" 2>/dev/null || true)" ]]; then printf '\n' >> "$out_file" fi cat "$block_file" >> "$out_file" echo "Merged MCP servers into ${CODEX_CONFIG}" fi mv "$out_file" "$CODEX_CONFIG" rm -f "$block_file" trap - RETURN } merge_codex_config for i in "${!NAMES[@]}"; do name="${NAMES[$i]}" port="${PORTS[$i]}" path="${PATHS[$i]}" if [[ ! -d "$path" ]]; then echo "error: workspace path does not exist: $path" >&2 exit 1 fi docker rm -f "$name" >/dev/null 2>&1 || true # Default MCP_HTTP_HOST=127.0.0.1 inside the image — no token needed. # Publish to host loopback so only this machine can reach the MCP port. docker run -d \ --name "$name" \ --restart unless-stopped \ -p "127.0.0.1:${port}:3939" \ -v "${path}:/workspace" \ "$IMAGE" echo "Started ${name} -> http://127.0.0.1:${port}/mcp (${path})" done echo echo "Codex MCP endpoints (merged into ${CODEX_CONFIG}):" for i in "${!NAMES[@]}"; do echo " ${NAMES[$i]}: http://127.0.0.1:${PORTS[$i]}/mcp" done