From 1a82cc3055ef1bd2e8663f8eae5a99e1734ecbdf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 16:07:49 +0000 Subject: [PATCH 1/3] Initial plan From 06f1970e90de503c54df528d9b931be76c032654 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 16:22:03 +0000 Subject: [PATCH 2/3] Clarify MCP CLI prompt fallback to MCP tools Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/md/mcp_cli_tools_prompt.md | 1 + pkg/workflow/mcp_cli_mount_test.go | 1 + 2 files changed, 2 insertions(+) diff --git a/actions/setup/md/mcp_cli_tools_prompt.md b/actions/setup/md/mcp_cli_tools_prompt.md index df823c6683b..3edd6ba4b50 100644 --- a/actions/setup/md/mcp_cli_tools_prompt.md +++ b/actions/setup/md/mcp_cli_tools_prompt.md @@ -2,5 +2,6 @@ CLI servers are available on `PATH`: __GH_AW_MCP_CLI_SERVERS_LIST__ Use ` --help` for tool names, parameters, and examples before calling any command. +If a listed CLI wrapper is unavailable, continue using the corresponding MCP tool directly. Do not treat a missing CLI wrapper as a missing capability. To pass many arguments safely, pipe a JSON object on stdin with `printf` and pass `.` as the payload sentinel: `printf '%s\n' '{"param":"value","count":1}' | .` diff --git a/pkg/workflow/mcp_cli_mount_test.go b/pkg/workflow/mcp_cli_mount_test.go index 205cfa178b5..d429b088c25 100644 --- a/pkg/workflow/mcp_cli_mount_test.go +++ b/pkg/workflow/mcp_cli_mount_test.go @@ -226,4 +226,5 @@ func TestBuildMCPCLIPromptSection_PromptFileUsesNonHeadingLabels(t *testing.T) { assert.NotRegexp(t, `(?m)^\s*(>\s*)?##\s+`, prompt, "prompt must not contain H2 Markdown headings") assert.NotRegexp(t, `(?m)^\s*(>\s*)?###\s+`, prompt, "prompt must not contain H3 Markdown headings") assert.Contains(t, prompt, "Use ` --help` for tool names, parameters, and examples before calling any command.") + assert.Contains(t, prompt, "If a listed CLI wrapper is unavailable, continue using the corresponding MCP tool directly.") } From 67ce9d1e082a9e4bd2ad19c9e221a0238bc5af82 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 14 Jun 2026 16:46:45 +0000 Subject: [PATCH 3/3] Fix MCP CLI wrapper list to reflect actual mounted servers Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/mount_mcp_as_cli.cjs | 13 ++++++++++++- actions/setup/js/mount_mcp_as_cli.test.cjs | 7 ++++++- actions/setup/md/mcp_cli_tools_prompt.md | 1 - pkg/workflow/mcp_cli_mount.go | 18 ++++++------------ pkg/workflow/mcp_cli_mount_test.go | 2 +- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/actions/setup/js/mount_mcp_as_cli.cjs b/actions/setup/js/mount_mcp_as_cli.cjs index 81702623441..ffaeba68818 100644 --- a/actions/setup/js/mount_mcp_as_cli.cjs +++ b/actions/setup/js/mount_mcp_as_cli.cjs @@ -311,6 +311,16 @@ exec node "${safeBridge}" \\ `; } +/** + * Format mounted server names into prompt-ready bullet lines. + * + * @param {string[]} mountedServers - Successfully mounted server names + * @returns {string} + */ +function formatMountedServersPromptList(mountedServers) { + return mountedServers.map(name => `- \`${name}\` — run \`${name} --help\` to see available tools`).join("\n"); +} + /** * Mount MCP servers as CLI tools by reading the manifest and generating wrapper scripts. * @@ -445,6 +455,7 @@ async function main() { } core.info(`CLI bin directory added to PATH: ${CLI_BIN_DIR}`); core.setOutput("mounted-servers", mountedServers.join(",")); + core.setOutput("mounted-servers-list", formatMountedServersPromptList(mountedServers)); } -module.exports = { main, fetchMCPTools, generateCLIWrapperScript, isValidServerName, shellEscapeDoubleQuoted, parseMCPResponseBody }; +module.exports = { main, fetchMCPTools, generateCLIWrapperScript, isValidServerName, shellEscapeDoubleQuoted, parseMCPResponseBody, formatMountedServersPromptList }; diff --git a/actions/setup/js/mount_mcp_as_cli.test.cjs b/actions/setup/js/mount_mcp_as_cli.test.cjs index cd86c1f53be..233858cce08 100644 --- a/actions/setup/js/mount_mcp_as_cli.test.cjs +++ b/actions/setup/js/mount_mcp_as_cli.test.cjs @@ -1,7 +1,7 @@ // @ts-check import { describe, expect, it } from "vitest"; -import { parseMCPResponseBody } from "./mount_mcp_as_cli.cjs"; +import { formatMountedServersPromptList, parseMCPResponseBody } from "./mount_mcp_as_cli.cjs"; describe("mount_mcp_as_cli.cjs", () => { it("parses JSON object responses unchanged", () => { @@ -38,4 +38,9 @@ describe("mount_mcp_as_cli.cjs", () => { }, }); }); + + it("formats mounted servers for prompt rendering", () => { + expect(formatMountedServersPromptList(["safeoutputs", "playwright"])).toBe("- `safeoutputs` — run `safeoutputs --help` to see available tools\n- `playwright` — run `playwright --help` to see available tools"); + expect(formatMountedServersPromptList([])).toBe(""); + }); }); diff --git a/actions/setup/md/mcp_cli_tools_prompt.md b/actions/setup/md/mcp_cli_tools_prompt.md index 3edd6ba4b50..df823c6683b 100644 --- a/actions/setup/md/mcp_cli_tools_prompt.md +++ b/actions/setup/md/mcp_cli_tools_prompt.md @@ -2,6 +2,5 @@ CLI servers are available on `PATH`: __GH_AW_MCP_CLI_SERVERS_LIST__ Use ` --help` for tool names, parameters, and examples before calling any command. -If a listed CLI wrapper is unavailable, continue using the corresponding MCP tool directly. Do not treat a missing CLI wrapper as a missing capability. To pass many arguments safely, pipe a JSON object on stdin with `printf` and pass `.` as the payload sentinel: `printf '%s\n' '{"param":"value","count":1}' | .` diff --git a/pkg/workflow/mcp_cli_mount.go b/pkg/workflow/mcp_cli_mount.go index 92008009f34..260bed34349 100644 --- a/pkg/workflow/mcp_cli_mount.go +++ b/pkg/workflow/mcp_cli_mount.go @@ -297,28 +297,22 @@ func GetMCPCLIPathSetup(data *WorkflowData) string { return `export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH"` } -// 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. +// buildMCPCLIPromptSection returns a PromptSection describing CLI wrappers available +// to the agent, or nil if no servers are configured for mounting. +// The prompt content is loaded from actions/setup/md/mcp_cli_tools_prompt.md at runtime. +// The server list comes from the mount step output so only successfully mounted wrappers +// are advertised to the model. func buildMCPCLIPromptSection(data *WorkflowData) *PromptSection { servers := getMCPCLIServerNames(data) if len(servers) == 0 { return nil } - // Build the human-readable list of servers with example usage - var listLines []string - for _, name := range servers { - listLines = append(listLines, fmt.Sprintf("- `%s` — run `%s --help` to see available tools", name, name)) - } - serversList := strings.Join(listLines, "\n") - return &PromptSection{ Content: mcpCLIToolsPromptFile, IsFile: true, EnvVars: map[string]string{ - "GH_AW_MCP_CLI_SERVERS_LIST": serversList, + "GH_AW_MCP_CLI_SERVERS_LIST": "${{ steps.mount-mcp-clis.outputs.mounted-servers-list }}", }, } } diff --git a/pkg/workflow/mcp_cli_mount_test.go b/pkg/workflow/mcp_cli_mount_test.go index d429b088c25..207ca774742 100644 --- a/pkg/workflow/mcp_cli_mount_test.go +++ b/pkg/workflow/mcp_cli_mount_test.go @@ -226,5 +226,5 @@ func TestBuildMCPCLIPromptSection_PromptFileUsesNonHeadingLabels(t *testing.T) { assert.NotRegexp(t, `(?m)^\s*(>\s*)?##\s+`, prompt, "prompt must not contain H2 Markdown headings") assert.NotRegexp(t, `(?m)^\s*(>\s*)?###\s+`, prompt, "prompt must not contain H3 Markdown headings") assert.Contains(t, prompt, "Use ` --help` for tool names, parameters, and examples before calling any command.") - assert.Contains(t, prompt, "If a listed CLI wrapper is unavailable, continue using the corresponding MCP tool directly.") + assert.Equal(t, "${{ steps.mount-mcp-clis.outputs.mounted-servers-list }}", section.EnvVars["GH_AW_MCP_CLI_SERVERS_LIST"]) }