Skip to content

Commit 67ce9d1

Browse files
Copilotpelikhan
andauthored
Fix MCP CLI wrapper list to reflect actual mounted servers
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent 06f1970 commit 67ce9d1

5 files changed

Lines changed: 25 additions & 16 deletions

File tree

actions/setup/js/mount_mcp_as_cli.cjs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,16 @@ exec node "${safeBridge}" \\
311311
`;
312312
}
313313

314+
/**
315+
* Format mounted server names into prompt-ready bullet lines.
316+
*
317+
* @param {string[]} mountedServers - Successfully mounted server names
318+
* @returns {string}
319+
*/
320+
function formatMountedServersPromptList(mountedServers) {
321+
return mountedServers.map(name => `- \`${name}\` — run \`${name} --help\` to see available tools`).join("\n");
322+
}
323+
314324
/**
315325
* Mount MCP servers as CLI tools by reading the manifest and generating wrapper scripts.
316326
*
@@ -445,6 +455,7 @@ async function main() {
445455
}
446456
core.info(`CLI bin directory added to PATH: ${CLI_BIN_DIR}`);
447457
core.setOutput("mounted-servers", mountedServers.join(","));
458+
core.setOutput("mounted-servers-list", formatMountedServersPromptList(mountedServers));
448459
}
449460

450-
module.exports = { main, fetchMCPTools, generateCLIWrapperScript, isValidServerName, shellEscapeDoubleQuoted, parseMCPResponseBody };
461+
module.exports = { main, fetchMCPTools, generateCLIWrapperScript, isValidServerName, shellEscapeDoubleQuoted, parseMCPResponseBody, formatMountedServersPromptList };

actions/setup/js/mount_mcp_as_cli.test.cjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// @ts-check
22
import { describe, expect, it } from "vitest";
33

4-
import { parseMCPResponseBody } from "./mount_mcp_as_cli.cjs";
4+
import { formatMountedServersPromptList, parseMCPResponseBody } from "./mount_mcp_as_cli.cjs";
55

66
describe("mount_mcp_as_cli.cjs", () => {
77
it("parses JSON object responses unchanged", () => {
@@ -38,4 +38,9 @@ describe("mount_mcp_as_cli.cjs", () => {
3838
},
3939
});
4040
});
41+
42+
it("formats mounted servers for prompt rendering", () => {
43+
expect(formatMountedServersPromptList(["safeoutputs", "playwright"])).toBe("- `safeoutputs` — run `safeoutputs --help` to see available tools\n- `playwright` — run `playwright --help` to see available tools");
44+
expect(formatMountedServersPromptList([])).toBe("");
45+
});
4146
});

actions/setup/md/mcp_cli_tools_prompt.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@
22
CLI servers are available on `PATH`:
33
__GH_AW_MCP_CLI_SERVERS_LIST__
44
Use `<server> --help` for tool names, parameters, and examples before calling any command.
5-
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.
65
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}' | <server> <tool> .`
76
</mcp-clis>

pkg/workflow/mcp_cli_mount.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -297,28 +297,22 @@ func GetMCPCLIPathSetup(data *WorkflowData) string {
297297
return `export PATH="${RUNNER_TEMP}/gh-aw/mcp-cli/bin:$PATH"`
298298
}
299299

300-
// buildMCPCLIPromptSection returns a PromptSection describing the CLI tools available
301-
// to the agent, or nil if there are no servers to mount.
302-
// The prompt is loaded from actions/setup/md/mcp_cli_tools_prompt.md at runtime,
303-
// with the __GH_AW_MCP_CLI_SERVERS_LIST__ placeholder substituted by the substitution step.
300+
// buildMCPCLIPromptSection returns a PromptSection describing CLI wrappers available
301+
// to the agent, or nil if no servers are configured for mounting.
302+
// The prompt content is loaded from actions/setup/md/mcp_cli_tools_prompt.md at runtime.
303+
// The server list comes from the mount step output so only successfully mounted wrappers
304+
// are advertised to the model.
304305
func buildMCPCLIPromptSection(data *WorkflowData) *PromptSection {
305306
servers := getMCPCLIServerNames(data)
306307
if len(servers) == 0 {
307308
return nil
308309
}
309310

310-
// Build the human-readable list of servers with example usage
311-
var listLines []string
312-
for _, name := range servers {
313-
listLines = append(listLines, fmt.Sprintf("- `%s` — run `%s --help` to see available tools", name, name))
314-
}
315-
serversList := strings.Join(listLines, "\n")
316-
317311
return &PromptSection{
318312
Content: mcpCLIToolsPromptFile,
319313
IsFile: true,
320314
EnvVars: map[string]string{
321-
"GH_AW_MCP_CLI_SERVERS_LIST": serversList,
315+
"GH_AW_MCP_CLI_SERVERS_LIST": "${{ steps.mount-mcp-clis.outputs.mounted-servers-list }}",
322316
},
323317
}
324318
}

pkg/workflow/mcp_cli_mount_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,5 +226,5 @@ func TestBuildMCPCLIPromptSection_PromptFileUsesNonHeadingLabels(t *testing.T) {
226226
assert.NotRegexp(t, `(?m)^\s*(>\s*)?##\s+`, prompt, "prompt must not contain H2 Markdown headings")
227227
assert.NotRegexp(t, `(?m)^\s*(>\s*)?###\s+`, prompt, "prompt must not contain H3 Markdown headings")
228228
assert.Contains(t, prompt, "Use `<server> --help` for tool names, parameters, and examples before calling any command.")
229-
assert.Contains(t, prompt, "If a listed CLI wrapper is unavailable, continue using the corresponding MCP tool directly.")
229+
assert.Equal(t, "${{ steps.mount-mcp-clis.outputs.mounted-servers-list }}", section.EnvVars["GH_AW_MCP_CLI_SERVERS_LIST"])
230230
}

0 commit comments

Comments
 (0)