Skip to content

[FEATURE] Support local MCP config for Copilot CLI#2048

Open
Skolim007 wants to merge 7 commits into
microsoft:mainfrom
Skolim007:feature/copilot-local-mcp-config
Open

[FEATURE] Support local MCP config for Copilot CLI#2048
Skolim007 wants to merge 7 commits into
microsoft:mainfrom
Skolim007:feature/copilot-local-mcp-config

Conversation

@Skolim007

@Skolim007 Skolim007 commented Jul 6, 2026

Copy link
Copy Markdown

Description

This PR enables workspace-level MCP configuration for the GitHub Copilot CLI integration, bringing it into parity with other harnesses like claude and codex.
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:

  1. Project-local .mcp.json
  2. Project-local .github/mcp.json
  3. User-global ~/.copilot/mcp-config.json

The Problem

Previously (as discussed in #2015), the adapter successfully created a project-local config, but the APM CLI's CopilotRuntime read-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 CopilotRuntime to:

  1. First check the current working directory for .mcp.json.
  2. Then check the current working directory for .github/mcp.json.
  3. Finally, fall back to the global ~/.copilot/mcp-config.json.
  4. When reading the JSON file, correctly fall back to the "mcpServers" key if "servers" is not present.

The -g / --global flag 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 the apm-spec-waiver trailer to account for this change.

Fixes #2047

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Maintenance / refactor

Testing

  • Tested locally
  • All existing tests pass
  • Added tests for new functionality (if applicable)

Spec conformance (OpenAPM v0.1)

If this PR changes behaviour that an OpenAPM v0.1 req-XXX covers,
confirm the three-step ritual (see CONTRIBUTING.md "Adding or
changing a normative requirement"):

  • Spec edit: docs/src/content/docs/specs/openapm-v0.1.md updated
    (new/changed <a id="req-XXX"></a> anchor + prose + Appendix C
    row).
  • Manifest edit: docs/src/content/docs/specs/manifest.json updated.
  • Test edit: tests/fixtures/spec-conformance/ updated.
  • CONFORMANCE.{md,json} regenerated via make spec-conformance.
  • N/A -- this PR does not change OpenAPM-observable behaviour.

Skolim007 added 5 commits July 4, 2026 11:28
…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
Copilot AI review requested due to automatic review settings July 6, 2026 08:26

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

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.json before 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 thread src/apm_cli/runtime/copilot_runtime.py Outdated
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)
Comment thread tests/integration/test_integration_runtime_coverage.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@Skolim007

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Support workspace-level (.mcp.json) and global (-g) MCP configurations for Copilot CLI

2 participants