APX mcp check Is the Fastest Way to Debug Shadowed MCPs
APC is the portable context layer. APX is the local runtime and tooling layer that makes APC useful every day. When an MCP setup feels wrong, the fastest fix is usually not to stare at the final list of servers. It is to inspect how APX merged the sources.
That is why apx mcp check matters. It shows the source files, the active entries after merge, and any conflicts. In other words, it answers the real question: which MCP won, and what got shadowed?
Why list is not enough
apx mcp list is useful, but it only shows the merged result. That is good for a quick inventory and bad for debugging drift. If the same MCP name exists in more than one scope, the final list hides the path that produced it.
A clean list can still hide a bad setup. For example:
- a shared MCP in
.apc/mcps.json - a runtime override in
~/.apx/projects/<id>/mcps.json - a machine-wide entry in
~/.apx/mcps.json
The name looks fine. The source may not be the one you expected.
The merge rule
APX is explicit about priority: runtime > shared > global. The runtime file wins when names collide, then the shared APC file, then the machine-wide global file. The tests cover that chain, and the CLI prints conflicts on purpose.
That means two things:
- Shadowing is normal.
- Shadowing should be visible.
If a server disappears or behaves differently than expected, do not guess. Ask APX which source won.
What mcp check shows
apx mcp check gives you three useful views at once:
- source files and whether each file exists
- active entries after merge
- conflicts, if a name appears more than once
That is the right level for debugging. It tells you whether APX is reading the repo file, the runtime file, or the global file. It also tells you whether an entry is APX-owned or coming from a foreign IDE config that APX only reads advisory.
A typical flow looks like this:
apx mcp check --project iacrmar
apx mcp list --scope runtime --project iacrmar
apx mcp list --scope shared --project iacrmar
Use check first. Use list second, when you already know where to look.
A concrete failure mode
Imagine you add github in shared scope because you want every clone of the repo to know the server exists. Later, you add another github entry in runtime scope because this machine needs a token.
That is not a bug. It is a layered override. But if you forget the runtime copy exists, you may edit the shared file and still see the runtime version win. The project looks unchanged, because APX is doing what the merge rule says.
apx mcp check makes that obvious. It will show the runtime entry as the winner and report the shared entry as the loser.
Ownership still matters
APX can inspect foreign MCP configs from other tools, but it will not rewrite them. The code is careful here: if an MCP comes from a foreign source, APX tells you to change it in that tool's config instead. That is a good boundary. APX should manage APX-owned scopes, not silently mutate somebody else's setup.
So the practical rule is simple:
- repo-shared MCPs belong in APC
- machine-specific MCPs belong in APX runtime
- machine-wide defaults belong in APX global
- foreign IDE configs stay in the IDE
Why this split helps APC too
APC stays portable because it only carries the shared part of the story. If a token or a local endpoint sneaks into the repo, the clone-safe contract breaks. APX protects that contract by keeping runtime state local and by making conflicts visible instead of hidden.
That is the deeper reason mcp check exists. It is not a status screen. It is a sanity check for the boundary between portable context and local execution.
Bottom line
When MCP behavior looks wrong, start with apx mcp check.
It shows the files, the winners, and the conflicts. That is usually enough to explain the issue in one pass, without guessing which layer won or which file got shadowed.
Top comments (1)
Shadowed MCPs are exactly the kind of local-runtime bug that wastes time because the final server list looks plausible. A check command is useful if it explains precedence: where each server came from, which one won, and which definition was ignored. That makes config debugging much less mystical.