Description
In `--bare` mode, `agent_setup::build_tool_setup` correctly skips `connect_all()` for non-OAuth MCP servers. However, the deferred OAuth spawn guard in `src/runner.rs` is not protected by an `exec_mode.bare` check. If the config contains an OAuth-transport MCP server (e.g. Todoist), a background task is spawned that calls `connect_oauth_deferred()` and establishes a live MCP connection — even in bare mode.
This is a regression from the fix in #3298 that added the bare-mode guard for `connect_all()` but did not cover the OAuth deferred path.
Reproduction Steps
- Configure an OAuth MCP server in your config (e.g. Todoist with `[mcp.servers.oauth]`).
- Run: `RUST_LOG=info ./target/debug/zeph --config .local/config/testing.toml --bare 2>&1 | grep -E 'mcp|MCP'`
- Observe `mcp.connect_url{server_id=todoist}` log line appearing after `agent shutdown complete`.
Expected Behavior
No MCP connections (including OAuth-based) should be established in `--bare` mode.
Actual Behavior
INFO zeph_core::agent: agent shutdown complete
INFO mcp.connect_url{server_id=todoist}: rmcp::service: Service initialized as client ...
The OAuth deferred connection fires ~8ms after agent shutdown, confirming the tokio task was spawned but the agent had already exited.
Root Cause
In `src/runner.rs`:
// Spawn deferred OAuth connections now that the UI channel is ready and can
// display the authorization URL.
if tool_setup.mcp_manager.has_oauth_servers() { // ← no exec_mode.bare guard
let mgr = std::sync::Arc::clone(&tool_setup.mcp_manager);
tokio::spawn(async move {
mgr.connect_oauth_deferred().await;
});
}
The guard should be `!exec_mode.bare && tool_setup.mcp_manager.has_oauth_servers()`.
Environment
Logs / Evidence
Session CI-600 live test. Log excerpt:
2026-04-24T19:15:55.369534Z INFO zeph_core::agent: agent shutdown complete
2026-04-24T19:15:55.377358Z INFO mcp.connect_url{server_id=todoist}: rmcp::service: Service initialized as client peer_info=Some(InitializeResult { ... "todoist-mcp-server" ... })
Description
In `--bare` mode, `agent_setup::build_tool_setup` correctly skips `connect_all()` for non-OAuth MCP servers. However, the deferred OAuth spawn guard in `src/runner.rs` is not protected by an `exec_mode.bare` check. If the config contains an OAuth-transport MCP server (e.g. Todoist), a background task is spawned that calls `connect_oauth_deferred()` and establishes a live MCP connection — even in bare mode.
This is a regression from the fix in #3298 that added the bare-mode guard for `connect_all()` but did not cover the OAuth deferred path.
Reproduction Steps
Expected Behavior
No MCP connections (including OAuth-based) should be established in `--bare` mode.
Actual Behavior
The OAuth deferred connection fires ~8ms after agent shutdown, confirming the tokio task was spawned but the agent had already exited.
Root Cause
In `src/runner.rs`:
The guard should be `!exec_mode.bare && tool_setup.mcp_manager.has_oauth_servers()`.
Environment
Logs / Evidence
Session CI-600 live test. Log excerpt: