Skip to content

Refactor MCP gateway converters into shared profiles - #53503

Closed
pelikhan with Copilot wants to merge 9 commits into
mainfrom
copilot/duplicate-code-remove-repeated-scaffolds
Closed

Refactor MCP gateway converters into shared profiles#53503
pelikhan with Copilot wants to merge 9 commits into
mainfrom
copilot/duplicate-code-remove-repeated-scaffolds

Conversation

Copilot AI commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

The engine-specific MCP gateway converter scripts repeated the same wrapper logic around shared conversion. This made per-engine differences harder to audit and increased drift risk.

  • Shared converter factory

    • Added convert_gateway_config_factory.cjs to build and run runGatewayConversion(...) options from declarative profiles.
    • Keeps standalone entrypoint behavior while removing repeated main() scaffolding.
  • Centralized engine profiles

    • Added convert_gateway_config_profiles.cjs for Copilot, Codex, Claude, and Gemini rules.
    • Moved output paths, URL prefix overrides, serializers, and entry transforms into one profile table.
  • Thin engine entrypoints

    • Reduced each convert_gateway_config_*.cjs script to a profile-backed wrapper.
    • Preserved existing public exports such as transformCopilotEntry, toCodexTomlSection, and main.

Example profile shape:

copilot: {
  format: "Copilot",
  engine: "Copilot",
  preRunOutputPath: resolveCopilotConfigOutputPath,
  transformEntry: transformCopilotEntry,
  serialize: servers => JSON.stringify({ mcpServers: servers }, null, 2),
  setFailedOnError: true,
}

run: https://github.com/github/gh-aw/actions/runs/32080816855> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.1 AIC · ⌖ 7.87 AIC · ⊞ 8.8K ·

Comment /souschef to run again


Run: https://github.com/github/gh-aw/actions/runs/32087856389> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10 AIC · ⌖ 8.08 AIC · ⊞ 8.8K ·

Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 9.41 AIC · ⌖ 8.04 AIC · ⊞ 8.8K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.14 AIC · ⌖ 7.76 AIC · ⊞ 6.4K ·
Comment /souschef to run again


Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.29 AIC · ⌖ 7.92 AIC · ⊞ 8.8K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor duplicate gateway-config conversion scaffolds Refactor MCP gateway converters into shared profiles Aug 17, 2026
Copilot AI requested a review from pelikhan August 17, 2026 22:20
@pelikhan
pelikhan marked this pull request as ready for review August 17, 2026 23:07
Copilot AI balanced review requested due to automatic review settings August 17, 2026 23:07

Copilot AI left a comment

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.

Pull request overview

Refactors MCP gateway converters into shared factory and profile modules while preserving engine-specific exports and behavior.

Changes:

  • Adds reusable profile-to-conversion factory logic.
  • Centralizes Copilot, Codex, Claude, and Gemini conversion rules.
  • Converts engine scripts into thin wrappers and adds focused tests.
Show a summary per file
File Description
convert_gateway_config_factory.cjs Builds and executes shared conversion options.
convert_gateway_config_factory.test.cjs Tests factory behavior and error handling.
convert_gateway_config_profiles.cjs Defines centralized engine conversion profiles.
convert_gateway_config_profiles.test.cjs Verifies supported profile declarations.
convert_gateway_config_copilot.cjs Uses the Copilot profile.
convert_gateway_config_codex.cjs Uses the Codex profile.
convert_gateway_config_claude.cjs Uses the Claude profile.
convert_gateway_config_gemini.cjs Uses the Gemini profile.

Review details

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 8/8 changed files
  • Comments generated: 0
  • Review effort level: Balanced

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please refresh this branch if needed, re-check for any unresolved review concerns, then run the pr-finisher skill and report back with the validation results and any follow-up changes.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10.1 AIC · ⌖ 7.87 AIC · ⊞ 8.8K ·
Comment /souschef to run again

Copilot AI commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please refresh this branch if needed, re-check for any unresolved review concerns, then run the pr-finisher skill and report back with the validation results and any follow-up changes.

G...

Refreshed against origin/main (already current), found no unresolved review threads, and ran pr-finisher validation. make fmt, make lint, make test-unit, converter CJS tests (5/5), make recompile, and make agent-report-progress passed; no follow-up changes were needed. make test has an unrelated existing failure in TestCopilotEngineInstallationWithCopilotSDKDriver because it still expects the ripgrep install step removed by current main commit d058c06. The prior CJS run was action_required before jobs began, so a maintainer must re-trigger CI for this head.

@github-actions

Copy link
Copy Markdown
Contributor

PR Triage

Category: refactor · Risk: medium · Score: 47/100

Breakdown: impact 25/50 · urgency 10/30 · quality 12/20

Recommended action: batch_review (batch: js-remediation)

Consolidates per-engine MCP gateway config converters (claude/codex/copilot/gemini) into a shared profile factory (+324/-245, 8 files). CI green. Only a bot COMMENTED review so far — worth a careful pass since it touches all engine converters at once. Batching with related setup-JS refactor PRs.

Generated by 🔧 PR Triage Agent · auto · 46.6 AIC · ⌖ 1.9 AIC · ⊞ 8.3K ·

@pelikhan

Copy link
Copy Markdown
Collaborator

/matt

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions github-actions Bot left a comment

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.

Skills-Based Review 🧠

Applied /codebase-design and /tdd — requesting changes on a few actionable issues.

📋 Key Themes & Highlights

Issues

  1. Dead importsrewriteUrl imported but unused in both copilot.cjs and gemini.cjs after the refactor.
  2. Side effect in a data modulecore.info(...) called inside the codex profile's getUrlPrefix, coupling logging to a pure data object.
  3. Eager vs lazy outputPathcodex and claude snapshot RUNNER_TEMP at module-load time; copilot uses a lazy thunk. The inconsistency can cause subtle test isolation bugs.
  4. Thin transform coverageprofiles.test.cjs checks profile shape but doesn't test the transformEntry functions that are the behaviorally meaningful part of this refactor.

Positive Highlights

  • ✅ Clean extraction into a single profile table — auditing per-engine differences is now much easier.
  • ✅ Factory correctly handles both transformEntry and transformServer forms without breaking existing callers.
  • setFailedOnError delegation to the factory is a nice isolation of the core.setFailed coupling.
  • ✅ Good test coverage in factory.test.cjs including the error-reporting path.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 58.6 AIC · ⌖ 10.8 AIC · ⊞ 7.8K
Comment /matt to run again

}
});
}
const { rewriteUrl } = require("./convert_gateway_config_shared.cjs");

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.

[/codebase-design] rewriteUrl is imported here but never referenced in this file after the refactor — dead import that misleads readers.

💡 Fix

Remove line 6:

const { rewriteUrl } = require("./convert_gateway_config_shared.cjs");

URL rewriting now happens inside profiles.cjs. The same dead import exists in convert_gateway_config_gemini.cjs.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Kept this import because rewriteUrl remains part of this entrypoint's pre-existing public module exports. Removing it would make module.exports.rewriteUrl undefined and break compatibility.

function getGeminiHostDomain() {
return process.env.MCP_GATEWAY_HOST_DOMAIN || "localhost";
}
const { rewriteUrl } = require("./convert_gateway_config_shared.cjs");

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.

[/codebase-design] Same dead import as in convert_gateway_config_copilot.cjsrewriteUrl is imported but never called here after the refactor.

💡 Fix

Remove line 6:

const { rewriteUrl } = require("./convert_gateway_config_shared.cjs");

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Kept this import because rewriteUrl remains part of this entrypoint's pre-existing public module exports. Removing it would make module.exports.rewriteUrl undefined and break compatibility.

outputPath: path.join(process.env.RUNNER_TEMP || "/tmp", "gh-aw/mcp-config/mcp-servers.json"),
transformEntry: transformClaudeEntry,
serialize: servers => JSON.stringify({ mcpServers: servers }, null, 2),
},

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.

[/codebase-design] core.info(...) is called inside the codex profile's getUrlPrefix function — this embeds a side effect (logging) deep in a data definition, making the profile hard to test without a real core shim.

💡 Suggested fix

Move the log call into the factory or into the codex entrypoint main(), not inside a data-tier function:

// In convert_gateway_config_factory.cjs or convert_gateway_config_codex.cjs
getUrlPrefix: ({ domain, port }) => {
  if (domain === "host.docker.internal") {
    // Log happens at the call site, not buried in the profile object
    return `(172.30.0.1/redacted)
  }
  return `(redacted)
},

Or accept core as a dependency parameter on the factory so the profile stays pure.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 1a9e742: Codex URL resolution is now pure in the profile; the shared factory emits the preserved resolution log from the profile's message provider. Added factory coverage for this behavior.

return toml;
},
},
claude: {

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.

[/codebase-design] outputPath for codex and claude is evaluated eagerly at module-load time (path.join(process.env.RUNNER_TEMP || "/tmp", ...)), but copilot uses preRunOutputPath for lazy resolution at run time. This asymmetry means importing profiles.cjs in a test will snapshot the value of RUNNER_TEMP at import time, potentially diverging from the value set later in the test.

💡 Suggested fix

Make outputPath for codex and claude also a thunk (or use preRunOutputPath) to match the copilot pattern:

codex: {
  ...
  preRunOutputPath: () => path.join(process.env.RUNNER_TEMP || "/tmp", "gh-aw/mcp-config/config.toml"),
  ...
},
claude: {
  ...
  preRunOutputPath: () => path.join(process.env.RUNNER_TEMP || "/tmp", "gh-aw/mcp-config/mcp-servers.json"),
  ...
},

This makes all profiles consistently lazy and avoids env-snapshot bugs in tests.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 1a9e742: Codex and Claude now resolve RUNNER_TEMP through preRunOutputPath at conversion time. Added coverage that changes RUNNER_TEMP after module import.

expect(gatewayConversionProfiles.claude).toMatchObject({ format: "Claude", engine: "Claude" });
expect(gatewayConversionProfiles.gemini).toMatchObject({ format: "Gemini", engine: "Gemini", contextOptions: { extraRequiredEnv: ["GITHUB_WORKSPACE"] } });
});
});

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.

[/tdd] The profiles test checks that profiles exist and have the right shape, but no test exercises the transformEntry / transformServer functions exported from profiles.cjs (e.g., that transformClaudeEntry sets type: "http" and deletes tools, or that transformGeminiEntry removes type). These are the behaviorally interesting parts of the refactor and the most likely place for regressions.

💡 Suggested additions
it("transformClaudeEntry sets type:http and removes tools", () => {
  const result = transformClaudeEntry({ url: "(host/redacted) tools: ["*"] }, "(host/redacted)
  expect(result.type).toBe("http");
  expect(result).not.toHaveProperty("tools");
});

it("transformGeminiEntry removes type field", () => {
  const result = transformGeminiEntry({ url: "(host/redacted) type: "http" }, "(host/redacted)
  expect(result).not.toHaveProperty("type");
});

it("transformCopilotEntry adds tools:['*'] when missing", () => {
  const result = transformCopilotEntry({ url: "(host/redacted) }, "(host/redacted)
  expect(result.tools).toEqual(["*"]);
});

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 1a9e742: added direct coverage for Copilot defaults, Claude HTTP/tool transformation, Gemini type removal, and URL rewriting.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the unresolved review feedback below, refresh the branch if needed, then run the pr-finisher skill and report back with the current validation results and blockers.

Run: https://github.com/github/gh-aw/actions/runs/32087856389

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 10 AIC · ⌖ 8.08 AIC · ⊞ 8.8K ·
Comment /souschef to run again

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please review the unresolved feedback below, refresh the branch if needed, then run the pr-finisher skill and report back with validation results and any remaining blockers.

Run: https://github.com/github/gh-aw/actions/runs/32089978540

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 9.41 AIC · ⌖ 8.04 AIC · ⊞ 8.8K ·
Comment /souschef to run again

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please review the unresolved feedback below, refresh the branch if needed, then run the pr-finisher skill and report back with validation results and any remaining blockers.

  • Unresolved r...

Branch is refreshed and already contains origin/main (db25fdf). All five feedback items are satisfied by 1a9e742 and already have substantive thread replies; this environment cannot resolve the remaining threads. Validation: converter CJS tests 10/10, make fmt, make lint, and make recompile passed. make test still fails only in pre-existing TestCopilotEngineInstallationWithCopilotSDKDriver assertions expecting the removed ripgrep install step. The latest CJS run (32090464058) is action_required before any job was created, so no failing job log exists. CI on this head still needs a maintainer re-trigger.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the unresolved review feedback below, refresh the branch if needed, then run the pr-finisher skill and report back with the current validation results and blockers.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.29 AIC · ⌖ 7.92 AIC · ⊞ 8.8K ·
Comment /souschef to run again

Copilot AI and others added 2 commits August 18, 2026 04:15
…e-remove-repeated-scaffolds

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the unresolved review feedback below, refresh the branch if needed, then run the pr-finisher skill and report back with the current validation results and blockers.

  • Unreso...

Refreshed with current main and committed regenerated workflow locks in e72e80f. The five listed threads remain substantively addressed by 1a9e742; no further converter change is needed. Validation passed: converter CJS tests 10/10, make fmt, make lint, make test-unit, make recompile, and make agent-report-progress. make test remains blocked by the pre-existing TestCopilotEngineInstallationWithCopilotSDKDriver expectations for the removed ripgrep install step. Latest CJS run 32097527268 is action_required before jobs start, so CI on this head requires a maintainer re-trigger. Thread resolution is unavailable in this environment.

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.

[duplicate-code] Duplicate Code: repeated gateway-config conversion scaffolds per engine

4 participants