feat: mount MCP servers as local CLIs after gateway starts#24503
feat: mount MCP servers as local CLIs after gateway starts#24503
Conversation
- Add `start_mcp_gateway.sh`: save CLI manifest (server names + local URLs) to /tmp/gh-aw/mcp-cli/manifest.json before cleanup - Add `mount_mcp_as_cli.sh`: new shell script that reads the manifest, queries each server's tools/list via JSON-RPC, and generates a standalone CLI wrapper script in /tmp/gh-aw/mcp-cli/bin/ (chmod 555) - Add `mcp_cli_mount.go`: Go helpers getMCPCLIServerNames() and generateMCPCLIMountStep() + buildMCPCLIPromptSection() - Add "Mount MCP servers as CLIs" workflow step in compiler_yaml_main_job.go - Inject MCP CLI tools prompt section in unified_prompt_step.go - Update golden test fixtures Agent-Logs-Url: https://github.com/github/gh-aw/sessions/f83b0114-9c57-4701-ac7d-bfa80f07a971 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
| <safe-output-tools> | ||
| Tools: add_comment(max:10), create_issue(max:5), create_discussion(max:2), missing_tool, missing_data, noop | ||
| </safe-output-tools> | ||
| ## MCP Tools Available as CLI Commands |
actions/setup/sh/mount_mcp_as_cli.sh
Outdated
| @@ -0,0 +1,309 @@ | |||
| #!/usr/bin/env bash | |||
There was a problem hiding this comment.
- convert this a hell script to actions/github-script (and delete after conversion)
- add logging
There was a problem hiding this comment.
Done in f3d7205. Converted to actions/setup/js/mount_mcp_as_cli.cjs with core.info() logging throughout (and core.warning() for non-fatal errors). The shell script has been deleted. The workflow step now uses actions/github-script.
There was a problem hiding this comment.
Great work converting to github-script! The added core.info() logging makes it much easier to debug MCP mounting issues in the Actions log. 🎉
📰 BREAKING: Report filed by Smoke Copilot · ● 860.4K
that enables this behavior. Default is false.
|
…ml tags - Delete mount_mcp_as_cli.sh shell script - Add mount_mcp_as_cli.cjs using actions/github-script with core.info() logging - Update generateMCPCLIMountStep to use actions/github-script - Wrap MCP CLI prompt section in <mcp-clis> XML tags - Update golden fixtures and recompile lock files Agent-Logs-Url: https://github.com/github/gh-aw/sessions/1bf60ced-fb56-48d7-a2ce-b870a185cc27 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. 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:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot add a field tools.mount-as-clis: true/false that enables this behavior. Default is false. When false, do not emit custom prompt or mount any MCPs. |
|
✅ All tools validated successfully! Agent Container Smoke Test confirms agent container is ready. |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
@copilot the cli wrappers must implement a proper mcp client protocol and maintain a session |
This comment has been minimized.
This comment has been minimized.
|
Smoke Test #23981224949 |
Overall:
|
There was a problem hiding this comment.
This PR adds MCP server CLI mounting to all workflow lock files — a useful improvement for discoverability. The pattern of continue-on-error: true is appropriate for non-critical tooling. Two minor suggestions: add explicit success logging in the script, and consider documenting the mount_mcp_as_cli.cjs function signature for future maintainers.
📰 BREAKING: Report filed by Smoke Copilot · ● 860.4K
| "apiKey": "${MCP_GATEWAY_API_KEY}", | ||
| "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" | ||
| } | ||
| } |
There was a problem hiding this comment.
Consider adding a debug output after await main() (e.g., core.info('MCP CLI mounts completed')) to make it easier to diagnose issues in the Actions log when continue-on-error silently eats failures.
| "apiKey": "${MCP_GATEWAY_API_KEY}", | ||
| "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" | ||
| } | ||
| } |
There was a problem hiding this comment.
The continue-on-error: true flag is appropriate here since mounting MCP CLIs is non-critical — failing silently is better than blocking the workflow. Good defensive pattern. 👍
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
This comment has been minimized.
This comment has been minimized.
|
@copilot merge main and recompile |
…-mounting-mcp-servers # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in d22ea30. Merged main and recompiled all 181 workflows successfully. 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:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing... |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
🌑 The shadows whisper... Smoke Codex failed. The oracle requires further meditation... |
|
✅ All tools validated successfully! Agent Container Smoke Test confirms agent container is ready. |
Agent Container Tool Check
Result: 12/12 tools available ✅ Overall Status: PASS
|
There was a problem hiding this comment.
Pull request overview
Adds an opt-in workflow feature to mount MCP servers as local CLI commands after the MCP gateway starts, and injects a prompt section listing those CLIs so the agent uses wrappers instead of speaking MCP directly.
Changes:
- Introduces a new
tools.mount-as-clisflag, plus workflow generation to run a post-gateway “mount as CLI” step. - Adds a Node script to read an MCP manifest, discover server tools, and generate read-only CLI wrapper scripts on
PATH. - Updates gateway config conversion scripts and prompt placeholder validation to support the new prompt section and filtering behavior.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/unified_prompt_step.go | Injects the new <mcp-clis> prompt section into the unified prompt. |
| pkg/workflow/tools_types.go | Adds MountAsCLIs to typed tools config. |
| pkg/workflow/tools_parser.go | Parses mount-as-clis from tools: and excludes it from custom tool detection. |
| pkg/workflow/prompt_constants.go | Adds constant for the new prompt template filename. |
| pkg/workflow/mcp_setup_generator.go | Exports GH_AW_MCP_CLI_SERVERS for downstream config filtering. |
| pkg/workflow/mcp_rendering.go | Documents that CLI-mounted servers remain in gateway config; filtering occurs later. |
| pkg/workflow/mcp_cli_mount.go | New logic to compute CLI-mounted server list, generate mount step, and build prompt section. |
| pkg/workflow/compiler_yaml_main_job.go | Adds a generated “Mount MCP servers as CLIs” step after MCP setup. |
| pkg/parser/schemas/main_workflow_schema.json | Adds schema for tools.mount-as-clis. |
| actions/setup/sh/validate_prompt_placeholders.sh | Ignores backtick-quoted placeholder names during placeholder validation. |
| actions/setup/sh/validate_prompt_placeholders_test.sh | Adds regression test for backtick-quoted placeholder names. |
| actions/setup/sh/start_mcp_gateway.sh | Saves a CLI manifest and filters CLI-mounted servers out of fallback agent config. |
| actions/setup/sh/convert_gateway_config_gemini.sh | Filters CLI-mounted servers out of Gemini agent MCP config. |
| actions/setup/sh/convert_gateway_config_copilot.sh | Filters CLI-mounted servers out of Copilot agent MCP config. |
| actions/setup/sh/convert_gateway_config_codex.sh | Filters CLI-mounted servers out of Codex agent MCP config output. |
| actions/setup/sh/convert_gateway_config_claude.sh | Filters CLI-mounted servers out of Claude agent MCP config. |
| actions/setup/md/mcp_cli_tools_prompt.md | New prompt template describing how to use mounted MCP CLIs. |
| actions/setup/js/mount_mcp_as_cli.cjs | New script that reads manifest, performs MCP handshake, and generates CLI wrappers. |
| .github/workflows/smoke-copilot.md | Enables mount-as-clis: true and updates smoke prompts to use CLI syntax. |
| .github/workflows/smoke-copilot.lock.yml | Recompiled lockfile reflecting the new mount step and prompt injection. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
pkg/workflow/mcp_cli_mount.go:54
- getMCPCLIServerNames currently returns "agentic-workflows" for the built-in tool, but the actual MCP server ID used in gateway configs (and thus in the CLI manifest / wrapper name) is "agenticworkflows" (no hyphen). This mismatch is visible in the compiled lock file where GH_AW_MCP_CLI_SERVERS contains "agentic-workflows" while the gateway config key is "agenticworkflows", so filtering won’t remove it from the agent config and the prompt will advertise a non-existent CLI name. Please map tool keys to the correct MCP server IDs (e.g., use constants.AgenticWorkflowsMCPServerID.String()).
// Only include tools that have MCP servers (skip bash, web-fetch, web-search, edit, cache-memory, etc.)
switch toolName {
case "github", "playwright", "qmd", "agentic-workflows":
servers = append(servers, toolName)
default:
actions/setup/js/mount_mcp_as_cli.cjs:419
- Server names from the manifest are used directly in path.join() and interpolated into the generated bash script (e.g., TOOLS_DIR/
${name}.json, CLI_BIN_DIR/name, andSERVER_NAME="${serverName}"). Because MCP server IDs ultimately come from user-controlled config keys and aren’t validated/sanitized, a malicious name containing path separators or quotes could write files outside the intended directory or break the generated script. Please validate/sanitizenameto a safe identifier (e.g., restrict to[A-Za-z0-9._-]+and skip/warn otherwise) before using it in paths or templates.
for (const server of servers) {
const { name, url } = server;
core.info(`Mounting MCP server '${name}' (url: ${url})...`);
const toolsFile = path.join(TOOLS_DIR, `${name}.json`);
// Query tools from the server
const tools = await fetchMCPTools(url, apiKey, core);
core.info(` Found ${tools.length} tool(s)`);
// Cache the tool list
try {
fs.writeFileSync(toolsFile, JSON.stringify(tools, null, 2), { mode: 0o644 });
} catch (err) {
core.warning(` Failed to write tools cache for ${name}: ${err instanceof Error ? err.message : String(err)}`);
}
// Write the CLI wrapper script
const scriptPath = path.join(CLI_BIN_DIR, name);
try {
fs.writeFileSync(scriptPath, generateCLIWrapperScript(name, url, toolsFile), { mode: 0o755 });
- Files reviewed: 20/20 changed files
- Comments generated: 5
pkg/workflow/tools_types.go
Outdated
| // a read-only directory added to PATH, and those servers are removed from the | ||
| // MCP gateway config (so the agent uses the CLI instead of the MCP protocol). |
There was a problem hiding this comment.
The MountAsCLIs doc comment says CLI-mounted servers are removed from the “MCP gateway config”, but this PR’s implementation keeps them in the gateway config and instead filters them out of the agent’s final MCP config (via GH_AW_MCP_CLI_SERVERS + convert_gateway_config_*.sh). Please update this comment to reflect the actual behavior to avoid misleading future changes.
| // a read-only directory added to PATH, and those servers are removed from the | |
| // MCP gateway config (so the agent uses the CLI instead of the MCP protocol). | |
| // a read-only directory added to PATH. The servers remain in the MCP gateway | |
| // config, but are filtered out of the agent's final MCP config so the agent | |
| // uses the CLI instead of the MCP protocol. |
| }, | ||
| "mount-as-clis": { | ||
| "type": "boolean", | ||
| "description": "When true, each user-facing MCP server is mounted as a standalone CLI tool on PATH. The agent can then call MCP servers via shell commands (e.g. 'github issue_read --method get ...'). Servers that are CLI-mounted are removed from the MCP gateway config. Default: false.", |
There was a problem hiding this comment.
Schema description for tools.mount-as-clis claims CLI-mounted servers are removed from the “MCP gateway config”, but the code now explicitly keeps them in the gateway config (so containers start) and only removes them from the agent’s final config in convert_gateway_config_*.sh. Please update the schema description so it matches the runtime behavior.
| "description": "When true, each user-facing MCP server is mounted as a standalone CLI tool on PATH. The agent can then call MCP servers via shell commands (e.g. 'github issue_read --method get ...'). Servers that are CLI-mounted are removed from the MCP gateway config. Default: false.", | |
| "description": "When true, each user-facing MCP server is mounted as a standalone CLI tool on PATH. The agent can then call MCP servers via shell commands (e.g. 'github issue_read --method get ...'). CLI-mounted servers remain in the MCP gateway config so their containers can start, and are removed only from the agent's final config during convert_gateway_config_*.sh processing. Default: false.", |
pkg/workflow/mcp_cli_mount.go
Outdated
| // actions/github-script which: | ||
| // - Reads the CLI manifest saved by start_mcp_gateway.sh | ||
| // - Queries each server for its tools/list via JSON-RPC | ||
| // - Writes a standalone CLI wrapper script for each server to /tmp/gh-aw/mcp-cli/bin/ |
There was a problem hiding this comment.
The file header comment says CLI wrapper scripts are written to /tmp/gh-aw/mcp-cli/bin/, but mount_mcp_as_cli.cjs generates them under ${RUNNER_TEMP}/gh-aw/mcp-cli/bin so they’re accessible inside the AWF sandbox. Please update this comment to match the actual output path.
This issue also appears on line 50 of the same file.
| // - Writes a standalone CLI wrapper script for each server to /tmp/gh-aw/mcp-cli/bin/ | |
| // - Writes a standalone CLI wrapper script for each server to ${RUNNER_TEMP}/gh-aw/mcp-cli/bin/ |
| // should not be exposed as user-facing CLI tools. | ||
| var internalMCPServerNames = map[string]bool{ | ||
| "safeoutputs": true, | ||
| "mcp-scripts": true, |
There was a problem hiding this comment.
internalMCPServerNames includes "mcp-scripts", but the actual MCP server ID used in rendered gateway configs is "mcpscripts" (see pkg/constants/job_constants.go) and the manifest will therefore contain "mcpscripts". As-is, enabling mount-as-clis can accidentally expose the internal mcpscripts server as a CLI. Consider excluding both "mcp-scripts" (config key) and "mcpscripts" (server ID) consistently.
| // should not be exposed as user-facing CLI tools. | |
| var internalMCPServerNames = map[string]bool{ | |
| "safeoutputs": true, | |
| "mcp-scripts": true, | |
| // should not be exposed as user-facing CLI tools. | |
| // Include both config-key and rendered server-ID variants where they differ. | |
| var internalMCPServerNames = map[string]bool{ | |
| "safeoutputs": true, | |
| "mcp-scripts": true, | |
| "mcpscripts": true, |
| const TOOLS_DIR = `${RUNNER_TEMP}/gh-aw/mcp-cli/tools`; | ||
|
|
||
| /** MCP servers that are internal infrastructure and should not be user-facing CLIs */ | ||
| const INTERNAL_SERVERS = new Set(["safeoutputs", "mcp-scripts"]); |
There was a problem hiding this comment.
INTERNAL_SERVERS excludes "mcp-scripts", but the gateway/server ID is "mcpscripts" (no hyphen). The CLI manifest will therefore contain "mcpscripts" and this step will mount it as a user-facing CLI unless it’s added to the internal exclusion list (or otherwise filtered).
This issue also appears on line 399 of the same file.
| const INTERNAL_SERVERS = new Set(["safeoutputs", "mcp-scripts"]); | |
| const INTERNAL_SERVERS = new Set(["safeoutputs", "mcp-scripts", "mcpscripts"]); |
|
@copilot read comments |
|
Smoke Test §23985224521 — PR #24503 (
Overall:
|
There was a problem hiding this comment.
Smoke test review for PR #24503 — MCP CLI mounting feature. The new mount_mcp_as_cli.cjs and mcp_cli_mount.go add a nice ergonomic improvement for agents. Two issues found: (1) generated bash scripts have a syntax error from an unclosed quote in the multi-line jq expression (bash -n validation fails); (2) the RUNNER_TEMP fallback path is hardcoded. The build passes, file writing and web-fetch work correctly. The core concept is solid but the script generation needs a fix before the CLIs are usable.
📰 BREAKING: Report filed by Smoke Copilot · ● 2.1M
| const MANIFEST_FILE = "/tmp/gh-aw/mcp-cli/manifest.json"; | ||
| // Use RUNNER_TEMP so the bin and tools directories are inside the AWF sandbox mount | ||
| // (AWF mounts ${RUNNER_TEMP}/gh-aw read-only; /tmp/gh-aw is not accessible inside AWF) | ||
| const RUNNER_TEMP = process.env.RUNNER_TEMP || "/home/runner/work/_temp"; |
There was a problem hiding this comment.
The RUNNER_TEMP fallback to /home/runner/work/_temp is reasonable, but consider using a more portable fallback like process.env.RUNNER_TEMP || path.join(require('os').tmpdir(), 'gh-aw') to avoid hardcoding a runner-specific path.
| "GH_AW_MCP_CLI_SERVERS_LIST": serversList, | ||
| }, | ||
| } | ||
| } |
There was a problem hiding this comment.
The multi-line jq expression that generates CLI output formatting (lines 153-158 of the generated bash scripts) contains an unclosed string literal, causing a bash syntax error (unexpected EOF while looking for matching '"'). The generated scripts fail with bash -n validation. The jq expression spanning multiple lines needs to be handled carefully to avoid shell quoting issues — consider using a heredoc or single-quoted jq string.
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
Smoke Test Results — Run §23985224528Core tests #1–12: ✅✅✅✅✅✅✅✅✅✅✅✅ Status: PARTIAL — all executed tests passed; #16 (resolve thread, no node IDs available) and #19 (close PR, skipped) were skipped.
|
There was a problem hiding this comment.
💥 Automated smoke test review - all systems nominal!
💥 [THE END] — Illustrated by Smoke Claude · ● 249.4K
| ...headers, | ||
| }, | ||
| }; | ||
|
|
There was a problem hiding this comment.
The httpPostJSON helper is clean and well-structured. Consider adding a note in the JSDoc about the 15s default timeout behavior, since callers for initialize and tools/list have different latency expectations.
| # Show all available tools for a server | ||
| <server-name> --help | ||
|
|
||
| # Show help for a specific tool |
There was a problem hiding this comment.
Good use of structured CLI usage examples. Would be helpful to add an example showing how to handle multi-word values with spaces (e.g., --param "value with spaces") since agents may need this for natural-language inputs.
…ripts exclusion Agent-Logs-Url: https://github.com/github/gh-aw/sessions/4e66887c-a46e-489f-83bd-7d092d487482 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed all 5 review comments in 2946954:
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:
If you need me to access, download, or install something from one of these locations, you can either:
|
Summary
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: trueflag (defaultfalse). When enabled, all user-facing MCP servers — including built-in ones likegithubandplaywrightas well as custom servers — are exposed as standalone shell commands and excluded from the agent's final MCP config so the agent uses the CLI wrappers exclusively. Whenfalse, no CLI mounting step is emitted and no prompt section is injected.How It Works
After the MCP gateway starts, a new "Mount MCP servers as CLIs" workflow step runs
mount_mcp_as_cli.cjsviaactions/github-script. This script:start_mcp_gateway.shbefore cleanup)initialize→notifications/initialized→tools/list) to discover available tools${RUNNER_TEMP}/gh-aw/mcp-cli/bin/<server-name>chmod 555) so the agent cannot modify or add scriptsPATHviacore.addPath()for subsequent stepsThe agent is also informed about these tools via an injected prompt section (wrapped in
<mcp-clis>XML tags) listing the available CLI commands.Architecture: Gateway vs. Agent Config
The MCP gateway must start Docker containers for all configured servers — including CLI-mounted ones — so they have reachable endpoints for the CLI manifest. The filtering is therefore applied in two stages:
start_mcp_gateway.sh): includes all servers so the gateway starts their containers and populates/tmp/gh-aw/mcp-cli/manifest.json.convert_gateway_config_*.sh): CLI-mounted servers are excluded via theGH_AW_MCP_CLI_SERVERSenvironment variable (a JSON array exported in the gateway step), so the agent cannot reach them directly and must use the CLI wrappers.AWF Sandbox Path
CLI wrapper scripts and tools JSON are generated under
${RUNNER_TEMP}/gh-aw/mcp-cli/(not/tmp/gh-aw/) so they are accessible inside the AWF sandbox, which mounts${RUNNER_TEMP}/gh-awread-only. The manifest file written bystart_mcp_gateway.shremains at/tmp/gh-aw/mcp-cli/manifest.jsonsince it is only read during the setup step, which runs on the host before AWF starts.Changes
New:
actions/setup/js/mount_mcp_as_cli.cjs/tmp/gh-aw/mcp-cli/manifest.jsoninitialize— establishes session, capturesMcp-Session-Idnotifications/initialized— required handshake notification (server responds 204 No Content)tools/list/tools/call— executed within the established session<server> --help— list all available tools<server> <tool> --help— show tool description and parameters<server> <tool> [--param value ...]— call a tool (follows the same 3-step MCP session protocol per invocation)safeoutputs,mcp-scripts) andcache-memory(file share, not an MCP server) are excluded${RUNNER_TEMP}/gh-aw/mcp-cli/bin/in achmod 555directory the agent cannot write to${RUNNER_TEMP}/gh-aw/mcp-cli/tools/so scripts can access it inside AWFcore.info()/core.warning()logging throughoutNew:
actions/setup/md/mcp_cli_tools_prompt.md<mcp-clis>prompt section, following the same pattern as other prompt templates (safe_outputs_prompt.md,github_mcp_tools_prompt.md, etc.)__GH_AW_MCP_CLI_SERVERS_LIST__placeholder substituted at runtime by thesubstitute_placeholdersstepcat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"in compiled lock filesModified:
actions/setup/sh/start_mcp_gateway.sh/tmp/gh-aw/mcp-cli/manifest.jsonwith server names and local URLs beforegateway-output.jsonis deletedGH_AW_MCP_CLI_SERVERSModified:
actions/setup/sh/convert_gateway_config_*.sh(Copilot, Claude, Codex, Gemini)GH_AW_MCP_CLI_SERVERS(JSON array) and excludes those servers from the agent's final MCP config using--argjson cliServers "${GH_AW_MCP_CLI_SERVERS:-[]}"in thejqcallNew:
pkg/workflow/mcp_cli_mount.gogetMCPCLIServerNames()— returns sorted list of user-facing MCP servers to mount (built-in and custom); returns nil whentools.mount-as-clisis nottruegenerateMCPCLIMountStep()— generates the "Mount MCP servers as CLIs"actions/github-scriptstep in compiled workflows; no-op when flag is falsebuildMCPCLIPromptSection()— returnsIsFile: truereferencingmcp_cli_tools_prompt.mdwith the server list passed asGH_AW_MCP_CLI_SERVERS_LISTenv var; no-op when flag is falseModified:
pkg/workflow/tools_types.goandpkg/workflow/tools_parser.goMountAsCLIs boolfield toToolsConfig(parsed fromtools.mount-as-clis, defaultfalse)Modified:
pkg/parser/schemas/main_workflow_schema.jsonmount-as-clisboolean property to the tools schemaModified:
pkg/workflow/mcp_rendering.gocomposeCLIMountFilter— CLI-mounted servers are no longer excluded from the gateway config (they must be started by the gateway). Filtering is now delegated to the conversion scripts.Modified:
pkg/workflow/mcp_setup_generator.goGH_AW_MCP_CLI_SERVERS(JSON array built withjson.Marshal) in the gateway step script, afterGH_AW_ENGINE, so conversion scripts can exclude those servers from the agent configModified:
pkg/workflow/compiler_yaml_main_job.gogenerateMCPCLIMountStep()aftergenerateMCPSetup()completesModified:
pkg/workflow/unified_prompt_step.go<mcp-clis>XML tags) after safe outputs (section 8a)Modified:
actions/setup/sh/validate_prompt_placeholders.sh__GH_AW_*__placeholders, so documented placeholder names in PR descriptions or code examples are not flagged as errorsModified:
.github/workflows/smoke-copilot.mdmount-as-clis: trueto exercise the feature in smoke testinggithub pull_request_read --method list ...,serena activate_project --path ...,playwright browser_navigate --url ...)Updated
.lock.ymlfiles recompiledExample
For a workflow configured with
mount-as-clis: true,playwright,github, and a customtavilyMCP server, the agent will have:Those servers are excluded from the agent's MCP config, so the agent interacts with them exclusively through the CLI wrappers. The gateway still starts all Docker containers so the CLI wrappers can communicate with them.
The prompt injected to the agent (loaded from
mcp_cli_tools_prompt.md):✨ PR Review Safe Output Test - Run 23985224528