mcp: a run says why a server's tools were withheld, instead of silently lacking them
A profile can declare a BYOK-gated server the user has no personal key for. The
manager refuses such a call and build_tool_list drops the server, so the tool
list stays honest — but the system prompt kept naming the server with no
explanation at all. The model knew it existed, held none of its tools, and had
nothing to tell the user, who concluded the assistant simply could not do the
task.

The reason was never stored: it is the complement of what visible_servers kept,
so _apply_mcp_scope derives it from that same value (byok_servers() - allowed)
rather than reading the key store a second time and risking a disagreement with
the first read. It rides in current_keyless_mcp_servers, next to the scope
variable, and _mcp_context_msg names each withheld server where it lists it,
followed by the reason and a pointer at Settings -> MCP keys.

Both ContextVar tokens are returned and reset together; without that the two
existing reset sites leak or raise. The variable defaults to empty, so a run
that never set it (a peer run out of a fresh task) claims nothing.

mcp_status said "without one this server runs on the shared default", which is
false for an ordinary account — the shared credential is admin-only.
1 parent 9eaa76b commit 9a720dc83611ccdcb0e55b238c14c7143327aa2a
@Eugene Sukhodolskiy Eugene Sukhodolskiy authored 4 hours ago
Showing 7 changed files
View
docs/mcp.md
View
navi/core/agent.py
View
navi/core/context_builder.py
View
navi/tools/_internal/base.py
View
navi/tools/mcp_status.py
View
tests/unit/core/test_agent.py
View
tests/unit/core/test_context_builder.py