diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml index e8b2f150f04..b88d79f9b10 100644 --- a/.github/workflows/archie.lock.yml +++ b/.github/workflows/archie.lock.yml @@ -153,6 +153,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -370,6 +380,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -426,12 +471,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index 5a31212caf4..f6cafa6558e 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -181,13 +181,18 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - name: Set up Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6 - with: - cache: true - go-version-file: go.mod - name: Install dependencies run: make deps-dev - env: @@ -485,6 +490,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -559,20 +599,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/daily-file-diet.lock.yml b/.github/workflows/daily-file-diet.lock.yml index 4f76f777b44..c18e31c79e9 100644 --- a/.github/workflows/daily-file-diet.lock.yml +++ b/.github/workflows/daily-file-diet.lock.yml @@ -113,6 +113,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -368,6 +378,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -424,12 +469,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index 1d46e9aff7d..141cb77b520 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -112,6 +112,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -415,6 +425,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -468,20 +513,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/duplicate-code-detector.lock.yml b/.github/workflows/duplicate-code-detector.lock.yml index f9b2da3eee9..82a54e65942 100644 --- a/.github/workflows/duplicate-code-detector.lock.yml +++ b/.github/workflows/duplicate-code-detector.lock.yml @@ -106,6 +106,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -356,6 +366,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -400,20 +445,7 @@ jobs: env_vars = ["GH_AW_MCP_LOG_DIR", "GH_AW_SAFE_OUTPUTS", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKSPACE", "DEFAULT_BRANCH"] [mcp_servers.serena] - container = "ghcr.io/oraios/serena:latest" - args = [ - "--network", - "host", - ] - entrypoint = "serena" - entrypointArgs = [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ] - mounts = ["${{ github.workspace }}:${{ github.workspace }}:rw"] + url = "http://host.docker.internal:9121" EOF # Generate JSON config for MCP gateway @@ -450,20 +482,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index 0d6e951ebba..3f3cb4ccf62 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -112,6 +112,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -367,6 +377,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -423,12 +468,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/go-fan.lock.yml b/.github/workflows/go-fan.lock.yml index 5a440df0959..81dd77f5212 100644 --- a/.github/workflows/go-fan.lock.yml +++ b/.github/workflows/go-fan.lock.yml @@ -111,6 +111,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -351,6 +361,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -404,20 +449,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml index 69591a2cd6c..ddc1c0fd58a 100644 --- a/.github/workflows/jsweep.lock.yml +++ b/.github/workflows/jsweep.lock.yml @@ -113,6 +113,12 @@ jobs: with: node-version: '20' package-manager-cache: false + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Install Node.js dependencies @@ -372,6 +378,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -428,12 +469,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index b78d5ed5621..59b8b854166 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -127,6 +127,10 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' - name: Setup Node.js uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: @@ -140,11 +144,6 @@ jobs: uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - name: Set up Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6 - with: - cache: true - go-version-file: go.mod - name: Install dependencies run: make deps-dev - env: @@ -435,6 +434,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -726,12 +760,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" }, "tavily": { "type": "http", diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index 420c2c52d2e..0e9138ff724 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -176,13 +176,18 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - - name: Set up Go - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6 - with: - cache: true - go-version-file: go.mod - name: Install dependencies run: make deps-dev - env: @@ -482,6 +487,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -545,12 +585,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" }, "tavily": { "type": "http", diff --git a/.github/workflows/repository-quality-improver.lock.yml b/.github/workflows/repository-quality-improver.lock.yml index f2e35a96a1c..e47b9daec25 100644 --- a/.github/workflows/repository-quality-improver.lock.yml +++ b/.github/workflows/repository-quality-improver.lock.yml @@ -111,6 +111,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -358,6 +368,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -414,12 +459,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 1135d978a36..8fe18650ea5 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -138,6 +138,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -572,6 +582,41 @@ jobs: bash /opt/gh-aw/actions/start_safe_inputs_server.sh + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -653,20 +698,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" }, "tavily": { "type": "http", diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index f6bfb0c3321..a30243631fb 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -137,6 +137,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -599,6 +609,41 @@ jobs: bash /opt/gh-aw/actions/start_safe_inputs_server.sh + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -669,20 +714,7 @@ jobs: env_vars = ["GH_AW_MCP_LOG_DIR", "GH_AW_SAFE_OUTPUTS", "GH_AW_SAFE_OUTPUTS_CONFIG_PATH", "GH_AW_SAFE_OUTPUTS_TOOLS_PATH", "GH_AW_ASSETS_BRANCH", "GH_AW_ASSETS_MAX_SIZE_KB", "GH_AW_ASSETS_ALLOWED_EXTS", "GITHUB_REPOSITORY", "GITHUB_SERVER_URL", "GITHUB_SHA", "GITHUB_WORKSPACE", "DEFAULT_BRANCH"] [mcp_servers.serena] - container = "ghcr.io/oraios/serena:latest" - args = [ - "--network", - "host", - ] - entrypoint = "serena" - entrypointArgs = [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ] - mounts = ["${{ github.workspace }}:${{ github.workspace }}:rw"] + url = "http://host.docker.internal:9121" [mcp_servers.tavily] url = "https://mcp.tavily.com/mcp/" @@ -747,20 +779,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" }, "tavily": { "type": "http", diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml index 37f28c781e9..0dd374c97ff 100644 --- a/.github/workflows/smoke-copilot.lock.yml +++ b/.github/workflows/smoke-copilot.lock.yml @@ -132,6 +132,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh # Cache memory file share configuration from frontmatter processed below @@ -472,6 +482,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -535,12 +580,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/terminal-stylist.lock.yml b/.github/workflows/terminal-stylist.lock.yml index 66d84881a02..db0ffb1230b 100644 --- a/.github/workflows/terminal-stylist.lock.yml +++ b/.github/workflows/terminal-stylist.lock.yml @@ -102,6 +102,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -336,6 +346,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -392,12 +437,8 @@ jobs: } }, "serena": { - "type": "stdio", - "container": "ghcr.io/oraios/serena:latest", - "args": ["--network", "host"], - "entrypoint": "serena", - "entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "type": "http", + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/.github/workflows/typist.lock.yml b/.github/workflows/typist.lock.yml index 829163667ad..0b7b8a9c5a2 100644 --- a/.github/workflows/typist.lock.yml +++ b/.github/workflows/typist.lock.yml @@ -109,6 +109,16 @@ jobs: uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: persist-credentials: false + - name: Setup Go + uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0 + with: + go-version: '1.25' + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: '3.12' + - name: Setup uv + uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2 - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Configure Git credentials @@ -338,6 +348,41 @@ jobs: } } EOF + - name: Start Serena MCP HTTP Server + id: serena-start + run: | + set -eo pipefail + mkdir -p /tmp/gh-aw/mcp-logs/serena + + echo "Starting Serena MCP HTTP server on port 9121..." + + # Start Serena MCP server in background with uvx + uvx --from git+https://github.com/oraios/serena \ + serena start-mcp-server \ + --transport streamable-http \ + --port 9121 \ + --project "${{ github.workspace }}" \ + > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 & + + # Save PID for potential cleanup + echo $! > /tmp/gh-aw/serena-mcp-server.pid + + # Wait for server to start (max 30 seconds) + echo "Waiting for Serena MCP server to start..." + for i in {1..30}; do + if curl -s http://localhost:9121/health > /dev/null 2>&1; then + echo "Serena MCP server is ready" + break + fi + if [ $i -eq 30 ]; then + echo "ERROR: Serena MCP server failed to start within 30 seconds" + echo "Server logs:" + cat /tmp/gh-aw/mcp-logs/serena/server.log || true + exit 1 + fi + sleep 1 + done + - name: Start MCP gateway id: start-mcp-gateway env: @@ -391,20 +436,7 @@ jobs: } }, "serena": { - "container": "ghcr.io/oraios/serena:latest", - "args": [ - "--network", - "host" - ], - "entrypoint": "serena", - "entrypointArgs": [ - "start-mcp-server", - "--context", - "codex", - "--project", - "${{ github.workspace }}" - ], - "mounts": ["${{ github.workspace }}:${{ github.workspace }}:rw"] + "url": "http://host.docker.internal:9121" } }, "gateway": { diff --git a/actions/setup/sh/convert_gateway_config_claude.sh b/actions/setup/sh/convert_gateway_config_claude.sh index 639147cafe1..8ad92e3d935 100755 --- a/actions/setup/sh/convert_gateway_config_claude.sh +++ b/actions/setup/sh/convert_gateway_config_claude.sh @@ -74,7 +74,9 @@ jq --arg urlPrefix "$URL_PREFIX" ' .value |= ( (.type = "http") | (del(.tools)) | - # Fix the URL to use the correct domain + # Fix the URL to use the correct domain for gateway-proxied servers only + # URLs with /mcp/ prefix are gateway-proxied and need rewriting + # Direct HTTP servers (like Serena on localhost) should pass through unchanged .url |= (. | sub("^http://[^/]+/mcp/"; $urlPrefix + "/mcp/")) ) ) diff --git a/actions/setup/sh/convert_gateway_config_codex.sh b/actions/setup/sh/convert_gateway_config_codex.sh index 14c8107340a..833058e6b06 100755 --- a/actions/setup/sh/convert_gateway_config_codex.sh +++ b/actions/setup/sh/convert_gateway_config_codex.sh @@ -73,7 +73,15 @@ TOML_EOF jq -r --arg urlPrefix "$URL_PREFIX" ' .mcpServers | to_entries[] | "[mcp_servers.\(.key)]\n" + - "url = \"" + ($urlPrefix + "/mcp/" + .key) + "\"\n" + + # Use original URL if it doesn'\''t contain /mcp/ (direct HTTP servers like Serena) + # Otherwise construct gateway URL + "url = \"" + ( + if (.value.url | contains("/mcp/")) then + $urlPrefix + "/mcp/" + .key + else + .value.url + end + ) + "\"\n" + "http_headers = { Authorization = \"\(.value.headers.Authorization)\" }\n" ' "$MCP_GATEWAY_OUTPUT" >> /tmp/gh-aw/mcp-config/config.toml diff --git a/actions/setup/sh/convert_gateway_config_copilot.sh b/actions/setup/sh/convert_gateway_config_copilot.sh index 14f471bbd69..b601581b19a 100755 --- a/actions/setup/sh/convert_gateway_config_copilot.sh +++ b/actions/setup/sh/convert_gateway_config_copilot.sh @@ -39,7 +39,7 @@ echo "Target domain: $MCP_GATEWAY_DOMAIN:$MCP_GATEWAY_PORT" # { # "mcpServers": { # "server-name": { -# "type": "http", +# "type": "http" or "stdio", # "url": "http://domain:port/mcp/server-name", # "headers": { # "Authorization": "apiKey" @@ -52,7 +52,7 @@ echo "Target domain: $MCP_GATEWAY_DOMAIN:$MCP_GATEWAY_PORT" # { # "mcpServers": { # "server-name": { -# "type": "http", +# "type": "http" or "local", # "url": "http://domain:port/mcp/server-name", # "headers": { # "Authorization": "apiKey" @@ -62,9 +62,11 @@ echo "Target domain: $MCP_GATEWAY_DOMAIN:$MCP_GATEWAY_PORT" # } # } # -# The main differences: +# The main differences for Copilot: # 1. Copilot requires the "tools" field -# 2. URLs must use the correct domain (host.docker.internal) for container access +# 2. Copilot uses "local" instead of "stdio" for containerized servers +# 3. HTTP servers keep "type": "http" and don't need conversion +# 4. URLs must use the correct domain (host.docker.internal) for container access # The gateway may output 0.0.0.0 or localhost which won't work from within containers # Build the correct URL prefix using the configured domain and port @@ -73,10 +75,13 @@ URL_PREFIX="http://${MCP_GATEWAY_DOMAIN}:${MCP_GATEWAY_PORT}" jq --arg urlPrefix "$URL_PREFIX" ' .mcpServers |= with_entries( .value |= ( + # Convert stdio to local for Copilot compatibility + (if .type == "stdio" then .type = "local" else . end) | # Add tools field if not present (if .tools then . else . + {"tools": ["*"]} end) | - # Fix the URL to use the correct domain - # Replace http://anything:port/mcp/ with http://domain:port/mcp/ + # Fix the URL to use the correct domain for gateway-proxied servers only + # URLs with /mcp/ prefix are gateway-proxied and need rewriting + # Direct HTTP servers (like Serena on localhost) should pass through unchanged .url |= (. | sub("^http://[^/]+/mcp/"; $urlPrefix + "/mcp/")) ) ) diff --git a/pkg/workflow/importable_tools_test.go b/pkg/workflow/importable_tools_test.go index edf29a89034..932fe922f0a 100644 --- a/pkg/workflow/importable_tools_test.go +++ b/pkg/workflow/importable_tools_test.go @@ -153,13 +153,19 @@ Uses imported serena tool. t.Error("Expected compiled workflow to contain serena tool") } - // Verify serena container (now using Docker instead of uvx) - if !strings.Contains(workflowData, "ghcr.io/oraios/serena:latest") { - t.Error("Expected compiled workflow to contain serena Docker container") + // Verify serena HTTP server setup (now using uvx with HTTP transport) + if !strings.Contains(workflowData, "Start Serena MCP HTTP Server") { + t.Error("Expected compiled workflow to contain Serena HTTP server startup step") + } + if !strings.Contains(workflowData, "uvx --from git+https://github.com/oraios/serena") { + t.Error("Expected compiled workflow to use uvx to start Serena") + } + if !strings.Contains(workflowData, "http://host.docker.internal:9121") { + t.Error("Expected compiled workflow to contain Serena HTTP URL with host.docker.internal") } - // Verify that language service setup steps are NOT present - // since Serena now runs in a container with language services included + // Verify that language service setup steps ARE present + // since Serena now runs with uvx on the host and needs language runtimes if strings.Contains(workflowData, "Install Go language service") { t.Error("Did not expect Go language service installation step (Serena runs in container)") } @@ -318,8 +324,8 @@ Uses all imported tools. if !strings.Contains(workflowData, "mcr.microsoft.com/playwright/mcp") { t.Error("Expected compiled workflow to contain playwright Docker image") } - if !strings.Contains(workflowData, "ghcr.io/oraios/serena:latest") { - t.Error("Expected compiled workflow to contain serena Docker container") + if !strings.Contains(workflowData, "http://host.docker.internal:9121") { + t.Error("Expected compiled workflow to contain Serena HTTP URL with host.docker.internal") } if !strings.Contains(workflowData, "example.com") { t.Error("Expected compiled workflow to contain example.com domain for playwright") @@ -391,19 +397,18 @@ Uses imported serena with language config. t.Error("Expected compiled workflow to contain serena tool") } - // Verify that language runtime setup steps are NOT present - // since Serena now runs in a container with language services included - if strings.Contains(workflowData, "Setup Go") { - t.Error("Did not expect Go setup step (Serena runs in container)") + // Verify that runtime setup steps ARE present for Serena languages + // since Serena now runs with uvx on the host and needs language runtimes + if !strings.Contains(workflowData, "Setup Go") { + t.Error("Expected Go setup step (Serena needs Go runtime)") } - - if strings.Contains(workflowData, "Setup Node.js") { - t.Error("Did not expect Node.js setup step (Serena runs in container)") + if !strings.Contains(workflowData, "Setup Node.js") { + t.Error("Expected Node.js setup step (Serena needs Node for TypeScript)") } - // Verify serena container is present - if !strings.Contains(workflowData, "ghcr.io/oraios/serena") { - t.Error("Expected serena to use Docker container") + // Verify serena HTTP server is started with uvx + if !strings.Contains(workflowData, "uvx --from git+https://github.com/oraios/serena") { + t.Error("Expected serena to use uvx for HTTP server") } } diff --git a/pkg/workflow/mcp-config.go b/pkg/workflow/mcp-config.go index eb1851ef586..cf81b5c8d8e 100644 --- a/pkg/workflow/mcp-config.go +++ b/pkg/workflow/mcp-config.go @@ -146,55 +146,20 @@ func renderPlaywrightMCPConfigWithOptions(yaml *strings.Builder, playwrightTool } // renderSerenaMCPConfigWithOptions generates the Serena MCP server configuration with engine-specific options -// Per MCP Gateway Specification v1.0.0 section 3.2.1, stdio-based MCP servers MUST be containerized. -// Uses Docker container format as specified by Serena: ghcr.io/oraios/serena:latest +// Serena now runs using uvx with HTTP transport in the agent job (not containerized) +// The HTTP server is started in a background step and accessed via http://host.docker.internal:9121 +// Note: host.docker.internal is used because the MCP gateway runs in a container and needs to reach the host func renderSerenaMCPConfigWithOptions(yaml *strings.Builder, serenaTool any, isLast bool, includeCopilotFields bool, inlineArgs bool) { - customArgs := getSerenaCustomArgs(serenaTool) - yaml.WriteString(" \"serena\": {\n") - // Add type field for Copilot (per MCP Gateway Specification v1.0.0, use "stdio" for containerized servers) + // Add type field for Copilot (HTTP transport) if includeCopilotFields { - yaml.WriteString(" \"type\": \"stdio\",\n") - } - - // Use Serena's Docker container image - yaml.WriteString(" \"container\": \"ghcr.io/oraios/serena:latest\",\n") - - // Docker runtime args (--network host for network access) - if inlineArgs { - yaml.WriteString(" \"args\": [\"--network\", \"host\"],\n") - } else { - yaml.WriteString(" \"args\": [\n") - yaml.WriteString(" \"--network\",\n") - yaml.WriteString(" \"host\"\n") - yaml.WriteString(" ],\n") - } - - // Serena entrypoint - yaml.WriteString(" \"entrypoint\": \"serena\",\n") - - // Entrypoint args for Serena MCP server - if inlineArgs { - yaml.WriteString(" \"entrypointArgs\": [\"start-mcp-server\", \"--context\", \"codex\", \"--project\", \"${{ github.workspace }}\"") - // Append custom args if present - writeArgsToYAMLInline(yaml, customArgs) - yaml.WriteString("],\n") - } else { - yaml.WriteString(" \"entrypointArgs\": [\n") - yaml.WriteString(" \"start-mcp-server\",\n") - yaml.WriteString(" \"--context\",\n") - yaml.WriteString(" \"codex\",\n") - yaml.WriteString(" \"--project\",\n") - yaml.WriteString(" \"${{ github.workspace }}\"") - // Append custom args if present - writeArgsToYAML(yaml, customArgs, " ") - yaml.WriteString("\n") - yaml.WriteString(" ],\n") + yaml.WriteString(" \"type\": \"http\",\n") } - // Add volume mount for workspace access - yaml.WriteString(" \"mounts\": [\"${{ github.workspace }}:${{ github.workspace }}:rw\"]\n") + // HTTP URL for Serena MCP server running on host + // Use host.docker.internal so the gateway container can reach the host + yaml.WriteString(" \"url\": \"http://host.docker.internal:9121\"\n") // Note: tools field is NOT included here - the converter script adds it back // for Copilot. This keeps the gateway config compatible with the schema. diff --git a/pkg/workflow/mcp_config_comprehensive_test.go b/pkg/workflow/mcp_config_comprehensive_test.go index 12c2aa8f57e..4dba3060fd0 100644 --- a/pkg/workflow/mcp_config_comprehensive_test.go +++ b/pkg/workflow/mcp_config_comprehensive_test.go @@ -574,15 +574,15 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) { inlineArgs: false, expectedContent: []string{ `"serena": {`, - `"container": "ghcr.io/oraios/serena:latest"`, - `"entrypoint": "serena"`, - `"entrypointArgs"`, - `"start-mcp-server"`, + `"url": "http://host.docker.internal:9121"`, ` },`, }, unexpectedContent: []string{ `"type"`, `"tools"`, + `"container"`, + `"entrypoint"`, + `"entrypointArgs"`, }, }, { @@ -593,12 +593,13 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) { inlineArgs: false, expectedContent: []string{ `"serena": {`, - `"container": "ghcr.io/oraios/serena:latest"`, + `"url": "http://host.docker.internal:9121"`, ` }`, }, unexpectedContent: []string{ `"type"`, `"tools"`, + `"container"`, ` },`, }, }, @@ -610,10 +611,12 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) { inlineArgs: false, expectedContent: []string{ `"serena": {`, - `"type": "stdio"`, - `"container": "ghcr.io/oraios/serena:latest"`, + `"type": "http"`, + `"url": "http://host.docker.internal:9121"`, + }, + unexpectedContent: []string{ + `"container"`, }, - unexpectedContent: []string{}, }, { name: "Serena config with inline args format", @@ -623,11 +626,13 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) { inlineArgs: true, expectedContent: []string{ `"serena": {`, - `"type": "stdio"`, - `"container": "ghcr.io/oraios/serena:latest"`, - `"entrypointArgs": ["start-mcp-server", "--context", "codex", "--project", "${{ github.workspace }}"]`, + `"type": "http"`, + `"url": "http://host.docker.internal:9121"`, + }, + unexpectedContent: []string{ + `"container"`, + `"entrypointArgs"`, }, - unexpectedContent: []string{}, }, { name: "Serena config with custom args", @@ -639,11 +644,14 @@ func TestRenderSerenaMCPConfigWithOptions(t *testing.T) { inlineArgs: false, expectedContent: []string{ `"serena": {`, - `"container": "ghcr.io/oraios/serena:latest"`, + `"url": "http://host.docker.internal:9121"`, + }, + unexpectedContent: []string{ + `"container"`, + // Note: custom args are now used in the startup step, not in MCP config `"--verbose"`, `"--debug"`, }, - unexpectedContent: []string{}, }, } diff --git a/pkg/workflow/mcp_renderer.go b/pkg/workflow/mcp_renderer.go index e93f445dfb4..d3d6663654a 100644 --- a/pkg/workflow/mcp_renderer.go +++ b/pkg/workflow/mcp_renderer.go @@ -185,40 +185,13 @@ func (r *MCPConfigRendererUnified) RenderSerenaMCP(yaml *strings.Builder, serena } // renderSerenaTOML generates Serena MCP configuration in TOML format -// Per MCP Gateway Specification v1.0.0 section 3.2.1, stdio-based MCP servers MUST be containerized. -// Uses Docker container format as specified by Serena: ghcr.io/oraios/serena:latest +// Serena now runs using uvx with HTTP transport in the agent job (not containerized) +// The HTTP server is started in a background step and accessed via http://host.docker.internal:9121 +// Note: host.docker.internal is used because the MCP gateway runs in a container and needs to reach the host func (r *MCPConfigRendererUnified) renderSerenaTOML(yaml *strings.Builder, serenaTool any) { - customArgs := getSerenaCustomArgs(serenaTool) - yaml.WriteString(" \n") yaml.WriteString(" [mcp_servers.serena]\n") - yaml.WriteString(" container = \"ghcr.io/oraios/serena:latest\"\n") - - // Docker runtime args (--network host for network access) - yaml.WriteString(" args = [\n") - yaml.WriteString(" \"--network\",\n") - yaml.WriteString(" \"host\",\n") - yaml.WriteString(" ]\n") - - // Serena entrypoint - yaml.WriteString(" entrypoint = \"serena\"\n") - - // Entrypoint args for Serena MCP server - yaml.WriteString(" entrypointArgs = [\n") - yaml.WriteString(" \"start-mcp-server\",\n") - yaml.WriteString(" \"--context\",\n") - yaml.WriteString(" \"codex\",\n") - yaml.WriteString(" \"--project\",\n") - yaml.WriteString(" \"${{ github.workspace }}\"") - - // Append custom args if present - writeArgsToYAML(yaml, customArgs, " ") - - yaml.WriteString("\n") - yaml.WriteString(" ]\n") - - // Add volume mount for workspace access - yaml.WriteString(" mounts = [\"${{ github.workspace }}:${{ github.workspace }}:rw\"]\n") + yaml.WriteString(" url = \"http://host.docker.internal:9121\"\n") } // RenderSafeOutputsMCP generates the Safe Outputs MCP server configuration diff --git a/pkg/workflow/mcp_servers.go b/pkg/workflow/mcp_servers.go index 1cb84a42e9b..a49d3828777 100644 --- a/pkg/workflow/mcp_servers.go +++ b/pkg/workflow/mcp_servers.go @@ -442,6 +442,68 @@ func (c *Compiler) generateMCPSetup(yaml *strings.Builder, tools map[string]any, yaml.WriteString(" \n") } + // Start Serena MCP HTTP server if serena tool is enabled + hasSerena := false + for _, toolName := range mcpTools { + if toolName == "serena" { + hasSerena = true + break + } + } + if hasSerena { + // Get Serena tool configuration for custom args + serenaTool := tools["serena"] + customArgs := getSerenaCustomArgs(serenaTool) + + yaml.WriteString(" - name: Start Serena MCP HTTP Server\n") + yaml.WriteString(" id: serena-start\n") + yaml.WriteString(" run: |\n") + yaml.WriteString(" set -eo pipefail\n") + yaml.WriteString(" mkdir -p /tmp/gh-aw/mcp-logs/serena\n") + yaml.WriteString(" \n") + yaml.WriteString(" echo \"Starting Serena MCP HTTP server on port 9121...\"\n") + yaml.WriteString(" \n") + yaml.WriteString(" # Start Serena MCP server in background with uvx\n") + yaml.WriteString(" uvx --from git+https://github.com/oraios/serena \\\n") + yaml.WriteString(" serena start-mcp-server \\\n") + yaml.WriteString(" --transport streamable-http \\\n") + yaml.WriteString(" --port 9121 \\\n") + yaml.WriteString(" --project \"${{ github.workspace }}\"") + + // Append custom args if present + if len(customArgs) > 0 { + yaml.WriteString(" \\\n") + for i, arg := range customArgs { + yaml.WriteString(" " + arg) + if i < len(customArgs)-1 { + yaml.WriteString(" \\\n") + } + } + } + yaml.WriteString(" \\\n") + yaml.WriteString(" > /tmp/gh-aw/mcp-logs/serena/server.log 2>&1 &\n") + yaml.WriteString(" \n") + yaml.WriteString(" # Save PID for potential cleanup\n") + yaml.WriteString(" echo $! > /tmp/gh-aw/serena-mcp-server.pid\n") + yaml.WriteString(" \n") + yaml.WriteString(" # Wait for server to start (max 30 seconds)\n") + yaml.WriteString(" echo \"Waiting for Serena MCP server to start...\"\n") + yaml.WriteString(" for i in {1..30}; do\n") + yaml.WriteString(" if curl -s http://localhost:9121/health > /dev/null 2>&1; then\n") + yaml.WriteString(" echo \"Serena MCP server is ready\"\n") + yaml.WriteString(" break\n") + yaml.WriteString(" fi\n") + yaml.WriteString(" if [ $i -eq 30 ]; then\n") + yaml.WriteString(" echo \"ERROR: Serena MCP server failed to start within 30 seconds\"\n") + yaml.WriteString(" echo \"Server logs:\"\n") + yaml.WriteString(" cat /tmp/gh-aw/mcp-logs/serena/server.log || true\n") + yaml.WriteString(" exit 1\n") + yaml.WriteString(" fi\n") + yaml.WriteString(" sleep 1\n") + yaml.WriteString(" done\n") + yaml.WriteString(" \n") + } + // Skip gateway setup if sandbox is disabled // When sandbox: false, MCP servers are configured without the gateway if !isSandboxDisabled(workflowData) { diff --git a/pkg/workflow/runtime_detection.go b/pkg/workflow/runtime_detection.go index a45fb6cd02e..e290fa80ac2 100644 --- a/pkg/workflow/runtime_detection.go +++ b/pkg/workflow/runtime_detection.go @@ -24,6 +24,11 @@ func DetectRuntimeRequirements(workflowData *WorkflowData) []RuntimeRequirement detectFromMCPConfigs(workflowData.ParsedTools, requirements) } + // Detect from Serena language configuration + if workflowData.ParsedTools != nil && workflowData.ParsedTools.Serena != nil { + detectFromSerenaLanguages(workflowData.ParsedTools.Serena, requirements) + } + // Detect from engine requirements if workflowData.EngineConfig != nil && len(workflowData.EngineConfig.Steps) > 0 { detectFromEngineSteps(workflowData.EngineConfig.Steps, requirements) @@ -129,9 +134,6 @@ func detectFromMCPConfigs(tools *ToolsConfig, requirements map[string]*RuntimeRe allTools := tools.ToMap() log.Printf("Scanning %d MCP configurations for runtime commands", len(allTools)) - // Note: Serena and other built-in MCP servers now run in containers and do not - // require runtime detection. Language services are provided inside the containers. - // Scan custom MCP tools for runtime commands // Skip containerized MCP servers as they don't need host runtime setup for _, tool := range tools.Custom { @@ -150,6 +152,113 @@ func detectFromMCPConfigs(tools *ToolsConfig, requirements map[string]*RuntimeRe } } +// detectFromSerenaLanguages detects runtime requirements based on Serena language configuration +// Serena now runs using uvx with HTTP transport in the agent job, requiring language runtimes +// to be installed on the host system +func detectFromSerenaLanguages(serenaConfig *SerenaToolConfig, requirements map[string]*RuntimeRequirement) { + if serenaConfig == nil { + return + } + + // uvx is always required to run Serena + uvRuntime := findRuntimeByID("uv") + if uvRuntime != nil { + runtimeSetupLog.Print("Serena detected, adding uv runtime requirement") + updateRequiredRuntime(uvRuntime, "", requirements) + } + + // Map to track which languages we need to process + languagesToProcess := make(map[string]string) // language name -> version + + // Check short syntax (array of language names) + if len(serenaConfig.ShortSyntax) > 0 { + runtimeSetupLog.Printf("Detecting runtimes from Serena short syntax: %v", serenaConfig.ShortSyntax) + for _, lang := range serenaConfig.ShortSyntax { + languagesToProcess[lang] = "" // No version specified in short syntax + } + } + + // Check long syntax (detailed language configuration) + if len(serenaConfig.Languages) > 0 { + runtimeSetupLog.Printf("Detecting runtimes from Serena long syntax: %d languages", len(serenaConfig.Languages)) + for lang, langConfig := range serenaConfig.Languages { + version := "" + if langConfig != nil && langConfig.Version != "" { + version = langConfig.Version + } + languagesToProcess[lang] = version + } + } + + // Map Serena languages to runtime IDs and add requirements + for lang, version := range languagesToProcess { + runtimeID := mapSerenaLanguageToRuntime(lang) + if runtimeID == "" { + // Language doesn't map to a known runtime (e.g., bash, markdown, yaml) + runtimeSetupLog.Printf("Skipping Serena language '%s' - no runtime mapping", lang) + continue + } + + runtime := findRuntimeByID(runtimeID) + if runtime != nil { + runtimeSetupLog.Printf("Adding runtime requirement for Serena language '%s' -> %s (version=%s)", lang, runtimeID, version) + updateRequiredRuntime(runtime, version, requirements) + } + } +} + +// mapSerenaLanguageToRuntime maps a Serena language identifier to a runtime ID +// Returns empty string if the language doesn't require a runtime setup +func mapSerenaLanguageToRuntime(serenaLang string) string { + // Mapping based on .serena/project.yml language list and available runtimes + languageMap := map[string]string{ + // Direct mappings + "go": "go", + "typescript": "node", // JavaScript/TypeScript use Node.js + "python": "python", + "java": "java", + "ruby": "ruby", + "haskell": "haskell", + "elixir": "elixir", + "rust": "rust", + + // Alternative names or variants + "python_jedi": "python", + "typescript_vts": "node", + "ruby_solargraph": "ruby", + "kotlin": "java", // Kotlin runs on JVM + "scala": "java", // Scala runs on JVM + "csharp": "dotnet", + "csharp_omnisharp": "dotnet", + "erlang": "elixir", // Erlang uses same runtime setup + + // Languages that don't need runtime setup (return empty string) + "bash": "", + "markdown": "", + "yaml": "", + + // Languages not in our runtime definitions (return empty string) + "cpp": "", + "clojure": "", + "dart": "", + "elm": "", + "fortran": "", + "julia": "", + "lua": "", + "nix": "", + "perl": "", + "php": "", + "r": "", + "rego": "", + "swift": "", + "terraform": "", + "zig": "", + "al": "", + } + + return languageMap[serenaLang] +} + // detectFromEngineSteps scans engine steps for runtime commands func detectFromEngineSteps(steps []map[string]any, requirements map[string]*RuntimeRequirement) { for _, step := range steps {