Describe the bug
When installing APM packages with --global (-g), MCP server entries are never written to any runtime config file. The install command unconditionally sets should_install_mcp = False at user scope, assuming all MCP configs are workspace-scoped:
# install.py:743-749
# MCP servers are workspace-scoped (.vscode/mcp.json); skip at user scope
if scope is InstallScope.USER:
should_install_mcp = False
This assumption is incorrect. Multiple supported runtimes have global/user-scoped config paths:
| Runtime |
Global config path |
Documentation |
| Copilot CLI |
~/.copilot/mcp-config.json |
GitHub docs |
| Codex CLI |
~/.codex/config.toml |
Global by design |
| VS Code |
User profile mcp.json |
VS Code docs -- "Servers configured here are available across all your workspaces" |
The same guard also silences --trust-transitive-mcp at global scope -- transitive MCP collection (install.py:839) is gated behind should_install_mcp, so the flag becomes a silent no-op.
To Reproduce
- Run
apm install -g some-package-with-mcp
- Check
~/.copilot/mcp-config.json (or other global runtime config)
- No MCP servers are present
With --verbose, the log shows: "MCP servers skipped at user scope (workspace-scoped concept)"
Expected behavior
MCP servers from the installed package should be written to the global config path of each applicable runtime (e.g. ~/.copilot/mcp-config.json for Copilot CLI). --trust-transitive-mcp should also work at global scope.
Environment (please complete the following information):
- OS: All
- Python Version: 3.12
- APM Version: current
main
Logs
At --verbose level: "MCP servers skipped at user scope (workspace-scoped concept)"
Additional context
Root cause chain:
install.py:744-745 -- blanket should_install_mcp = False for InstallScope.USER
install.py:839 -- transitive MCP collection gated behind the same flag, making --trust-transitive-mcp -g a silent no-op
MCPIntegrator.install() (mcp_integrator.py:798-807) has no scope parameter -- no mechanism to tell the integrator which scope is active
- No per-adapter scope classification exists to distinguish workspace-only from global-capable adapters
Suggested fix direction:
- Add scope awareness to
MCPClientAdapter (e.g. supports_user_scope -> bool)
- Pass
scope through to MCPIntegrator.install()
- At user scope, install to global-capable runtimes; skip workspace-only adapters
- For VS Code, add support for the user profile
mcp.json path alongside the existing workspace path
Describe the bug
When installing APM packages with
--global(-g), MCP server entries are never written to any runtime config file. The install command unconditionally setsshould_install_mcp = Falseat user scope, assuming all MCP configs are workspace-scoped:This assumption is incorrect. Multiple supported runtimes have global/user-scoped config paths:
~/.copilot/mcp-config.json~/.codex/config.tomlmcp.jsonThe same guard also silences
--trust-transitive-mcpat global scope -- transitive MCP collection (install.py:839) is gated behindshould_install_mcp, so the flag becomes a silent no-op.To Reproduce
apm install -g some-package-with-mcp~/.copilot/mcp-config.json(or other global runtime config)With
--verbose, the log shows:"MCP servers skipped at user scope (workspace-scoped concept)"Expected behavior
MCP servers from the installed package should be written to the global config path of each applicable runtime (e.g.
~/.copilot/mcp-config.jsonfor Copilot CLI).--trust-transitive-mcpshould also work at global scope.Environment (please complete the following information):
mainLogs
At
--verboselevel:"MCP servers skipped at user scope (workspace-scoped concept)"Additional context
Root cause chain:
install.py:744-745-- blanketshould_install_mcp = FalseforInstallScope.USERinstall.py:839-- transitive MCP collection gated behind the same flag, making--trust-transitive-mcp -ga silent no-opMCPIntegrator.install()(mcp_integrator.py:798-807) has noscopeparameter -- no mechanism to tell the integrator which scope is activeSuggested fix direction:
MCPClientAdapter(e.g.supports_user_scope -> bool)scopethrough toMCPIntegrator.install()mcp.jsonpath alongside the existing workspace path