From a651e13cd0e38f8b58f30bafeaf2c62d18f3965c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 06:51:19 +0000 Subject: [PATCH 1/3] Initial plan From af198dc221dab6f64488d2fbabc0b93d6ea0499b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 07:05:13 +0000 Subject: [PATCH 2/3] Refactor shared gateway entry normalization Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../convert_gateway_config_adapters.test.cjs | 15 +++++++++++++- .../js/convert_gateway_config_claude.cjs | 14 +++++-------- .../js/convert_gateway_config_copilot.cjs | 18 +++++++---------- .../js/convert_gateway_config_gemini.cjs | 14 +++++-------- .../js/convert_gateway_config_shared.cjs | 20 +++++++++++++++++++ 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/actions/setup/js/convert_gateway_config_adapters.test.cjs b/actions/setup/js/convert_gateway_config_adapters.test.cjs index 6193a4095ff..9b53584bcfd 100644 --- a/actions/setup/js/convert_gateway_config_adapters.test.cjs +++ b/actions/setup/js/convert_gateway_config_adapters.test.cjs @@ -4,7 +4,7 @@ import fs from "fs"; import os from "os"; import path from "path"; -import { rewriteUrl, filterAndTransformServers, writeSecureOutput } from "./convert_gateway_config_shared.cjs"; +import { rewriteUrl, normalizeGatewayEntry, filterAndTransformServers, writeSecureOutput } from "./convert_gateway_config_shared.cjs"; import { transformClaudeEntry } from "./convert_gateway_config_claude.cjs"; import { transformCopilotEntry } from "./convert_gateway_config_copilot.cjs"; import { transformGeminiEntry } from "./convert_gateway_config_gemini.cjs"; @@ -16,6 +16,19 @@ describe("convert gateway config shared pipeline", () => { expect(rewritten).toBe("http://host.docker.internal:80/mcp/github"); }); + it("normalizes gateway entry with provider mutation and url rewrite", () => { + const entry = { type: "ignored", url: "http://old/mcp/github", headers: { Authorization: "token" } }; + const normalized = normalizeGatewayEntry(entry, "http://host.docker.internal:80", transformed => { + transformed.type = "http"; + }); + expect(normalized).toEqual({ + type: "http", + url: "http://host.docker.internal:80/mcp/github", + headers: { Authorization: "token" }, + }); + expect(entry).toEqual({ type: "ignored", url: "http://old/mcp/github", headers: { Authorization: "token" } }); + }); + it("filters CLI-mounted servers before applying engine transforms", () => { const servers = { github: { url: "http://old/mcp/github" }, diff --git a/actions/setup/js/convert_gateway_config_claude.cjs b/actions/setup/js/convert_gateway_config_claude.cjs index 42dd2b3cd49..c0dbabb1963 100644 --- a/actions/setup/js/convert_gateway_config_claude.cjs +++ b/actions/setup/js/convert_gateway_config_claude.cjs @@ -23,7 +23,7 @@ require("./shim.cjs"); */ const path = require("path"); -const { rewriteUrl, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs"); +const { rewriteUrl, normalizeGatewayEntry, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs"); const OUTPUT_PATH = path.join(process.env.RUNNER_TEMP || "/tmp", "gh-aw/mcp-config/mcp-servers.json"); @@ -33,14 +33,10 @@ const OUTPUT_PATH = path.join(process.env.RUNNER_TEMP || "/tmp", "gh-aw/mcp-conf * @returns {Record} */ function transformClaudeEntry(entry, urlPrefix) { - const transformed = { ...entry }; - // Claude uses "type": "http" for HTTP-based MCP servers - transformed.type = "http"; - // Fix the URL to use the correct domain - if (typeof transformed.url === "string") { - transformed.url = rewriteUrl(transformed.url, urlPrefix); - } - return transformed; + return normalizeGatewayEntry(entry, urlPrefix, transformed => { + // Claude uses "type": "http" for HTTP-based MCP servers + transformed.type = "http"; + }); } function main() { diff --git a/actions/setup/js/convert_gateway_config_copilot.cjs b/actions/setup/js/convert_gateway_config_copilot.cjs index bda12b2047c..6c42bc9c05d 100644 --- a/actions/setup/js/convert_gateway_config_copilot.cjs +++ b/actions/setup/js/convert_gateway_config_copilot.cjs @@ -25,7 +25,7 @@ require("./shim.cjs"); */ const path = require("path"); -const { rewriteUrl, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs"); +const { rewriteUrl, normalizeGatewayEntry, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs"); /** * Resolves the Copilot CLI MCP config output path from the runtime $HOME. @@ -54,16 +54,12 @@ function resolveCopilotConfigOutputPath() { * @returns {Record} */ function transformCopilotEntry(entry, urlPrefix) { - const transformed = { ...entry }; - // Add tools field if not present - if (!transformed.tools) { - transformed.tools = ["*"]; - } - // Fix the URL to use the correct domain - if (typeof transformed.url === "string") { - transformed.url = rewriteUrl(transformed.url, urlPrefix); - } - return transformed; + return normalizeGatewayEntry(entry, urlPrefix, transformed => { + // Add tools field if not present + if (!transformed.tools) { + transformed.tools = ["*"]; + } + }); } function main() { diff --git a/actions/setup/js/convert_gateway_config_gemini.cjs b/actions/setup/js/convert_gateway_config_gemini.cjs index 460ae4e5161..b4038f6ebaa 100644 --- a/actions/setup/js/convert_gateway_config_gemini.cjs +++ b/actions/setup/js/convert_gateway_config_gemini.cjs @@ -31,7 +31,7 @@ require("./shim.cjs"); */ const path = require("path"); -const { rewriteUrl, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs"); +const { rewriteUrl, normalizeGatewayEntry, loadGatewayContext, logCLIFilters, filterAndTransformServers, logServerStats, writeSecureOutput } = require("./convert_gateway_config_shared.cjs"); /** * @param {Record} entry @@ -39,14 +39,10 @@ const { rewriteUrl, loadGatewayContext, logCLIFilters, filterAndTransformServers * @returns {Record} */ function transformGeminiEntry(entry, urlPrefix) { - const transformed = { ...entry }; - // Remove "type" field — Gemini uses transport auto-detection from url/httpUrl - delete transformed.type; - // Fix the URL to use the correct domain - if (typeof transformed.url === "string") { - transformed.url = rewriteUrl(transformed.url, urlPrefix); - } - return transformed; + return normalizeGatewayEntry(entry, urlPrefix, transformed => { + // Remove "type" field — Gemini uses transport auto-detection from url/httpUrl + delete transformed.type; + }); } function main() { diff --git a/actions/setup/js/convert_gateway_config_shared.cjs b/actions/setup/js/convert_gateway_config_shared.cjs index 5d720010f22..1848063a02c 100644 --- a/actions/setup/js/convert_gateway_config_shared.cjs +++ b/actions/setup/js/convert_gateway_config_shared.cjs @@ -16,6 +16,25 @@ function rewriteUrl(url, urlPrefix) { return url.replace(/^http:\/\/[^/]+\/mcp\//, `${urlPrefix}/mcp/`); } +/** + * Clone a gateway entry, apply provider-specific mutations, and rewrite URL. + * + * @param {Record} entry + * @param {string} urlPrefix + * @param {(transformed: Record) => void} [mutate] + * @returns {Record} + */ +function normalizeGatewayEntry(entry, urlPrefix, mutate) { + const transformed = { ...entry }; + if (mutate) { + mutate(transformed); + } + if (typeof transformed.url === "string") { + transformed.url = rewriteUrl(transformed.url, urlPrefix); + } + return transformed; +} + /** * @param {string} name * @returns {string} @@ -129,6 +148,7 @@ function writeSecureOutput(outputPath, output) { module.exports = { rewriteUrl, + normalizeGatewayEntry, loadGatewayContext, logCLIFilters, filterAndTransformServers, From d13c2ff1d450a5833a7786c527a30d506f66592b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 1 Jul 2026 11:58:23 +0000 Subject: [PATCH 3/3] Fix normalizeGatewayEntry docstring to clarify shallow clone semantics Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/convert_gateway_config_shared.cjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/actions/setup/js/convert_gateway_config_shared.cjs b/actions/setup/js/convert_gateway_config_shared.cjs index 1848063a02c..c539461e0ce 100644 --- a/actions/setup/js/convert_gateway_config_shared.cjs +++ b/actions/setup/js/convert_gateway_config_shared.cjs @@ -17,7 +17,8 @@ function rewriteUrl(url, urlPrefix) { } /** - * Clone a gateway entry, apply provider-specific mutations, and rewrite URL. + * Shallow-clone a gateway entry, apply provider-specific mutations, and rewrite URL. + * Note: only the top-level object is cloned; nested fields (e.g., `headers`) are shared references. * * @param {Record} entry * @param {string} urlPrefix