fix(cli): bridge connects in a fresh terminal even when the app is down - #55
Merged
Conversation
Victauri's MCP server is embedded inside the Tauri app, so it only exists while the app runs. `victauri bridge` discovered the backend BEFORE answering the MCP `initialize` handshake (blocking ~30s under `--wait`), so the host aborted at its 30s connection ceiling — every fresh terminal opened before the app started reported: Failed to reconnect to victauri: MCP server "victauri" connection timed out after 30000ms Fix (all in crates/victauri-cli/src/bridge.rs; public API unchanged, semver-clean): - Answer `initialize`/`tools/list`/`ping`/`*list` LOCALLY so the server always shows connected with its full tool surface, app or no app. Only tool CALLS need a live backend; when down they return an actionable "start the app" error instead of hanging. - Serve a baked 35-tool fallback list (names+descriptions extracted from the plugin's #[tool] annotations -> tools_fallback.json) while the app is down. - Background availability poller emits notifications/tools/list_changed on the down->up transition, so tools go live automatically with no /mcp reconnect. - Make discovery cheap: batch liveness into ONE tasklist/ps call per scan (not one spawn per stale dir), filter dead-PID entries before any /health probe, and bound the probe connect to 600ms so a closed/filtered stale port can't stall a scan. Cold-start scan with ~25 stale dirs now <1s (was ~9s). - `victauri init` drops the now-vestigial `--wait` from generated .mcp.json (still accepted for back-compat); CLAUDE.md guidance updated. Verified end-to-end against the compiled binary: new e2e test proves instant handshake with no app, the fallback list, an actionable down-call error, then auto-emitted list_changed + live tools + a working call when a mock backend appears — no reconnect. Existing restart-recovery e2e still passes. Gate: fmt --all, clippy --workspace --all-targets -D warnings, build --workspace, test -p victauri-cli (46 unit + 2 e2e) all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KfH8iYXUYm5YruHescthzD
…liable Live-4DA verification exposed an intermittency I introduced: `health_ok` built a fresh reqwest client per call with a 1s total timeout, so the FIRST (cold) /health probe against a running server under load could exceed it — discovery then missed the live app on first contact and the bridge served the fallback tool list / errored the first tool call (a retry then worked). Fix: build ONE warm health client in a OnceLock and keep a tight CONNECT timeout (1200ms — still fast-fails a closed/filtered stale port) with a generous total timeout (3s, only relevant for a rare connected-but- unresponsive reused port). Verified against live 4DA: 5/5 fresh cold-connects now return the LIVE tool list (real schemas) + a working get_plugin_info call on first contact (442-1069ms); `victauri check` is green (379 commands). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KfH8iYXUYm5YruHescthzD
CI's Check & Lint upgraded to clippy 1.97.0, whose question_mark lint flags a
pre-existing manual `if let Some(i) = ... else { return None }` in
extract_fn_name. Rewrite as `let i = line.find("fn ")?;`. Verified with a
matching local toolchain: `cargo clippy --workspace --all-targets -D warnings`,
`cargo fmt --all --check`, and `cargo test -p victauri-cli` all green on 1.97.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KfH8iYXUYm5YruHescthzD
This was referenced Jul 13, 2026
runyourempire
added a commit
that referenced
this pull request
Jul 13, 2026
…58) victauri-cli-only, semver-clean within ^0.8 (plugin + public Rust API unchanged). Bundles: the bridge cold-start fix (#55 — connects in a fresh terminal even with the app down), pre-emptive internal red-team hardening (#56), external GPT audit remediation incl. a real token-leak fix + regression test, and round-2 verification follow-ups (#57). - scripts/bump-version.ps1 0.8.7 (workspace version, dep pins, action pin, CLAUDE.md refs, Cargo.lock) - CHANGELOG [Unreleased] -> [0.8.7] - 2026-07-13 - MIGRATION.md v0.8.6 -> v0.8.7 (bridge connects in a fresh terminal; --wait no-op; per-forward trusted re-resolve) - CLAUDE.md Current State -> v0.8.7 Gate green locally: fmt --all, clippy --workspace --all-targets -D warnings (1.97), build --workspace, test -p victauri-cli (46 unit + 3 e2e). NOT published (operator's crates.io gate). Claude-Session: https://claude.ai/code/session_01KfH8iYXUYm5YruHescthzD Co-authored-by: audit <audit@example.test> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Opening a fresh Claude Code terminal in a Victauri-consuming app (4DA) showed:
Root cause is architectural, not the app. Victauri's MCP server is embedded inside the Tauri process, so it only exists while the app runs.
victauri bridgediscovered the backend before answering the MCPinitializehandshake (worse under--wait, which blocked ~30s), so the host aborts at its 30s connection ceiling — meaning every fresh terminal opened before the app was started failed to connect, and the agent silently loses Victauri (falling back to worse tooling or flying blind).Fix (all in
crates/victauri-cli/src/bridge.rs; public API unchanged → semver-clean in^0.8)initialize/tools/list/ping/*listlocally, so the MCP server always shows connected with its full tool surface whether or not an app is running. Only tool calls need a live backend; when down they return an actionable "backend not reachable — start the app (npm run tauri dev)" error instead of hanging.tools/listserves all 35 tools (names + descriptions extracted from the plugin's#[tool]annotations →tools_fallback.json,include_str!-embedded).notifications/tools/list_changed(+resources/list_changed) on the down→up transition, so the client refreshes from the fallback to the live, version-accurate list automatically.tasklist/pscall per scan (not one spawn per stale dir), filter dead-PID entries before any/healthprobe, and bound the probe connect to 600ms so a closed/filtered stale port can't stall a scan. Cold-start scan with ~25 stale dirs now <1s (was ~9s, then a 20s hang mid-iteration — both fixed).victauri initdrops the now-vestigial--waitfrom generated.mcp.json(still accepted for back-compat); generatedCLAUDE.mdguidance updated to say the server connects even before the app is up.Verification (against the compiled binary)
bridge_cold_start_serves_handshake_then_goes_live_when_app_appears: instant handshake with no app → 35-tool fallback → actionable down-call error → auto-emittedlist_changedwhen a mock backend appears → live tool list + working tool call, no reconnect.victauri bridge, app down, 25 stale dirs):initializenear-instant, full sequence <1s (was 30 000ms timeout).Gate green:
cargo fmt --all --check,cargo clippy --workspace --all-targets -D warnings,cargo build --workspace,cargo test -p victauri-cli(46 unit + 2 e2e).🤖 Generated with Claude Code