From dba67374152744a396096657459940ec7cdb8102 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Aug 2026 17:27:59 +0000 Subject: [PATCH 1/6] Enforce proxies for MCP-less engines Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/shared/aider.md | 7 +-- .github/workflows/smoke-aider.lock.yml | 53 +++++++++++++------ .github/workflows/smoke-aider.md | 1 - pkg/parser/schemas/main_workflow_schema.json | 5 ++ pkg/workflow/compiler_orchestrator_tools.go | 50 ++++++++++++++++- .../compiler_orchestrator_tools_test.go | 48 +++++++++++++++++ pkg/workflow/engine_definition.go | 10 ++-- 7 files changed, 148 insertions(+), 26 deletions(-) diff --git a/.github/workflows/shared/aider.md b/.github/workflows/shared/aider.md index 8e779de7195..da4caa6f71b 100644 --- a/.github/workflows/shared/aider.md +++ b/.github/workflows/shared/aider.md @@ -7,6 +7,7 @@ engine: display-name: Aider description: Aider AI pair programming CLI running in scripting (non-interactive) mode experimental: true + mcp: false provider: name: github behaviors: @@ -111,7 +112,7 @@ from `OPENAI_API_BASE`. Aider runs in scripting mode: the generated prompt file is passed with `--message-file` and all confirmations are auto-accepted (`--yes-always`). -Aider has no MCP client, so MCP-backed tools are unavailable. Disable the -GitHub MCP server with `tools: github: false` and rely on `bash:` tools, file -edits, and safe outputs written to `$GH_AW_SAFE_OUTPUTS` instead. +Aider has no MCP client, so the compiler exposes MCP-backed tools through +`cli-proxy` and GitHub access through `gh-proxy`. Both proxies are enabled +automatically and cannot be disabled for this engine. --> diff --git a/.github/workflows/smoke-aider.lock.yml b/.github/workflows/smoke-aider.lock.yml index 62f8541caf5..be20a9f5575 100644 --- a/.github/workflows/smoke-aider.lock.yml +++ b/.github/workflows/smoke-aider.lock.yml @@ -1,5 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"5fe6b30544a70de8a74d7ce1243d138d484002c8e8c62becf87ca8df44d43d5d","body_hash":"0cd234d798084dd1c3c97f233b49ed2ad218e5641feaa797a9330499e80f368f","strict":true,"agent_id":"aider","agent_model":"copilot/claude-sonnet-4.5"} -# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/setup-python","sha":"5fda3b95a4ea91299a34e894583c3862153e4b97","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43","digest":"sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43","digest":"sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43","digest":"sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.7","digest":"sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}],"has_pull_request":true} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"3568fc066a3d188f0117bd320d2c08c748c4773deb3c782d059a9900a4a27d0b","body_hash":"08a83d959fcc7013948642ced76171e3aebba9c49a0c98b2659bb66eff8e886e","strict":true,"agent_id":"aider","agent_model":"copilot/claude-sonnet-4.5"} +# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/cache/save","sha":"55cc8345863c7cc4c66a329aec7e433d2d1c52a9","version":"v6.1.0"},{"repo":"actions/checkout","sha":"3d3c42e5aac5ba805825da76410c181273ba90b1","version":"v7.0.1"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"820762786026740c76f36085b0efc47a31fe5020","version":"v7.0.0"},{"repo":"actions/setup-python","sha":"5fda3b95a4ea91299a34e894583c3862153e4b97","version":"v7.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43","digest":"sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43","digest":"sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43","digest":"sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43@sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43","digest":"sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.4.7","digest":"sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196","pinned_image":"ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196"},{"image":"ghcr.io/github/github-mcp-server:v1.8.0","digest":"sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520","pinned_image":"ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520"}],"has_pull_request":true} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # # ___ _ _ @@ -49,6 +49,7 @@ # Container images used: # - ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6 # - ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1 +# - ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43@sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab # - ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d # - ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00 # - ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 @@ -305,20 +306,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_b38486ab868ed8c3_EOF' + cat << 'GH_AW_PROMPT_88da2982c25c22f2_EOF' - GH_AW_PROMPT_b38486ab868ed8c3_EOF + GH_AW_PROMPT_88da2982c25c22f2_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_b38486ab868ed8c3_EOF' + cat << 'GH_AW_PROMPT_88da2982c25c22f2_EOF' Tools: add_comment(max:2), create_issue, add_labels, missing_tool, missing_data, noop - GH_AW_PROMPT_b38486ab868ed8c3_EOF + GH_AW_PROMPT_88da2982c25c22f2_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_b38486ab868ed8c3_EOF' + cat << 'GH_AW_PROMPT_88da2982c25c22f2_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -347,16 +348,16 @@ jobs: {{/if}} - GH_AW_PROMPT_b38486ab868ed8c3_EOF - cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + GH_AW_PROMPT_88da2982c25c22f2_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/cli_proxy_with_safeoutputs_prompt.md" if [ "$GITHUB_EVENT_NAME" = "issue_comment" ] && [ -n "$GH_AW_IS_PR_COMMENT" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review_comment" ] || [ "$GITHUB_EVENT_NAME" = "pull_request_review" ]; then cat "${RUNNER_TEMP}/gh-aw/prompts/pr_context_prompt.md" fi - cat << 'GH_AW_PROMPT_b38486ab868ed8c3_EOF' + cat << 'GH_AW_PROMPT_88da2982c25c22f2_EOF' {{#runtime-import .github/workflows/shared/aider.md}} {{#runtime-import .github/workflows/smoke-aider.md}} - GH_AW_PROMPT_b38486ab868ed8c3_EOF + GH_AW_PROMPT_88da2982c25c22f2_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -576,7 +577,7 @@ jobs: GH_AW_SKILL_DIR: ".aider/skills" run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" - name: Download container images - run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1 ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520 + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/gh-aw-firewall/agent:0.27.43@sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6 ghcr.io/github/gh-aw-firewall/api-proxy:0.27.43@sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1 ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.43@sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab ghcr.io/github/gh-aw-firewall/squid:0.27.43@sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d ghcr.io/github/gh-aw-mcpg:v0.4.7@sha256:7545220a9aca134b71e51193ee0eaf4c50756ebf8fbd25a63ae7556e62815c00 ghcr.io/github/gh-aw-node@sha256:0d9f1fb5fd6610c0ac1f5194a38e45a8a1e81f8a390d5142d8e4e6f26a4b3196 ghcr.io/github/github-mcp-server:v1.8.0@sha256:d5a18c04b92714c309eb46a2305087e91a4dbd80420f6e462656699f95093520 - name: Generate Safe Outputs Config run: | mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" @@ -763,9 +764,6 @@ jobs: GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_CONFIG_PATH }} GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS_TOOLS_PATH }} GH_AW_SINK_VISIBILITY: ${{ steps.determine-automatic-lockdown.outputs.visibility }} - GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }} - GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }} - GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eo pipefail @@ -784,6 +782,7 @@ jobs: export DEBUG="*" export GH_AW_ENGINE="aider" + export GH_AW_MCP_CLI_SERVERS='["safeoutputs"]' MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') source "${RUNNER_TEMP}/gh-aw/actions/resolve_docker_socket_gid.sh" @@ -810,6 +809,21 @@ jobs: id: pre_agent_audit continue-on-error: true run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" + - name: Start CLI Proxy + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_HOST: ${{ env.GH_HOST }} + GITHUB_HOST: ${{ env.GITHUB_HOST }} + GITHUB_ENTERPRISE_HOST: ${{ env.GITHUB_ENTERPRISE_HOST }} + GITHUB_GRAPHQL_URL: ${{ env.GITHUB_GRAPHQL_URL }} + GITHUB_COPILOT_BASE_URL: ${{ env.GITHUB_COPILOT_BASE_URL }} + GH_AW_NETWORK_ISOLATION: 'true' + CLI_PROXY_POLICY: '{"allow-only":{"repos":"${{ steps.determine-automatic-lockdown.outputs.repos }}","min-integrity":"${{ steps.determine-automatic-lockdown.outputs.min_integrity }}"}}' + CLI_PROXY_IMAGE: 'ghcr.io/github/gh-aw-mcpg:v0.4.7' + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/start_cli_proxy.sh" - name: Write Aider harness script run: | mkdir -p ${RUNNER_TEMP}/gh-aw/actions @@ -859,7 +873,7 @@ jobs: printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt (umask 177 && touch /tmp/gh-aw/agent-stdio.log) GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" - printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.43/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.githubusercontent.com\",\"*.pythonhosted.org\",\"anaconda.org\",\"api.github.com\",\"api.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"binstar.org\",\"bootstrap.pypa.io\",\"codeload.github.com\",\"conda.anaconda.org\",\"conda.binstar.org\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"docs.github.com\",\"files.pythonhosted.org\",\"github-cloud.githubusercontent.com\",\"github-cloud.s3.amazonaws.com\",\"github.blog\",\"github.com\",\"github.githubassets.com\",\"host.docker.internal\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"lfs.github.com\",\"objects.githubusercontent.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"patch-diff.githubusercontent.com\",\"patchdiff.githubusercontent.com\",\"pip.pypa.io\",\"ppa.launchpad.net\",\"pypi.org\",\"pypi.python.org\",\"raw.githubusercontent.com\",\"repo.anaconda.com\",\"repo.continuum.io\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.43,squid=sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d,agent=sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6,api-proxy=sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1,cli-proxy=sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.43/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.githubusercontent.com\",\"*.pythonhosted.org\",\"anaconda.org\",\"api.github.com\",\"api.githubcopilot.com\",\"api.snapcraft.io\",\"archive.ubuntu.com\",\"azure.archive.ubuntu.com\",\"binstar.org\",\"bootstrap.pypa.io\",\"codeload.github.com\",\"conda.anaconda.org\",\"conda.binstar.org\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"docs.github.com\",\"files.pythonhosted.org\",\"github-cloud.githubusercontent.com\",\"github-cloud.s3.amazonaws.com\",\"github.blog\",\"github.com\",\"github.githubassets.com\",\"host.docker.internal\",\"json-schema.org\",\"json.schemastore.org\",\"keyserver.ubuntu.com\",\"lfs.github.com\",\"objects.githubusercontent.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.microsoft.com\",\"patch-diff.githubusercontent.com\",\"patchdiff.githubusercontent.com\",\"pip.pypa.io\",\"ppa.launchpad.net\",\"pypi.org\",\"pypi.python.org\",\"raw.githubusercontent.com\",\"repo.anaconda.com\",\"repo.continuum.io\",\"s.symcb.com\",\"s.symcd.com\",\"security.ubuntu.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"www.googleapis.com\"],\"isolation\":true,\"topologyAttach\":[\"awmg-mcpg\",\"awmg-cli-proxy\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"maxCacheMisses\":5,\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.5\",\"gpt-5.6\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"auto\":[\"copilot/auto\",\"large\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\",\"kimi\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"detection\":[\"small\"],\"evals\":[\"small\"],\"fable\":[\"copilot/*fable*\",\"anthropic/*fable*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-3.6-flash\":[\"copilot/gemini-3.6*flash*\",\"google/gemini-3.6*flash*\",\"gemini/gemini-3.6*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-omni\":[\"copilot/gemini-omni*\",\"google/gemini-omni*\",\"gemini/gemini-omni*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.1\":[\"copilot/gpt-5.1*\",\"openai/gpt-5.1*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"gpt-5.6\":[\"copilot/gpt-5.6*\",\"openai/gpt-5.6*\"],\"grok\":[\"copilot/*grok*\",\"openai/*grok*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"image-generation\":[\"copilot/gpt-image*\",\"openai/gpt-image*\",\"openai/chatgpt-image*\",\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"google/imagen*\"],\"kimi\":[\"copilot/kimi*\",\"openai/kimi*\"],\"kiwi\":[\"copilot/kiwi*\",\"openai/kiwi*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"lyria\":[\"google/lyria*\",\"gemini/lyria*\",\"copilot/lyria*\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mai-code-1-flash-picker\":[\"copilot/MAI-Code-1-Flash-picker*\",\"copilot/mai-code-1-flash-picker*\",\"openai/MAI-Code-1-Flash-picker*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"raptor-mini\":[\"copilot/raptor*\",\"openai/raptor*\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-5*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\",\"anthropic/*sonnet-5*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"veo\":[\"google/veo*\",\"gemini/veo*\"],\"vision\":[\"copilot/gemini-*image*\",\"google/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.43,squid=sha256:26be5e0b8c8f4c41c8a59126b29bb5d80b07253597472ded2a16bdd75abcbf9d,agent=sha256:04e2d1987a565000a8f114b89d806ae7a3864dd4f944be65275b28c93d8690e6,api-proxy=sha256:d85f57975af5ea23af4996e41ed73fbc8f5b4a47402472bfe82e508f352cb0c1,cli-proxy=sha256:65c45ea2967984d0024f3df61bc71335658a77ede96c8d9665da7a5f33a795ab\"},\"logging\":{\"proxyLogsDir\":\"/tmp/gh-aw/sandbox/firewall/logs\",\"auditDir\":\"/tmp/gh-aw/sandbox/firewall/audit\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST="" @@ -877,7 +891,7 @@ jobs: fi fi # shellcheck disable=SC1003,SC2016,SC2086 - awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --skip-pull \ + awf --config "${RUNNER_TEMP}/gh-aw/awf-config.json" --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" ${GH_AW_TOOL_CACHE_MOUNT:+--mount "$GH_AW_TOOL_CACHE_MOUNT"} ${GH_AW_DOCKER_HOST:+--docker-host "$GH_AW_DOCKER_HOST"} --env-all --exclude-env ACTIONS_ID_TOKEN_REQUEST_TOKEN --exclude-env ACTIONS_ID_TOKEN_REQUEST_URL --exclude-env COPILOT_GITHUB_TOKEN --exclude-env GH_TOKEN --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env MCP_GATEWAY_API_KEY --log-level info --skip-pull --difc-proxy-host awmg-cli-proxy:18443 --difc-proxy-ca-cert /tmp/gh-aw/difc-proxy-tls/ca.crt \ -- /bin/bash -c 'set +o histexpand; export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH" && export no_proxy="${NO_PROXY:-}" && : "${RUNNER_TOOL_CACHE:?RUNNER_TOOL_CACHE must be set}"; GH_AW_TOOL_CACHE="$RUNNER_TOOL_CACHE"; export PATH="$(find "$GH_AW_TOOL_CACHE" -maxdepth 5 -type d -name bin 2>/dev/null | tr '\''\n'\'' '\'':'\'')$PATH"; [ -n "$GOROOT" ] && export PATH="$GOROOT/bin:$PATH" || true; [ -n "$ERLANG_HOME" ] && export PATH="$ERLANG_HOME/bin:$PATH" || true && GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/aider_harness.cjs aider --yes-always --no-auto-commits --no-check-update --no-show-release-notes --no-detect-urls --no-pretty --no-stream --no-fancy-input --analytics-disable' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log env: AIDER_ANALYTICS_DISABLE: true @@ -889,6 +903,7 @@ jobs: GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || github.token }} GITHUB_COPILOT_BASE_URL: http://host.docker.internal:10002 GITHUB_WORKSPACE: ${{ github.workspace }} NO_PROXY: localhost,127.0.0.1,host.docker.internal,host.docker.internal:10000,host.docker.internal:10001,host.docker.internal:10002,host.docker.internal:10003,172.30.0.30,172.30.0.30:10000,172.30.0.30:10001,172.30.0.30:10002,172.30.0.30:10003 @@ -897,6 +912,10 @@ jobs: OPENAI_BASE_URL: http://host.docker.internal:10002 RUNNER_TEMP: ${{ runner.temp }} TRACEPARENT: ${{ env.GITHUB_AW_OTEL_TRACE_ID != '' && env.GITHUB_AW_OTEL_PARENT_SPAN_ID != '' && format('00-{0}-{1}-01', env.GITHUB_AW_OTEL_TRACE_ID, env.GITHUB_AW_OTEL_PARENT_SPAN_ID) || '' }} + - name: Stop CLI Proxy + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/stop_cli_proxy.sh" - name: Configure Git credentials env: GITHUB_REPOSITORY: ${{ github.repository }} diff --git a/.github/workflows/smoke-aider.md b/.github/workflows/smoke-aider.md index 8a548cecc3e..90512972300 100644 --- a/.github/workflows/smoke-aider.md +++ b/.github/workflows/smoke-aider.md @@ -29,7 +29,6 @@ network: - defaults - github tools: - github: false edit: bash: - "*" diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 8527058d0ba..8f885a43a44 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -13116,6 +13116,11 @@ "type": "boolean", "description": "Marks the engine as experimental so compiled workflows can surface an explicit warning." }, + "mcp": { + "type": "boolean", + "description": "Whether the engine supports MCP. When false, the compiler automatically enables gh-proxy and cli-proxy and rejects attempts to disable either proxy.", + "default": true + }, "runtime-id": { "type": "string", "description": "Runtime adapter identifier. Maps to the CodingAgentEngine registered in the engine registry. Defaults to id when omitted." diff --git a/pkg/workflow/compiler_orchestrator_tools.go b/pkg/workflow/compiler_orchestrator_tools.go index e3ed7638a36..ead95b560f3 100644 --- a/pkg/workflow/compiler_orchestrator_tools.go +++ b/pkg/workflow/compiler_orchestrator_tools.go @@ -62,7 +62,7 @@ func (c *Compiler) processToolsAndMarkdown(result *parser.FrontmatterResult, cle if err != nil { return nil, err } - toolsData, err := c.resolveToolsConfiguration(result, effectiveMarkdown, markdownDir, importsResult, agenticEngine) + toolsData, err := c.resolveToolsConfiguration(result, effectiveMarkdown, markdownDir, importsResult, agenticEngine, engineSetting) if err != nil { return nil, err } @@ -174,6 +174,7 @@ func (c *Compiler) resolveToolsConfiguration( markdownDir string, importsResult *parser.ImportsResult, agenticEngine CodingAgentEngine, + engineSetting string, ) (*mergedToolsData, error) { topTools := extractToolsMapFromFrontmatter(result.Frontmatter) if err := ValidateToolsSection(topTools); err != nil { @@ -206,7 +207,15 @@ func (c *Compiler) resolveToolsConfiguration( orchestratorToolsLog.Printf("MCP configuration validation failed: %v", err) return nil, err } + tools, err = enforceMCPProxyTools(c.engineCatalog.Get(engineSetting), tools) + if err != nil { + return nil, err + } tools = c.adjustToolsForEngineCapabilities(result.Frontmatter, agenticEngine, tools) + tools, err = enforceMCPProxyTools(c.engineCatalog.Get(engineSetting), tools) + if err != nil { + return nil, err + } if err := c.validateEngineToolRequirements(result.Frontmatter, agenticEngine, tools); err != nil { return nil, err } @@ -220,6 +229,45 @@ func (c *Compiler) resolveToolsConfiguration( }, nil } +// enforceMCPProxyTools exposes MCP-backed tools through CLI proxies for engines +// that do not have an MCP client. +func enforceMCPProxyTools(engine *EngineDefinition, tools map[string]any) (map[string]any, error) { + if engine == nil || engine.MCP == nil || *engine.MCP { + return tools, nil + } + + if githubValue, exists := tools["github"]; exists { + switch github := githubValue.(type) { + case bool: + if !github { + return nil, fmt.Errorf("engine '%s' does not support MCP; tools.github cannot be disabled because gh-proxy is required", engine.ID) + } + case map[string]any: + if modeValue, hasMode := github["mode"]; hasMode { + mode, ok := modeValue.(string) + if !ok || (mode != string(GitHubMCPModeGHProxy) && mode != string(GitHubMCPModeCLI)) { + return nil, fmt.Errorf("engine '%s' does not support MCP; tools.github.mode must be gh-proxy", engine.ID) + } + } + github["mode"] = string(GitHubMCPModeGHProxy) + } + } + + if _, exists := tools["github"]; !exists { + tools["github"] = map[string]any{"mode": string(GitHubMCPModeGHProxy)} + } else if enabled, ok := tools["github"].(bool); ok && enabled { + tools["github"] = map[string]any{"mode": string(GitHubMCPModeGHProxy)} + } + + if cliProxy, exists := tools["cli-proxy"]; exists { + if enabled, ok := cliProxy.(bool); ok && !enabled { + return nil, fmt.Errorf("engine '%s' does not support MCP; tools.cli-proxy cannot be disabled", engine.ID) + } + } + tools["cli-proxy"] = true + return tools, nil +} + func nonEmptyStrings(values ...string) []string { out := make([]string, 0, len(values)) for _, value := range values { diff --git a/pkg/workflow/compiler_orchestrator_tools_test.go b/pkg/workflow/compiler_orchestrator_tools_test.go index af0d4156218..9abfbb66c06 100644 --- a/pkg/workflow/compiler_orchestrator_tools_test.go +++ b/pkg/workflow/compiler_orchestrator_tools_test.go @@ -884,3 +884,51 @@ func TestWarnDeprecatedFrontmatterFields_SafeOutputsDeprecatedAliases(t *testing assert.Contains(t, stderr, "required-title-prefix", "warning should mention required-title-prefix replacement") assert.Equal(t, 1, compiler.warningCount, "one warning for the deprecated alias") } + +func TestEnforceMCPProxyTools(t *testing.T) { + mcpUnsupported := false + engine := &EngineDefinition{ID: "aider", MCP: &mcpUnsupported} + + t.Run("enables required proxies", func(t *testing.T) { + tools, err := enforceMCPProxyTools(engine, map[string]any{}) + require.NoError(t, err) + assert.Equal(t, true, tools["cli-proxy"]) + assert.Equal(t, map[string]any{"mode": "gh-proxy"}, tools["github"]) + }) + + t.Run("preserves github configuration", func(t *testing.T) { + tools, err := enforceMCPProxyTools(engine, map[string]any{ + "github": map[string]any{"toolsets": []any{"repos"}}, + }) + require.NoError(t, err) + assert.Equal(t, map[string]any{ + "mode": "gh-proxy", + "toolsets": []any{"repos"}, + }, tools["github"]) + assert.Equal(t, true, tools["cli-proxy"]) + }) + + t.Run("rejects disabled github proxy", func(t *testing.T) { + _, err := enforceMCPProxyTools(engine, map[string]any{"github": false}) + require.ErrorContains(t, err, "tools.github cannot be disabled") + }) + + t.Run("rejects non proxy github mode", func(t *testing.T) { + _, err := enforceMCPProxyTools(engine, map[string]any{ + "github": map[string]any{"mode": "remote"}, + }) + require.ErrorContains(t, err, "tools.github.mode must be gh-proxy") + }) + + t.Run("rejects disabled cli proxy", func(t *testing.T) { + _, err := enforceMCPProxyTools(engine, map[string]any{"cli-proxy": false}) + require.ErrorContains(t, err, "tools.cli-proxy cannot be disabled") + }) + + t.Run("leaves MCP engines unchanged", func(t *testing.T) { + tools := map[string]any{"github": false, "cli-proxy": false} + actual, err := enforceMCPProxyTools(&EngineDefinition{ID: "copilot"}, tools) + require.NoError(t, err) + assert.Equal(t, tools, actual) + }) +} diff --git a/pkg/workflow/engine_definition.go b/pkg/workflow/engine_definition.go index 9887bfdc5d3..596c984c6cc 100644 --- a/pkg/workflow/engine_definition.go +++ b/pkg/workflow/engine_definition.go @@ -274,10 +274,12 @@ func (a *AuthDefinition) RequiredSecretNames() []string { // It is separate from the runtime adapter (CodingAgentEngine) to allow the catalog // layer to carry identity and provider information without coupling to implementation. type EngineDefinition struct { - ID string `yaml:"id"` - DisplayName string `yaml:"display-name,omitempty"` - Description string `yaml:"description,omitempty"` - Experimental bool `yaml:"experimental,omitempty"` + ID string `yaml:"id"` + DisplayName string `yaml:"display-name,omitempty"` + Description string `yaml:"description,omitempty"` + Experimental bool `yaml:"experimental,omitempty"` + // MCP indicates whether the engine supports MCP. Nil defaults to supported. + MCP *bool `yaml:"mcp,omitempty"` GHSkillAgentName string `yaml:"gh-skill-agent-name,omitempty"` // RuntimeID maps to the CodingAgentEngine registered in EngineRegistry. // Defaults to ID when omitted. From 066a1ef5f3ffb1ef3e23925f07c7c7bcfda6e2bd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:17:49 +0000 Subject: [PATCH 2/6] fix: enforce MCP proxies for Pi Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/compiler_orchestrator_tools.go | 2 ++ pkg/workflow/compiler_orchestrator_tools_test.go | 16 +++++++++++++++- pkg/workflow/data/engines/pi.md | 1 + pkg/workflow/engine_definition_test.go | 12 +++++++----- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/pkg/workflow/compiler_orchestrator_tools.go b/pkg/workflow/compiler_orchestrator_tools.go index ead95b560f3..f8f88f3311b 100644 --- a/pkg/workflow/compiler_orchestrator_tools.go +++ b/pkg/workflow/compiler_orchestrator_tools.go @@ -250,6 +250,8 @@ func enforceMCPProxyTools(engine *EngineDefinition, tools map[string]any) (map[s } } github["mode"] = string(GitHubMCPModeGHProxy) + case nil, string: + tools["github"] = map[string]any{"mode": string(GitHubMCPModeGHProxy)} } } diff --git a/pkg/workflow/compiler_orchestrator_tools_test.go b/pkg/workflow/compiler_orchestrator_tools_test.go index 9abfbb66c06..18044218bd5 100644 --- a/pkg/workflow/compiler_orchestrator_tools_test.go +++ b/pkg/workflow/compiler_orchestrator_tools_test.go @@ -887,7 +887,7 @@ func TestWarnDeprecatedFrontmatterFields_SafeOutputsDeprecatedAliases(t *testing func TestEnforceMCPProxyTools(t *testing.T) { mcpUnsupported := false - engine := &EngineDefinition{ID: "aider", MCP: &mcpUnsupported} + engine := &EngineDefinition{ID: "custom-engine", MCP: &mcpUnsupported} t.Run("enables required proxies", func(t *testing.T) { tools, err := enforceMCPProxyTools(engine, map[string]any{}) @@ -908,6 +908,20 @@ func TestEnforceMCPProxyTools(t *testing.T) { assert.Equal(t, true, tools["cli-proxy"]) }) + t.Run("normalizes default-enabled github forms", func(t *testing.T) { + for name, github := range map[string]any{ + "nil": nil, + "string": "enabled", + } { + t.Run(name, func(t *testing.T) { + tools, err := enforceMCPProxyTools(engine, map[string]any{"github": github}) + require.NoError(t, err) + assert.Equal(t, map[string]any{"mode": "gh-proxy"}, tools["github"]) + assert.Equal(t, true, tools["cli-proxy"]) + }) + } + }) + t.Run("rejects disabled github proxy", func(t *testing.T) { _, err := enforceMCPProxyTools(engine, map[string]any{"github": false}) require.ErrorContains(t, err, "tools.github cannot be disabled") diff --git a/pkg/workflow/data/engines/pi.md b/pkg/workflow/data/engines/pi.md index 37459e088ec..2981a1b6a0a 100644 --- a/pkg/workflow/data/engines/pi.md +++ b/pkg/workflow/data/engines/pi.md @@ -4,6 +4,7 @@ engine: display-name: Pi description: Pi AI coding agent (experimental) runtime-id: pi + mcp: false provider: name: github --- diff --git a/pkg/workflow/engine_definition_test.go b/pkg/workflow/engine_definition_test.go index 6474cf77690..421788a5937 100644 --- a/pkg/workflow/engine_definition_test.go +++ b/pkg/workflow/engine_definition_test.go @@ -20,12 +20,13 @@ func TestNewEngineCatalog_BuiltIns(t *testing.T) { engineID string displayName string provider string + mcp *bool }{ - {"claude", "Claude Code", "anthropic"}, - {"codex", "Codex", "openai"}, - {"copilot", "GitHub Copilot CLI", "github"}, - {"gemini", "Google Gemini CLI", "google"}, - {"pi", "Pi", "github"}, + {"claude", "Claude Code", "anthropic", nil}, + {"codex", "Codex", "openai", nil}, + {"copilot", "GitHub Copilot CLI", "github", nil}, + {"gemini", "Google Gemini CLI", "google", nil}, + {"pi", "Pi", "github", boolPtr(false)}, } for _, tt := range tests { @@ -38,6 +39,7 @@ func TestNewEngineCatalog_BuiltIns(t *testing.T) { assert.Equal(t, tt.displayName, resolved.Definition.DisplayName, "Definition.DisplayName should match") assert.Equal(t, tt.provider, resolved.Definition.Provider.Name, "Definition.Provider.Name should match") assert.Equal(t, tt.engineID, resolved.Runtime.GetID(), "Runtime.GetID() should match engine ID") + assert.Equal(t, tt.mcp, resolved.Definition.MCP, "Definition.MCP should match") }) } } From af1a536fe64b81d7e74950ab96885639d4513273 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:24:45 +0000 Subject: [PATCH 3/6] chore: plan Pi MCP capability update Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/skills/agentic-workflows/SKILL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index 141445630d5..f11eaadd2e7 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -42,6 +42,7 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/llms.md` - `.github/aw/loop.md` - `.github/aw/lsp.md` +- `.github/aw/maintainer.md` - `.github/aw/mcp-clis.md` - `.github/aw/memory-stateful-patterns.md` - `.github/aw/memory.md` From 34723316c20e7e8f4e32b321e93107ec8f4c230a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:32:08 +0000 Subject: [PATCH 4/6] fix: expose engine MCP capability Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/skills/agentic-workflows/SKILL.md | 1 - pkg/workflow/agentic_engine.go | 10 ++++++++++ pkg/workflow/antigravity_engine.go | 1 + pkg/workflow/behavior_defined_engine.go | 8 +++++++- .../behavior_defined_engine_harness_test.go | 16 ++++++++++++++++ pkg/workflow/claude_engine.go | 1 + pkg/workflow/codex_engine.go | 1 + pkg/workflow/compiler_orchestrator_tools.go | 14 +++++++------- pkg/workflow/compiler_orchestrator_tools_test.go | 11 ++++++++--- pkg/workflow/copilot_engine.go | 1 + pkg/workflow/engine_definition.go | 10 +++++++++- pkg/workflow/gemini_engine.go | 1 + pkg/workflow/pi_engine.go | 1 + pkg/workflow/pi_engine_test.go | 1 + 14 files changed, 64 insertions(+), 13 deletions(-) diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index f11eaadd2e7..141445630d5 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -42,7 +42,6 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/llms.md` - `.github/aw/loop.md` - `.github/aw/lsp.md` -- `.github/aw/maintainer.md` - `.github/aw/mcp-clis.md` - `.github/aw/memory-stateful-patterns.md` - `.github/aw/memory.md` diff --git a/pkg/workflow/agentic_engine.go b/pkg/workflow/agentic_engine.go index 3d5a00ef082..538eaffee40 100644 --- a/pkg/workflow/agentic_engine.go +++ b/pkg/workflow/agentic_engine.go @@ -114,6 +114,9 @@ type EngineCapabilities struct { // ToolsAllowlist reports whether the engine supports MCP tool allow-listing. ToolsAllowlist bool + // MCP reports whether the engine supports MCP servers directly. + MCP bool + // MaxTurns reports whether the engine supports the max-turns feature. MaxTurns bool @@ -150,6 +153,13 @@ type CapabilityProvider interface { GetCapabilities() EngineCapabilities } +// MCPProxyEngine provides the identity and MCP capability information needed to +// configure CLI proxy tools. +type MCPProxyEngine interface { + Engine + CapabilityProvider +} + // WorkflowExecutor handles workflow compilation and execution // All engines must implement this to generate GitHub Actions steps type WorkflowExecutor interface { diff --git a/pkg/workflow/antigravity_engine.go b/pkg/workflow/antigravity_engine.go index 7538eb9de7e..db12eecd910 100644 --- a/pkg/workflow/antigravity_engine.go +++ b/pkg/workflow/antigravity_engine.go @@ -28,6 +28,7 @@ func NewAntigravityEngine() *AntigravityEngine { ghSkillAgentName: "antigravity", capabilities: EngineCapabilities{ ToolsAllowlist: true, + MCP: true, MaxTurns: true, MaxContinuations: false, // Antigravity CLI does not support --max-autopilot-continues-style continuation mode WebSearch: false, diff --git a/pkg/workflow/behavior_defined_engine.go b/pkg/workflow/behavior_defined_engine.go index 9ad098674d7..2c51ae61680 100644 --- a/pkg/workflow/behavior_defined_engine.go +++ b/pkg/workflow/behavior_defined_engine.go @@ -39,6 +39,12 @@ func NewBehaviorDefinedEngine(def *EngineDefinition) (*BehaviorDefinedEngine, er if def.Behaviors == nil { return nil, fmt.Errorf("engine definition %q is missing behaviors", def.ID) } + capabilities := def.Behaviors.Capabilities.ToRuntimeCapabilities() + capabilities.MCP = true + if def.MCP != nil { + capabilities.MCP = *def.MCP + } + engine := &BehaviorDefinedEngine{ UniversalLLMConsumerEngine: UniversalLLMConsumerEngine{ BaseEngine: BaseEngine{ @@ -47,7 +53,7 @@ func NewBehaviorDefinedEngine(def *EngineDefinition) (*BehaviorDefinedEngine, er description: def.Description, experimental: def.Experimental, ghSkillAgentName: def.GHSkillAgentName, - capabilities: def.Behaviors.Capabilities.ToRuntimeCapabilities(), + capabilities: capabilities, }, }, definition: def, diff --git a/pkg/workflow/behavior_defined_engine_harness_test.go b/pkg/workflow/behavior_defined_engine_harness_test.go index 25e97680383..17394473952 100644 --- a/pkg/workflow/behavior_defined_engine_harness_test.go +++ b/pkg/workflow/behavior_defined_engine_harness_test.go @@ -131,6 +131,22 @@ func TestBehaviorDefinedEngineHarnessScript(t *testing.T) { }) } +func TestBehaviorDefinedEngineMCPCapability(t *testing.T) { + t.Run("defaults to supported", func(t *testing.T) { + engine, err := NewBehaviorDefinedEngine(newHarnessEngineDefinition()) + require.NoError(t, err) + assert.True(t, engine.GetCapabilities().MCP) + }) + + t.Run("uses engine definition", func(t *testing.T) { + def := newHarnessEngineDefinition() + def.MCP = boolPtr(false) + engine, err := NewBehaviorDefinedEngine(def) + require.NoError(t, err) + assert.False(t, engine.GetCapabilities().MCP) + }) +} + // TestBehaviorDefinedEngineNoHarnessScript verifies that engines without harness-script // continue to use the direct command execution path (inline prompt substitution). func TestBehaviorDefinedEngineNoHarnessScript(t *testing.T) { diff --git a/pkg/workflow/claude_engine.go b/pkg/workflow/claude_engine.go index 8c2f58d0515..99a2374ec96 100644 --- a/pkg/workflow/claude_engine.go +++ b/pkg/workflow/claude_engine.go @@ -31,6 +31,7 @@ func NewClaudeEngine() *ClaudeEngine { ghSkillAgentName: "claude-code", capabilities: EngineCapabilities{ ToolsAllowlist: true, + MCP: true, MaxTurns: true, // Claude supports max-turns feature MaxContinuations: false, // Claude Code does not support --max-autopilot-continues-style continuation WebSearch: true, // Claude has built-in WebSearch support diff --git a/pkg/workflow/codex_engine.go b/pkg/workflow/codex_engine.go index 780d82d8677..79ba75182d3 100644 --- a/pkg/workflow/codex_engine.go +++ b/pkg/workflow/codex_engine.go @@ -59,6 +59,7 @@ func NewCodexEngine() *CodexEngine { ghSkillAgentName: "codex", capabilities: EngineCapabilities{ ToolsAllowlist: true, + MCP: true, MaxTurns: true, // AWF max-turns is supported for Codex runs MaxContinuations: false, // Codex does not support --max-autopilot-continues-style continuation mode WebSearch: true, // Codex has built-in web-search support diff --git a/pkg/workflow/compiler_orchestrator_tools.go b/pkg/workflow/compiler_orchestrator_tools.go index f8f88f3311b..47c4ed168f7 100644 --- a/pkg/workflow/compiler_orchestrator_tools.go +++ b/pkg/workflow/compiler_orchestrator_tools.go @@ -207,12 +207,12 @@ func (c *Compiler) resolveToolsConfiguration( orchestratorToolsLog.Printf("MCP configuration validation failed: %v", err) return nil, err } - tools, err = enforceMCPProxyTools(c.engineCatalog.Get(engineSetting), tools) + tools, err = enforceMCPProxyTools(agenticEngine, tools) if err != nil { return nil, err } tools = c.adjustToolsForEngineCapabilities(result.Frontmatter, agenticEngine, tools) - tools, err = enforceMCPProxyTools(c.engineCatalog.Get(engineSetting), tools) + tools, err = enforceMCPProxyTools(agenticEngine, tools) if err != nil { return nil, err } @@ -231,8 +231,8 @@ func (c *Compiler) resolveToolsConfiguration( // enforceMCPProxyTools exposes MCP-backed tools through CLI proxies for engines // that do not have an MCP client. -func enforceMCPProxyTools(engine *EngineDefinition, tools map[string]any) (map[string]any, error) { - if engine == nil || engine.MCP == nil || *engine.MCP { +func enforceMCPProxyTools(engine MCPProxyEngine, tools map[string]any) (map[string]any, error) { + if engine == nil || engine.GetCapabilities().MCP { return tools, nil } @@ -240,13 +240,13 @@ func enforceMCPProxyTools(engine *EngineDefinition, tools map[string]any) (map[s switch github := githubValue.(type) { case bool: if !github { - return nil, fmt.Errorf("engine '%s' does not support MCP; tools.github cannot be disabled because gh-proxy is required", engine.ID) + return nil, fmt.Errorf("engine '%s' does not support MCP; tools.github cannot be disabled because gh-proxy is required", engine.GetID()) } case map[string]any: if modeValue, hasMode := github["mode"]; hasMode { mode, ok := modeValue.(string) if !ok || (mode != string(GitHubMCPModeGHProxy) && mode != string(GitHubMCPModeCLI)) { - return nil, fmt.Errorf("engine '%s' does not support MCP; tools.github.mode must be gh-proxy", engine.ID) + return nil, fmt.Errorf("engine '%s' does not support MCP; tools.github.mode must be gh-proxy", engine.GetID()) } } github["mode"] = string(GitHubMCPModeGHProxy) @@ -263,7 +263,7 @@ func enforceMCPProxyTools(engine *EngineDefinition, tools map[string]any) (map[s if cliProxy, exists := tools["cli-proxy"]; exists { if enabled, ok := cliProxy.(bool); ok && !enabled { - return nil, fmt.Errorf("engine '%s' does not support MCP; tools.cli-proxy cannot be disabled", engine.ID) + return nil, fmt.Errorf("engine '%s' does not support MCP; tools.cli-proxy cannot be disabled", engine.GetID()) } } tools["cli-proxy"] = true diff --git a/pkg/workflow/compiler_orchestrator_tools_test.go b/pkg/workflow/compiler_orchestrator_tools_test.go index 18044218bd5..e71552f03d5 100644 --- a/pkg/workflow/compiler_orchestrator_tools_test.go +++ b/pkg/workflow/compiler_orchestrator_tools_test.go @@ -886,8 +886,10 @@ func TestWarnDeprecatedFrontmatterFields_SafeOutputsDeprecatedAliases(t *testing } func TestEnforceMCPProxyTools(t *testing.T) { - mcpUnsupported := false - engine := &EngineDefinition{ID: "custom-engine", MCP: &mcpUnsupported} + engine := &BaseEngine{ + id: "custom-engine", + capabilities: EngineCapabilities{MCP: false}, + } t.Run("enables required proxies", func(t *testing.T) { tools, err := enforceMCPProxyTools(engine, map[string]any{}) @@ -941,7 +943,10 @@ func TestEnforceMCPProxyTools(t *testing.T) { t.Run("leaves MCP engines unchanged", func(t *testing.T) { tools := map[string]any{"github": false, "cli-proxy": false} - actual, err := enforceMCPProxyTools(&EngineDefinition{ID: "copilot"}, tools) + actual, err := enforceMCPProxyTools(&BaseEngine{ + id: "mcp-engine", + capabilities: EngineCapabilities{MCP: true}, + }, tools) require.NoError(t, err) assert.Equal(t, tools, actual) }) diff --git a/pkg/workflow/copilot_engine.go b/pkg/workflow/copilot_engine.go index 149de64d4c6..208e6e72cd2 100644 --- a/pkg/workflow/copilot_engine.go +++ b/pkg/workflow/copilot_engine.go @@ -43,6 +43,7 @@ func NewCopilotEngine() *CopilotEngine { ghSkillAgentName: "github-copilot", capabilities: EngineCapabilities{ ToolsAllowlist: true, + MCP: true, MaxTurns: true, // AWF max-turns is supported for Copilot runs MaxContinuations: true, // Copilot CLI supports --autopilot with --max-autopilot-continues WebSearch: false, // Copilot CLI does not have built-in web-search support diff --git a/pkg/workflow/engine_definition.go b/pkg/workflow/engine_definition.go index 596c984c6cc..2641bf1de57 100644 --- a/pkg/workflow/engine_definition.go +++ b/pkg/workflow/engine_definition.go @@ -136,7 +136,15 @@ type EngineCapabilitiesDefinition struct { // ToRuntimeCapabilities converts the declarative capabilities definition into the // runtime EngineCapabilities struct used by CodingAgentEngine implementations. func (d EngineCapabilitiesDefinition) ToRuntimeCapabilities() EngineCapabilities { - return EngineCapabilities(d) + return EngineCapabilities{ + ToolsAllowlist: d.ToolsAllowlist, + MaxTurns: d.MaxTurns, + WebSearch: d.WebSearch, + MaxContinuations: d.MaxContinuations, + NativeAgentFile: d.NativeAgentFile, + BareMode: d.BareMode, + BashCommandAllowlist: d.BashCommandAllowlist, + } } // EngineManifestDefinition describes engine-specific files and folders that alter diff --git a/pkg/workflow/gemini_engine.go b/pkg/workflow/gemini_engine.go index 1bb7cdaab3a..ee50fb3e7dc 100644 --- a/pkg/workflow/gemini_engine.go +++ b/pkg/workflow/gemini_engine.go @@ -28,6 +28,7 @@ func NewGeminiEngine() *GeminiEngine { ghSkillAgentName: "gemini-cli", capabilities: EngineCapabilities{ ToolsAllowlist: true, + MCP: true, MaxTurns: true, MaxContinuations: false, // Gemini CLI does not support --max-autopilot-continues-style continuation mode WebSearch: false, diff --git a/pkg/workflow/pi_engine.go b/pkg/workflow/pi_engine.go index c4a0f433dda..7df5f5a23bd 100644 --- a/pkg/workflow/pi_engine.go +++ b/pkg/workflow/pi_engine.go @@ -43,6 +43,7 @@ func NewPiEngine() *PiEngine { ghSkillAgentName: "pi", capabilities: EngineCapabilities{ ToolsAllowlist: true, + MCP: false, MaxTurns: true, MaxContinuations: false, WebSearch: false, diff --git a/pkg/workflow/pi_engine_test.go b/pkg/workflow/pi_engine_test.go index d6bbe7c7b6b..85bf417f97e 100644 --- a/pkg/workflow/pi_engine_test.go +++ b/pkg/workflow/pi_engine_test.go @@ -19,6 +19,7 @@ func TestNewPiEngine(t *testing.T) { assert.True(t, engine.IsExperimental(), "Pi engine should be experimental") capabilities := engine.GetCapabilities() assert.True(t, capabilities.ToolsAllowlist, "Pi should support tools allowlist (needed for gh-proxy/cli-proxy settings)") + assert.False(t, capabilities.MCP, "Pi should not support MCP directly") assert.True(t, capabilities.MaxTurns, "Pi should support max turns") } From fa4877e88022d1a8a643819b3146d5ee4e1fcb2d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:08:22 +0000 Subject: [PATCH 5/6] Plan review feedback fix Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- .github/skills/agentic-workflows/SKILL.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index e9f1125c621..f11eaadd2e7 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -98,6 +98,5 @@ After loading the matching workflow prompt or skill, follow it directly: - Choose workflow architecture and patterns: `.github/aw/patterns.md` - Optimize token usage and cost: `.github/aw/token-optimization.md` - Design long-running multi-agent research workflows: `.github/aw/multi-agent-research.md` -- Maintaining a repository, consuming backlog: `.githbub/aw/maintainer.md` When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill. From d2181ed600089238eb922bc5b4449997a607070d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Aug 2026 19:28:41 +0000 Subject: [PATCH 6/6] Sync agent workflow metadata after branch refresh Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- .github/skills/agentic-workflows/SKILL.md | 1 + pkg/cli/data/agentic_workflows_fallback_aw_files.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index f11eaadd2e7..22e2accc575 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -100,3 +100,4 @@ After loading the matching workflow prompt or skill, follow it directly: - Design long-running multi-agent research workflows: `.github/aw/multi-agent-research.md` When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill. + diff --git a/pkg/cli/data/agentic_workflows_fallback_aw_files.json b/pkg/cli/data/agentic_workflows_fallback_aw_files.json index 0b26d0d266b..b1f63d9fc3c 100644 --- a/pkg/cli/data/agentic_workflows_fallback_aw_files.json +++ b/pkg/cli/data/agentic_workflows_fallback_aw_files.json @@ -26,6 +26,7 @@ "llms.md", "loop.md", "lsp.md", + "maintainer.md", "mcp-clis.md", "memory-stateful-patterns.md", "memory.md",