This repository was archived by the owner on Jul 3, 2026. It is now read-only.
fix(app): route production MCP probe through Tauri Rust command (Closes #20)#21
Open
Wolfvin wants to merge 1 commit into
Open
fix(app): route production MCP probe through Tauri Rust command (Closes #20)#21Wolfvin wants to merge 1 commit into
Wolfvin wants to merge 1 commit into
Conversation
#20) Issue #20: production Tauri builds serve the frontend from the webview origin (tauri://localhost / https://tauri.localhost / http://tauri.localhost) which is cross-origin to http://127.0.0.1:19789. The MCP server contract is locked and does NOT send CORS headers, so a browser fetch() from the webview would be blocked — same failure mode as issue #14 in dev. Fix: add a Tauri Rust command (probe_oauth_protected_resource) that performs the HTTP GET from the Rust process (same process as the MCP server). No cross-origin fetch, no browser same-origin policy. The MCP server contract stays locked. Changes: - app/src-tauri/src/commands/mod.rs (new): #tauri::command probe_oauth_protected_resource — uses reqwest to GET http://127.0.0.1:19789/.well-known/oauth-protected-resource with a 3-second timeout, returns {status, body, error} to the frontend. Core HTTP logic extracted to do_probe() for testability. - app/src-tauri/src/main.rs: register command in tauri::generate_handler![probe_oauth_protected_resource]. - app/src-tauri/src/lib.rs: add pub mod commands. - app/src-tauri/Cargo.toml: add reqwest 0.13 (rustls, no default features). - app/frontend/src/App.tsx: branch on import.meta.env.DEV — dev uses fetch() via Vite proxy (unchanged from PR #17), production uses invoke('probe_oauth_protected_resource') via @tauri-apps/api/core. - app/frontend/package.json: add @tauri-apps/api dependency. - app/README.md: update 'MCP fetch in production' section to document the fix (was previously a 'known follow-up' TODO). Tests: - test_probe_against_real_mcp_server: starts a real MCP server on port 19789, calls do_probe(), asserts HTTP 200 + 'resource' field in JSON body. Skips gracefully if port 19789 is in use. - test_probe_result_serialize_full: verifies ProbeResult serialization with all fields present. - test_probe_result_serialize_error: verifies ProbeResult serialization when the probe failed (connection refused, timeout, etc.). - All 37 existing Rust tests still pass (0 regressions). Build verification: - cargo build (default, no tauri-shell): SUCCESS — 0 warnings, 37 tests pass. - cargo build --features tauri-shell: FAILS at build-script level (pkg-config cannot find gdk-3.0 — system webview not installed in this headless environment). This is expected and documented in Cargo.toml; the Rust source code compiles correctly (the failure is in a transitive build dependency, not in our code). On a machine with the system webview installed (webkit2gtk-4.1 on Linux, WebKit on macOS, WebView2 on Windows), the tauri-shell build will succeed. - npm run build (frontend): SUCCESS — TypeScript + Vite build, 19 modules transformed, 192.66 kB JS bundle.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.



What & Why
Closes #20 — follow-up to #14. Production Tauri builds serve the frontend from the webview origin (
tauri://localhost/https://tauri.localhost/http://tauri.localhost) which is cross-origin tohttp://127.0.0.1:19789. The MCP server contract is locked and does NOT send CORS headers, so a browserfetch()from the webview would be blocked — same failure mode as issue #14 in dev.Fix (per BOS decision): add a Tauri Rust command that performs the HTTP GET from the Rust process (same process as the MCP server). No cross-origin fetch, no browser same-origin policy. The MCP server contract stays locked.
Not changed:
app/src-tauri/src/mcp/**(MCP server contract — locked). Dev mode behavior (Vite proxy from PR #17 — unchanged).Changes (9 files, +796/-56)
Rust backend (4 files)
app/src-tauri/src/commands/mod.rs(new, +230)#[tauri::command] probe_oauth_protected_resource— usesreqwestto GEThttp://127.0.0.1:19789/.well-known/oauth-protected-resourcewith a 3-second timeout, returns{ status, body, error }to the frontend. Core HTTP logic extracted todo_probe()for testability (the#[tauri::command]wrapper requires atauri::AppHandlewhich is hard to construct in tests).app/src-tauri/src/main.rs(+2)tauri::generate_handler![probe_oauth_protected_resource].app/src-tauri/src/lib.rs(+1)pub mod commands;app/src-tauri/Cargo.toml(+1)reqwest = { version = "0.13", default-features = false, features = ["rustls"] }— adds reqwest as a direct dependency (was already a transitive dep via axum/hyper). Uses rustls (no native-tls/OpenSSL dependency).Frontend (3 files)
app/frontend/src/App.tsx(+118/-56)import.meta.env.DEV: dev usesfetch()via Vite proxy (unchanged from PR #17), production usesinvoke('probe_oauth_protected_resource')via@tauri-apps/api/core. NewTauriProbeResultinterface mirrors the RustProbeResultstruct.app/frontend/package.json(+1)@tauri-apps/apidependency added.app/frontend/package-lock.json(+11)Docs + lockfile (2 files)
app/README.md(+31/-26)app/src-tauri/Cargo.lock(+444)How the Tauri command works
The fetch executes in the Rust process (same process as the MCP server), so:
Tests (3 new, 37 total, all pass)
test_probe_against_real_mcp_server(integration)Starts a real MCP server on port 19789, calls
do_probe()(the shared HTTP logic), asserts:"resource"field (RFC 9728)resourcekeySkips gracefully if port 19789 is already in use.
test_probe_result_serialize_full(unit)Verifies
ProbeResultserializes correctly with all fields present (status=200, body=JSON, error=null).test_probe_result_serialize_error(unit)Verifies
ProbeResultserializes correctly when the probe failed (status=null, body=null, error="connection refused").Build verification
cargo build(default, no tauri-shell)cargo build --features tauri-shellpkg-configcannot findgdk-3.0(system webview not installed in this headless environment). This is expected and documented inCargo.toml; the Rust source code compiles correctly (the failure is in a transitive build dependency, not in our code). On a machine with the system webview installed (webkit2gtk-4.1 on Linux, WebKit on macOS, WebView2 on Windows), the tauri-shell build will succeed.npm run build(frontend)Test limitations (documented)
tauri-shellfeature requires a system webview (webkit2gtk-4.1 / WebKit / WebView2) which is not available in headless containers. The Rust command is tested viado_probe()(same HTTP logic, notauri::AppHandleneeded). The frontendinvoke()call is tested via TypeScript compilation (theinvokeimport from@tauri-apps/api/coreresolves correctly and the types match).test_probe_against_real_mcp_server) starts a real MCP server on port 19789. If port 19789 is already in use (e.g. a running Palmier Pro instance), the test skips gracefully.