[FEATURE] Support local MCP config for Copilot CLI#2048
Open
Skolim007 wants to merge 7 commits into
Open
Conversation
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
…very This updates the read-path in CopilotRuntime to mirror the write-path in CopilotClientAdapter, supporting .mcp.json and .github/mcp.json before falling back to the global ~/.copilot/mcp-config.json. apm-spec-waiver: Fixing PR microsoft#2015 runtime/install-path mismatch
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the Copilot CLI MCP integration to support workspace-scoped configuration discovery and installs, matching Copilot CLI’s config loading priority while retaining an explicit user-scope (-g/--global) path.
Changes:
- Update Copilot runtime MCP config discovery to prefer workspace
.mcp.json/.github/mcp.jsonbefore falling back to~/.copilot/mcp-config.json. - Update Copilot client adapter + stale-cleanup logic to route config writes/cleanup by scope (project vs user).
- Expand unit/integration tests and docs to cover the new scope behavior and config key support.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_copilot_runtime.py | Updates runtime-path tests and adds coverage for mcpServers key parsing. |
| tests/unit/test_copilot_adapter.py | Adds scope-routing tests for Copilot adapter config paths and read/write behavior. |
| tests/unit/test_copilot_adapter_phase3.py | Updates config-path expectations for project vs user scope. |
| tests/unit/test_copilot_adapter_compatibility.py | Mirrors the phase3 config-path scope updates for compatibility coverage. |
| tests/unit/integration/test_mcp_integrator.py | Updates stale-cleanup tests to validate project/user scope behavior for Copilot. |
| tests/integration/test_mcp_env_var_copilot_e2e.py | Adjusts E2E expectations to project .mcp.json as the default install output. |
| tests/integration/test_integration_runtime_coverage.py | Tweaks coverage tests for portability/OS behavior and subprocess execution. |
| src/apm_cli/runtime/copilot_runtime.py | Implements workspace-first MCP config path resolution and supports mcpServers + servers keys. |
| src/apm_cli/integration/mcp_integrator.py | Updates stale MCP cleanup to resolve Copilot config path based on scope. |
| src/apm_cli/adapters/client/copilot.py | Changes Copilot adapter config path routing (project .mcp.json vs user ~/.copilot/mcp-config.json). |
| docs/src/content/docs/producer/author-primitives/mcp-as-primitive.md | Updates harness mapping narrative to include Copilot CLI project .mcp.json. |
| docs/src/content/docs/consumer/install-mcp-servers.md | Updates harness table + adds migration guidance for servers -> mcpServers. |
| CHANGELOG.md | Adds an Unreleased note describing the new Copilot scope behavior. |
Comment on lines
168
to
176
| cwd_mcp = Path.cwd() / ".mcp.json" | ||
| if cwd_mcp.exists(): | ||
| return cwd_mcp | ||
|
|
||
| cwd_github_mcp = Path.cwd() / ".github" / "mcp.json" | ||
| if cwd_github_mcp.exists(): | ||
| return cwd_github_mcp | ||
|
|
||
| return Path.home() / ".copilot" / "mcp-config.json" |
Comment on lines
74
to
+85
| runtime = CopilotRuntime() | ||
| config_path = runtime.get_mcp_config_path() | ||
|
|
||
| assert config_path.as_posix().endswith(".copilot/mcp-config.json") | ||
|
|
||
| # Setup mock directories | ||
| mock_cwd = tmp_path / "workspace" | ||
| mock_cwd.mkdir() | ||
| mock_home = tmp_path / "home" | ||
| mock_home.mkdir() | ||
| mock_copilot = mock_home / ".copilot" | ||
| mock_copilot.mkdir() | ||
|
|
||
| with patch("pathlib.Path.cwd", return_value=mock_cwd), patch("pathlib.Path.home", return_value=mock_home): | ||
| # 1. Global fallback (no workspace config) |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Author
|
@microsoft-github-policy-service agree |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR enables workspace-level MCP configuration for the GitHub Copilot CLI integration, bringing it into parity with other harnesses like
claudeandcodex.I've created PR before trying to adress this problem, though it was rejected I'd like to try again. It seems it is mostly lack of clarity in official Copilot docs, that do not describe this behaiour in main configuration documentation for MCP (https://docs.github.com/en/copilot/how-tos/copilot-cli/use-copilot-cli/overview#add-an-mcp-server), this is only described on another subpage (https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-command-reference#mcp-server-loading-priority).
Related feature request: #2047
Still hope to make a contribution, rather than attempt some workarounds locally.
Background
In the GitHub Copilot CLI, MCP configuration is loaded with the following priority, as per the official documentation:
.mcp.json.github/mcp.json~/.copilot/mcp-config.jsonThe Problem
Previously (as discussed in #2015), the adapter successfully created a project-local config, but the APM CLI's
CopilotRuntimeread-path remained hardcoded to only look at the global~/.copilot/mcp-config.json. This mismatch caused the runtime to fail discovering locally installed tools during execution. Furthermore, when reading.mcp.json, the schema usually places servers inside the"mcpServers"key instead of the older"servers"key.The Solution & Changes Made
To fully support Copilot's intended configuration loading priority and fix the runtime-read path mismatch, this PR updates
CopilotRuntimeto:.mcp.json..github/mcp.json.~/.copilot/mcp-config.json."mcpServers"key if"servers"is not present.The
-g/--globalflag is now correctly supported for explicit user-scope installations.Note on Critical Paths: The changes involve
src/apm_cli/runtime/which is a critical path. The commits include theapm-spec-waivertrailer to account for this change.Fixes #2047
Type of change
Testing
Spec conformance (OpenAPM v0.1)
If this PR changes behaviour that an OpenAPM v0.1
req-XXXcovers,confirm the three-step ritual (see CONTRIBUTING.md "Adding or
changing a normative requirement"):
docs/src/content/docs/specs/openapm-v0.1.mdupdated(new/changed
<a id="req-XXX"></a>anchor + prose + Appendix Crow).
docs/src/content/docs/specs/manifest.jsonupdated.tests/fixtures/spec-conformance/updated.make spec-conformance.