Describe the bug
When running apm install <new-package> with --trust-transitive-mcp, all transitive MCP servers are reinstalled/reconfigured even if they are already configured from a previous install. The skip logic (check_servers_needing_installation) does not apply to self-defined (transitive) MCP servers — only to registry-based servers.
To Reproduce
- Have a project with existing APM + MCP dependencies already installed
- Run
apm install <new-package> --trust-transitive-mcp to add a new package
- Observe that all transitive MCP servers are reconfigured even though they were already installed
Expected behavior
- MCP servers that are already configured should be skipped with
✓ <name> (already configured) — the same behavior that exists for registry-based servers.
- Only new or changed MCP servers should be installed/reconfigured.
Root Cause (analysis)
The check_servers_needing_installation() method in registry/operations.py is only invoked for registry-based MCP deps. Self-defined (transitive) MCP servers follow a separate code path in _install_mcp_dependencies() that does not check whether the server is already configured before reinstalling it.
The registry path (~L2835 in cli.py) correctly calls:
servers_to_install = operations.check_servers_needing_installation(target_runtimes, valid_servers)
But the self-defined/transitive server path does not perform an equivalent check.
Environment (please complete the following information):
- OS: macOS
- Python Version: 3.12
- APM Version: latest (main branch)
Logs
apm install xxxxx/xxxxx/general/demo-playbook --trust-transitive-mcp
Validating 1 package(s)...
✓ xxxxx/xxxxx/ - accessible
Added xxxxx/xxxxx/ apm.yml
Updated apm.yml with 1 new package(s)
Installing dependencies from apm.yml...
Installing APM dependencies (11)...
Using apm.lock (10 locked dependencies)
✓ github.com/xxxxxx/xxxxx/ (cached)
└─ 3 prompts integrated → .github/prompts/
└─ 1 skill(s) integrated → .github/skills/
Generated apm.lock with 1 dependencies
Installed 0 APM dependencies
┌─ MCP Servers (3)
│ ⬇️ atlassian (self-defined, http)
│ └─ Configuring for Copilot, Vscode...
Installing atlassian...
✓ atlassian
│ ⬇️ zephyr (self-defined, http)
│ └─ Configuring for Copilot, Vscode...
Installing zephyr...
✓ zephyr
│ ⬇️ github (self-defined, http)
│ └─ Configuring for Copilot, Vscode...
Installing github...
✓ github
└─ Configured 3 servers
All 3 MCP servers were already configured from a prior apm install but were reinstalled anyway.
Additional context
This also affects the failure case: when apm install <bad-pkg> fails validation, the command still falls through and reinstalls all existing MCP servers (exits 0). Ideally, when the only requested package fails, the command should bail out or no-op instead of triggering a full MCP reinstall.
Describe the bug
When running
apm install <new-package>with--trust-transitive-mcp, all transitive MCP servers are reinstalled/reconfigured even if they are already configured from a previous install. The skip logic (check_servers_needing_installation) does not apply to self-defined (transitive) MCP servers — only to registry-based servers.To Reproduce
apm install <new-package> --trust-transitive-mcpto add a new packageExpected behavior
✓ <name> (already configured)— the same behavior that exists for registry-based servers.Root Cause (analysis)
The
check_servers_needing_installation()method inregistry/operations.pyis only invoked for registry-based MCP deps. Self-defined (transitive) MCP servers follow a separate code path in_install_mcp_dependencies()that does not check whether the server is already configured before reinstalling it.The registry path (~L2835 in
cli.py) correctly calls:But the self-defined/transitive server path does not perform an equivalent check.
Environment (please complete the following information):
Logs
All 3 MCP servers were already configured from a prior
apm installbut were reinstalled anyway.Additional context
This also affects the failure case: when
apm install <bad-pkg>fails validation, the command still falls through and reinstalls all existing MCP servers (exits 0). Ideally, when the only requested package fails, the command should bail out or no-op instead of triggering a full MCP reinstall.