Skip to content

feat: mount MCP servers as local CLIs after gateway starts#25928

Open
Copilot wants to merge 33 commits intomainfrom
copilot/reconstruct-feature-24503
Open

feat: mount MCP servers as local CLIs after gateway starts#25928
Copilot wants to merge 33 commits intomainfrom
copilot/reconstruct-feature-24503

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 12, 2026

Reconstructs the feature from #24503. Adds opt-in mounting of MCP servers as standalone CLI tools on PATH via tools.mount-as-clis: true (default false). When enabled, user-facing MCP servers are exposed as shell commands and excluded from the agent's final MCP config, forcing the agent to use CLI wrappers exclusively. The github MCP server is excluded from CLI mounting as it is handled differently and remains available as a normal MCP tool.

The safeoutputs and mcpscripts servers are always CLI-mounted when enabled — regardless of the mount-as-clis setting — and remain available as MCP tools too (dual access). The injected prompt instructs the agent to prefer the CLI wrappers over the MCP tools for these servers.

How it works

The gateway starts containers for all configured servers (so they're reachable), then filtering happens in two stages:

  1. Gateway config: includes all servers — needed to populate ${RUNNER_TEMP}/gh-aw/mcp-cli/manifest.json
  2. Agent config: CLI-mounted servers excluded via GH_AW_MCP_CLI_SERVERS env var in each convert_gateway_config_*.cjs script — except safeoutputs and mcpscripts, which stay in the agent MCP config for dual access

After the gateway starts, mount_mcp_as_cli.cjs reads the manifest, queries each server's tools/list via the full MCP session protocol (initializenotifications/initializedtools/list), and generates locked-down CLI wrappers under ${RUNNER_TEMP}/gh-aw/mcp-cli/bin/.

tools:
  playwright:
  mount-as-clis: true
# Agent uses these instead of MCP protocol:
playwright browser_navigate --url https://example.com
safeoutputs add_comment --body "Analysis complete"
mcpscripts mcpscripts-gh --args "pr list --repo owner/repo --limit 5"

Note: The github MCP server is not CLI-mounted — it is handled differently and remains available as a normal MCP tool even when mount-as-clis: true is set.

Changes

New files

  • pkg/workflow/mcp_cli_mount.gogetMCPCLIServerNames(), getMCPCLIExcludeFromAgentConfig(), generateMCPCLIMountStep(), buildMCPCLIPromptSection(), GetMCPCLIPathSetup()
  • actions/setup/js/mount_mcp_as_cli.cjs — manifest reader, MCP handshake, CLI wrapper generator; generates thin bash stubs that exec into the Node.js bridge
  • actions/setup/js/mcp_cli_bridge.cjs — Node.js CLI-to-MCP bridge handling full MCP session protocol (initializenotifications/initializedtools/call), argument parsing, --help display, response formatting, and JSONL audit logging; uses shim.cjs and core.* for consistent GitHub Actions logging
  • actions/setup/md/mcp_cli_tools_prompt.md<mcp-clis> prompt section template
  • actions/setup/js/convert_gateway_config_copilot.cjs — JavaScript gateway config converter for Copilot (filters CLI servers, adds tools:["*"], rewrites URLs)
  • actions/setup/js/convert_gateway_config_claude.cjs — JavaScript gateway config converter for Claude (filters CLI servers, sets type:"http", rewrites URLs)
  • actions/setup/js/convert_gateway_config_codex.cjs — JavaScript gateway config converter for Codex (filters CLI servers, resolves host.docker.internal to 172.30.0.1, generates TOML)
  • actions/setup/js/convert_gateway_config_gemini.cjs — JavaScript gateway config converter for Gemini (filters CLI servers, removes type field for transport auto-detection, rewrites URLs, adds context.includeDirectories)
  • actions/setup/js/start_mcp_gateway.cjs — JavaScript gateway startup script (reads MCP config from stdin, launches Docker container, health check polling, engine-specific converter dispatch, CLI manifest creation, GitHub Actions outputs)

CLI wrapper architecture (bash → Node.js bridge)

  • Generated bash CLI wrappers are thin stubs that exec node mcp_cli_bridge.cjs with server config passed as arguments — no jq/curl/awk dependencies
  • mcp_cli_bridge.cjs handles all MCP protocol logic in Node.js:
    • Full MCP session lifecycle: initializenotifications/initializedtools/call with proper session ID tracking
    • Argument parsing: --key value and --key=value styles, with --json flag for raw JSON output
    • --help / -h support: displays available tools with parameter schemas
    • Response formatting: extracts text content, handles errors with structured output
    • Uses shim.cjs and core.* for all logging (consistent GitHub Actions annotation output)
    • JSONL audit logging: appends structured entries to /tmp/gh-aw/mcp-cli-audit/<server>.jsonl with timestamps, duration, request/response details, and error tracking — audit directory/file failures logged as warnings without blocking tool execution

Go pipeline integration

  • ToolsConfig.MountAsCLIs field + parser + schema + validation
  • compiler_yaml_main_job.go calls generateMCPCLIMountStep() after gateway setup
  • mcp_setup_generator.go exports GH_AW_MCP_CLI_SERVERS JSON array to $GITHUB_ENV using getMCPCLIExcludeFromAgentConfig() (excludes safeoutputs/mcpscripts so they remain as MCP tools)
  • unified_prompt_step.go injects CLI tools prompt section (8a, after safe outputs)
  • mcp_rendering.go documents why CLI servers stay in gateway config
  • mcp_renderer.go invokes node start_mcp_gateway.cjs (converted from bash start_mcp_gateway.sh)
  • getMCPCLIServerNames() always includes safeoutputs and mcpscripts when they are enabled (HasSafeOutputsEnabled/IsMCPScriptsEnabled), regardless of mount-as-clis setting
  • getMCPCLIExcludeFromAgentConfig() returns only servers that should be removed from agent MCP config (does not include safeoutputs/mcpscripts — they get dual access)

MCP CLI bin directory on PATH inside AWF container

  • GetMCPCLIPathSetup() in mcp_cli_mount.go returns the export PATH= snippet that prepends ${RUNNER_TEMP}/gh-aw/mcp-cli/bin to $PATH
  • All four engine files (copilot_engine_execution.go, claude_engine.go, codex_engine.go, gemini_engine.go) inject this PATH setup into the AWF container's environment so CLI wrappers are discoverable without manual export by the agent

Dual access for safeoutputs and mcpscripts

  • safeoutputs and mcpscripts are always CLI-mounted when enabled, even without mount-as-clis: true
  • They remain in the agent's MCP config (not filtered by converter scripts) — dual access via both CLI and MCP
  • The alwaysCLIMountedServers map in Go controls which servers get this treatment
  • The prompt template instructs the agent to prefer CLI wrappers over MCP tools for these servers

Gateway scripts (bash → JavaScript)

  • start_mcp_gateway.cjs — full JavaScript port of the gateway startup script using child_process.spawn for Docker container management, Node.js http module for health checks, and child_process.execSync for converter/checker dispatch. Maintains all security controls (umask, symlink attack prevention, 0o600 file permissions)
  • convert_gateway_config_{copilot,claude,codex,gemini}.cjs — all four engine converters are JavaScript for CLI server filtering, URL rewriting, and engine-specific config generation
  • validate_prompt_placeholders.sh — strips backtick code spans before checking for unreplaced __GH_AW_*__ placeholders

Config storage hardening (/tmpRUNNER_TEMP)

  • MCP config (mcp-config/) and CLI manifest (mcp-cli/) moved from /tmp/gh-aw/ to ${RUNNER_TEMP}/gh-aw/ to prevent tampering — /tmp is world-writable, RUNNER_TEMP is per-runner and not world-accessible
  • Updated across all JavaScript scripts (start_mcp_gateway.cjs, converter scripts, mount_mcp_as_cli.cjs, redact_secrets.cjs) and Go engine code (claude_engine.go, codex_engine.go, codex_mcp.go, claude_mcp.go, gemini_mcp.go, mcp_setup_generator.go, threat_detection.go, step_order_validation.go)
  • MCP logs remain under /tmp/gh-aw/mcp-logs/ since the Docker gateway container writes there via -v /tmp:/tmp:rw

Security hardening (shell injection, input validation)

  • shellEscapeDoubleQuoted() in mount_mcp_as_cli.cjs — escapes $ `` \ " ! and strips \r\n for all values embedded in generated CLI wrapper bash scripts (server name, URL, tools file path, API key), preventing shell injection and line injection attacks
  • isValidServerName() in mount_mcp_as_cli.cjs — validates server names against [a-zA-Z0-9_-] with 64-char max length, preventing path traversal and shell metacharacter injection via malicious server names; servers failing validation are skipped with a warning
  • URL validation — manifest server entries validated with new URL() before processing
  • Port validationgatewayPort verified to be strictly numeric before interpolation into execSync shell commands in start_mcp_gateway.cjs
  • API key passingcheck_mcp_servers.sh call uses $MCP_GATEWAY_API_KEY env var reference instead of direct JS string interpolation to avoid shell metacharacter risks
  • Server name validation in manifeststart_mcp_gateway.cjs filters invalid server names when generating the CLI manifest

Observability improvements

  • All new JavaScript scripts use core.* logging via shim.cjs (core.info, core.error, core.warning) instead of console.*, ensuring consistent GitHub Actions annotation output
  • All 4 converter scripts log CLI-mounted server filter list and include/filter counts
  • start_mcp_gateway.cjs logs startup banner (engine, port, domain, runner temp), server names in CLI manifest; top-level error handler preserves stack traces via core.error(err.stack) before core.setFailed()
  • mount_mcp_as_cli.cjs logs manifest server count after internal filtering, skipped servers with validation error reasons
  • mcp_cli_bridge.cjs logs every tool invocation with timing, arguments, and response status; appends JSONL audit entries to /tmp/gh-aw/mcp-cli-audit/<server>.jsonl for post-run analysis

Server exclusions

  • The github MCP server is excluded from CLI mounting in both Go (internalMCPServerNames) and JavaScript (INTERNAL_SERVERS) — it is handled differently and remains a normal MCP tool
  • safeoutputs and mcpscripts are always CLI-mounted when enabled (dual access with MCP), with usage examples and preference guidance in the prompt template

Smoke test

  • smoke-copilot.md enables mount-as-clis: true and updates test instructions to use CLI syntax for playwright/serena/safeoutputs/mcpscripts while keeping github as a normal MCP tool


✨ PR Review Safe Output Test - Run 24424530300

💥 [THE END] — Illustrated by Smoke Claude · ● 210.7K ·



✨ PR Review Safe Output Test - Run 24427887182

💥 [THE END] — Illustrated by Smoke Claude · ● 236.9K ·

Copilot AI and others added 2 commits April 12, 2026 18:06
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f6e50b8d-7b6d-4cef-a64b-c7b0f9f8878d

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Adds automatic mounting of MCP servers as local CLI tools in agentic
workflows. This behavior is opt-in via a new `tools.mount-as-clis: true`
flag (default `false`). When enabled, all user-facing MCP servers are
exposed as standalone shell commands and excluded from the agent's final
MCP config so the agent uses the CLI wrappers exclusively.

Reconstructs the feature from PR #24503.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f6e50b8d-7b6d-4cef-a64b-c7b0f9f8878d

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot ignore the github MCP server, it is handled differently.

The github MCP server is handled differently and should not be
mounted as a CLI tool. Added it to the exclusion lists in both
Go and JavaScript code, updated prompt template examples, and
restored smoke test instructions to use github as a normal MCP tool.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/35a490ef-753b-4f4e-8ab3-0d10a2d44b21

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 12, 2026

@copilot ignore the github MCP server, it is handled differently.

Excluded the github MCP server from CLI mounting in commit 4951367. Added it to the exclusion lists in both Go (internalMCPServerNames) and JavaScript (INTERNAL_SERVERS), updated the prompt template to remove github examples, and restored the smoke test to use github as a normal MCP tool.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw -pack /home/REDACTED/work/gh-aw/gh-aw/cmd/gh-aw/main.go (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw muPkofL/NgJlZta4-C (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha .js&#39; --ignore-path .prettierigno-errorsas (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha .js&#39; --ignore-path .prettierigno-errorsas erena-mcp-server:latest x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha k/gh-aw/gh-aw config 1/x64/bin/node remote.origin.urgit (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha .js&#39; --ignore-path .prettierigno-errorsas (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha .js&#39; --ignore-path .prettierigno-errorsas show x_amd64/vet (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha to pkg/workflow/data/action_pins.json...&#34; (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha ithub/workflows commit.gpgsign /home/REDACTED/.local/bin/bash (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha (http block)
  • https://api.github.com/repos/docker/build-push-action/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v7 --jq .object.sha (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/-
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/- --jq .object.sha (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from pelikhan April 12, 2026 18:58
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot enable flag for smoke-copilot

@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot always enabled for safeoutputs, mcpscripts. Update the built prompt generator to reflect this change too.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 12, 2026

@copilot enable flag for smoke-copilot

The mount-as-clis: true flag is already enabled in smoke-copilot.md (line 47 in the tools section) since commit afeaeed. The compiled lock file includes the "Mount MCP servers as CLIs" step, GH_AW_MCP_CLI_SERVERS env var, and CLI prompt section for agenticworkflows, playwright, and serena (with github excluded per the previous feedback).

Removed safeoutputs, mcp-scripts, and mcpscripts from the
internalMCPServerNames exclusion list in both Go and JavaScript.
Added explicit logic to always include safeoutputs and mcpscripts
in getMCPCLIServerNames() when they are enabled.
Updated the prompt template with safeoutputs/mcpscripts examples
and updated smoke-copilot test instructions accordingly.

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/20bf245a-f76f-48bb-9b17-8597b84ee941

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 12, 2026

@copilot always enabled for safeoutputs, mcpscripts. Update the built prompt generator to reflect this change too.

Done in fb83906. Removed safeoutputs and mcpscripts from the exclusion lists in both Go (internalMCPServerNames) and JavaScript (INTERNAL_SERVERS). Added explicit logic in getMCPCLIServerNames() to always include them when enabled. Updated the prompt template with safeoutputs/mcpscripts usage examples and the smoke-copilot test instructions to list them as CLI-mounted servers.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw **/*.cjs 64/bin/go git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq .object.sha -json GO111MODULE /usr/local/bin/bash GOINSECURE GOMOD -d bash --no�� --noprofile GOPROXY (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq .object.sha &#34; GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node /opt�� prettier --check 64/bin/go --ignore-path .prettierignore 64/bin/go go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha -test.timeout=10m0s -test.count=1 /usr/bin/git GOSUMDB GOWORK 64/bin/go git rev-�� --show-toplevel go /usr/bin/git MFpD/H8VUAZrsjt5git GO111MODULE 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq .object.sha --show-toplevel node /usr/bin/git run lint:cjs 64/bin/go git rev-�� --show-toplevel sh /usr/bin/git &#34;prettier&#34; --chegit node 64/bin/go git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/pkg/tool/linux_amd64/cgo GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/cgo (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha d -n 10 (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha d -n 10 --global rgo/bin/git http.https://gitgh (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha (http block)
  • https://api.github.com/repos/docker/build-push-action/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v7 --jq .object.sha --get-regexp --global t (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v7 --jq .object.sha ver\|cli_server _config_copilot.sh r: $owner, name: $name) { hasDiscussionsEnabled } } (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq .object.sha 476627/b001/workflow.test GO111MODULE 476627/b001/importcfg.link GOINSECURE GOMOD GOMODCACHE iTe2m1FqJ9AqD/E7yW-V-7DMzId52nbD6_/zJRkgRAW4PV_t4DqOxSf/EhrgUD1iTe2m1FqJ9AqD env ry=1 GO111MODULE che/go-build/14/14900198eb5740c9d1377a056c579ed3b8c3e7641e6841d95fa187196c139bf3-d GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq .object.sha --show-toplevel go /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� --show-toplevel npx /usr/bin/git --check **/*.cjs 64/bin/go git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq .object.sha 1089883/b423/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env hkp_/BdvgLBe8Jb1GOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE 1089883/b423/impGOPROXY (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/-
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/- --jq .object.sha (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq .object.sha 1089883/b428/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env BdUk/qiAXtumHukIGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE 1089883/b428/impGOPROXY (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 12, 2026

✅ All tools validated successfully! Agent Container Smoke Test confirms agent container is ready.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 12, 2026

⚠️ Smoke Gemini failed. Gemini encountered unexpected challenges...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 12, 2026

✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟

@github-actions
Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 12, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions github-actions bot removed the smoke label Apr 12, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

⚠️ Smoke Gemini failed. Gemini encountered unexpected challenges...

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown
Contributor

Smoke Test Results — Run §24424530245

Test Status
GitHub MCP
MCP Scripts GH CLI
Serena CLI ❌ HTTP 400
Playwright CLI ❌ HTTP 400
Web Fetch
File Writing + Bash
Discussion Interaction
Build gh-aw
Upload artifact
Discussion Creation
Workflow Dispatch
PR Review

Overall: ⚠️ PARTIAL PASS (2 MCP server infrastructure failures)
PR Author: @Copilot | Assignees: @pelikhan, @Copilot

📰 BREAKING: Report filed by Smoke Copilot · ● 898.5K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Smoke Test Review — PR #25928 adds opt-in MCP CLI mounting via mount-as-clis: true. The feature is well-structured with clear separation between gateway config and agent config. Left 2 minor inline suggestions on mcp_cli_mount.go. Overall the implementation looks solid with good security hardening (shell escaping, server name validation, URL validation).

📰 BREAKING: Report filed by Smoke Copilot · ● 898.5K

if data.ParsedTools != nil && data.ParsedTools.MountAsCLIs {
// Collect user-facing standard MCP tools from the raw Tools map
for toolName, toolValue := range data.Tools {
if toolValue == false {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Smoke Test Review — The toolValue == false check here works but is a bit surprising — false is a valid Go zero-value for bool, but toolValue is any. It might be clearer to use toolValue == nil || toolValue == false to also guard against nil entries, or to add a comment explaining that false means "tool disabled".

// (regardless of mount-as-clis setting), as they provide safe-output and script tools
// that the agent should invoke via CLI wrappers.
var internalMCPServerNames = map[string]bool{
"github": true, // GitHub MCP server is handled differently and should not be CLI-mounted
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Smoke Test Review — The internalMCPServerNames map correctly excludes the github server. The comment on line 29 nicely explains the rationale. One suggestion: consider adding an integration test that asserts github is never returned from getMCPCLIServerNames so this invariant is enforced by tests.

@github-actions
Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥 Automated smoke test review - all systems nominal! Run 24424530300 verified the Claude engine end-to-end. Core tests (GitHub MCP, Serena, Make build, Playwright, Tavily, file I/O) and PR review safe outputs all passing.

💥 [THE END] — Illustrated by Smoke Claude · ● 210.7K

// buildMCPCLIPromptSection returns a PromptSection describing the CLI tools available
// to the agent, or nil if there are no servers to mount.
// The prompt is loaded from actions/setup/md/mcp_cli_tools_prompt.md at runtime,
// with the __GH_AW_MCP_CLI_SERVERS_LIST__ placeholder substituted by the substitution step.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥 Smoke Test Review — The --help hint in the prompt section is a great UX improvement. Consider also adding a brief example invocation in the generated prompt so agents understand the CLI wrapper syntax at a glance (e.g., playwright browser_navigate --url (example.com/redacted)).

@@ -0,0 +1,5 @@
---
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smoke Test Review — Good changeset entry! Clear and concise summary of the feature. The note about github MCP server exclusion is helpful for reviewers understanding the scope of the change.

@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot review gateway logs, the cli calls are failing

https://github.com/github/gh-aw/actions/runs/24424530245/job/71355310322#step:45:1

Copilot AI and others added 2 commits April 14, 2026 22:48
…eature-24503

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Both mcp_cli_bridge.cjs and mount_mcp_as_cli.cjs were missing the
required Accept: application/json, text/event-stream header, causing
HTTP 400 errors from the MCP gateway with 'Accept must contain both
application/json and text/event-stream'.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 14, 2026

@copilot merge main, fix conflicts, recompile

Merged main (no conflicts) and recompiled all 191 lock files in a4e2ede.

@copilot review gateway logs, the cli calls are failing

https://github.com/github/gh-aw/actions/runs/24424530245/job/71355310322#step:45:1

Fixed in a4e2ede. Both mcp_cli_bridge.cjs and mount_mcp_as_cli.cjs were missing the required Accept: application/json, text/event-stream header for the Streamable HTTP MCP transport. The gateway returned HTTP 400 because the MCP spec mandates both content types in the Accept header. Added the header to the httpPostJSON function in both files.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw -pack /home/REDACTED/work/gh-aw/gh-aw/cmd/gh-aw/main.go (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw mUQDUZ6/c0s-iMgD-C (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq .object.sha -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq .object.sha -json GO111MODULE 64/pkg/tool/linux_amd64/asm GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/asm env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq .object.sha -json GO111MODULE ache/go/1.25.8/x64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha ath ../../../.pr**/*.json (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v7 --jq .object.sha h ../../../.pret--log-level=error (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha (http block)
  • https://api.github.com/repos/docker/build-push-action/git/ref/tags/v7
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v7 --jq .object.sha 3 --global x_amd64/compile http.https://git/usr/bin/gh (http block)
    • Triggering command: /usr/bin/gh gh api /repos/docker/build-push-action/git/ref/tags/v7 --jq .object.sha 3 --global $name) { hasDiscussionsEnabled } } http.https://git/usr/bin/gh (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/-
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/- --jq .object.sha data/action_pins.json...&#34; (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

✅ All tools validated successfully! Agent Container Smoke Test confirms agent container is ready.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

⚠️ Smoke Gemini failed. Gemini encountered unexpected challenges...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation...

@github-actions
Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link
Copy Markdown
Contributor

Agent Container Tool Check

Tool Status Version
bash 5.2.21
sh available
git 2.53.0
jq 1.7
yq v4.52.5
curl 8.5.0
gh 2.89.0
node v20.20.2
python3 3.12.3
go 1.24.13
java 10.0.201
dotnet 10.0.201

Result: 12/12 tools available ✅

Overall Status: PASS

🔧 Tool validation by Agent Container Smoke Test · ● 159.7K ·

@github-actions
Copy link
Copy Markdown
Contributor

Smoke Test Results — Run §24427887182

Core tests #1-12: ✅✅✅✅✅✅✅✅✅✅✅✅
PR review tests #13-19: ✅✅✅✅✅⚠️✅✅⚠️

Overall: PARTIAL (2 skipped: #16 thread resolve - no thread node ID accessible, #19 close PR - no safe test PR)

💥 [THE END] — Illustrated by Smoke Claude · ● 236.9K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥 Automated smoke test review - all systems nominal! This PR introduces MCP CLI mounting and RUNNER_TEMP fixes — both well-implemented. Tests #14-15 complete.

💥 [THE END] — Illustrated by Smoke Claude · ● 236.9K

"gh-aw": patch
---

Added opt-in MCP CLI mounting via `tools.mount-as-clis: true`, which exposes eligible MCP servers as local CLI wrappers on `PATH` and updates prompt/config wiring so agents use those wrappers. The `github` MCP server remains a normal MCP tool, while `safeoutputs` and `mcpscripts` are included in CLI mounting when enabled.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Good changeset description! The opt-in nature via tools.mount-as-clis: true is clearly documented. Consider also mentioning any performance impact of mounting MCP servers as CLIs vs. direct MCP tool calls.

run: |
set -eo pipefail
mkdir -p /tmp/gh-aw/mcp-config
mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Good fix — switching from hardcoded /tmp/gh-aw/mcp-config to \$\{RUNNER_TEMP}/gh-aw/mcp-config improves portability across different runner environments. This is consistent with GitHub Actions best practices for using RUNNER_TEMP.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Smoke Test Results — Run §24427887202

Test Status
GitHub MCP (merged PRs)
MCP Scripts GH CLI
Serena CLI (find_symbol EOF)
Playwright CLI
Web Fetch
File Writing
Bash Tool
Discussion Interaction
Build gh-aw
Upload Artifact
Discussion Creation
Workflow Dispatch
PR Review

Overall: ⚠️ PARTIAL PASS (12/13)

PR author: @Copilot · Assignees: @pelikhan, @Copilot

📰 BREAKING: Report filed by Smoke Copilot · ● 1.8M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Smoke Test Review (Run §24427887202)

This PR introduces a well-architected MCP CLI mounting system. The separation between internalMCPServerNames, alwaysCLIMountedServers, and user-opted servers is clean. Security hardening (shell injection prevention, server name validation) is thorough. The dual-access pattern for safeoutputs/mcpscripts is pragmatic. Build verified ✅

📰 BREAKING: Report filed by Smoke Copilot · ● 1.8M

---
"gh-aw": patch
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Smoke Test Review — Changeset entry clearly describes the feature. Consider mentioning the security hardening aspects (shell injection prevention, server name validation) in the changeset description as they're significant improvements worth surfacing in the changelog.

// Note: safeoutputs and mcpscripts are NOT excluded — they are always CLI-mounted
// (regardless of mount-as-clis setting), as they provide safe-output and script tools
// that the agent should invoke via CLI wrappers.
var internalMCPServerNames = map[string]bool{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Smoke Test Review — The internalMCPServerNames map elegantly centralizes exclusion logic. One suggestion: consider adding a doc comment explaining what makes a server "internal" vs eligible for CLI mounting, which would help future contributors understand the distinction between this map and alwaysCLIMountedServers.

@github-actions
Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot merge main, recompile, deep review

…eature-24503

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants