Skip to content

Add tauri-mcp-client tool: Tauri app + FastMCP sidecar + HTML UI - #1

Closed
AM1010101 wants to merge 11 commits into
masterfrom
claude/tauri-fastmcp-tool-qjgc6w
Closed

Add tauri-mcp-client tool: Tauri app + FastMCP sidecar + HTML UI#1
AM1010101 wants to merge 11 commits into
masterfrom
claude/tauri-fastmcp-tool-qjgc6w

Conversation

@AM1010101

@AM1010101 AM1010101 commented Jul 21, 2026

Copy link
Copy Markdown
Owner

A desktop scaffold that drives a FastMCP process to call MCP servers.
The Python sidecar plays both MCP roles: a local FastMCP "hub" server
with its own tools, plus a config-driven fastmcp.Client that proxies to
external MCP servers. A FastAPI localhost bridge exposes it to a simple
HTML frontend, and the Tauri (v2) Rust shell spawns the sidecar on start.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu

Summary by CodeRabbit

  • New Features

    • Added an MCP dashboard experience with selectable dashboards and configurable panels.
    • Added responsive line and bar charts with tooltips, hover states, and light/dark themes.
    • Added support for configuring MCP servers, discovering tools, running scripts, and creating dashboards.
    • Added example dashboards for tool counts, revenue trends, and sales summaries.
    • Added desktop packaging and development launchers for Tauri.
  • Documentation

    • Added setup, dashboard creation, script authoring, MCP inspection, security, and deployment guidance.

claude added 8 commits July 21, 2026 16:42
A desktop scaffold that drives a FastMCP process to call MCP servers.
The Python sidecar plays both MCP roles: a local FastMCP "hub" server
with its own tools, plus a config-driven fastmcp.Client that proxies to
external MCP servers. A FastAPI localhost bridge exposes it to a simple
HTML frontend, and the Tauri (v2) Rust shell spawns the sidecar on start.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
- Add sidecar.spec: freeze the FastMCP/FastAPI bridge into one mcp-bridge
  binary (collects fastmcp/uvicorn trees, bundles example config; excludes
  mcp.cli which sys.exits at import without its optional extras).
- Add scripts/build-sidecar.sh: build in a throwaway venv and stage the
  binary as src-tauri/binaries/mcp-bridge-<target-triple> for Tauri.
- tauri.conf.json: declare bundle.externalBin so Tauri copies the sidecar
  next to the app executable.
- main.rs: prefer the bundled mcp-bridge binary at runtime, fall back to
  python server.py in dev.
- server.py: resolve mcp_config.json across dev and frozen layouts
  (MCP_CONFIG env, cwd, next-to-exe, bundled example).
- mcp_config.example.json: wire to the MCP "everything" demo server.
- .gitignore + README updated for the build artifacts and flow.

Verified: frozen binary runs under `env -i` (no Python) and serves the
hub, config listing, and tool calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
Introduces src-scripts/, a Node/TS runtime that is both the MCP client
(official @modelcontextprotocol/sdk) and the "Script" layer from the
dashboarding design. Scripts authored in TypeScript compose MCP tool
calls and return chart-ready JSON; the frontend calls named scripts, the
sanctioned egress path from the (future) sandbox.

- src/mcp.ts: config-driven MCP client manager (stdio + HTTP/SSE),
  one cached client per server, JSON-friendly results.
- src/scripts.ts: script context + loader; scripts re-imported per run
  so Builder-agent edits take effect without a restart.
- src/bridge.ts: localhost HTTP bridge (/health, /servers,
  /servers/:name/tools, /scripts, /scripts/:name/run).
- scripts/demo_timeseries.ts (pure, always runnable) and
  scripts/everything_sum.ts (calls the everything server's get-sum).
- dev.sh, tsconfig, README; single-local-user auth model.

Verified: typecheck passes; pure script and MCP-backed script both run
end to end (get-sum returned "The sum of 19 and 23 is 42.").

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
Adds src-web/, a Vite/React app that renders dashboards by running scripts
through the Script-layer bridge -- the frontend never calls MCP directly.

- Declarative dashboard JSON (panels: script + params + chart spec);
  <Panel> runs the script via callScript() and renders the chart.
- Hand-rolled SVG line/bar charts honoring the dataviz mark specs:
  single-series blue from the validated reference palette, 2px lines with
  soft area, rounded bar data-ends, recessive grid, hover crosshair/tooltip,
  light + dark themes via CSS tokens.
- bridge.ts client; theme.css tokens; example sales.json dashboard.
- Tauri config points at src-web (dev via Vite, build via vite build);
  main.rs gains MCP_SIDECAR_DISABLED so the dashboard dev flow can own the
  bridge without a port clash.
- dev-dashboard.sh runs bridge + Vite (+ optional Tauri); READMEs + roadmap.

Verified live: bridge + Vite running, React panels rendered demo_timeseries
end to end as line + bar in both light and dark (Playwright screenshots).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
Three skills teach Claude to author the dashboard artifacts:
- inspect-mcps: discover configured servers + tools (config + bridge).
- write-script: author a TS script returning chart-ready rows; verify it
  against the running bridge.
- write-dashboard: author dashboard JSON (panels: script + chart spec).

Enable the loop and prove it:
- src-scripts: add ctx.listTools(server) so scripts can enumerate a
  server's tools.
- scripts/mcp_tool_counts.ts (authored per write-script): tool count per
  configured MCP server from live data.
- dashboards/mcp_overview.json (authored per write-dashboard) renders it.
- App.tsx: dashboard picker; theme.css: picker styling.

Verified live: mcp_tool_counts returned real MCP data (everything: 13
tools); the MCP Overview dashboard rendered it as a bar chart alongside the
demo line, light + dark (screenshots).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
Confine the agent-generated frontend so its only egress is the bridge, and
the bridge's only egress is configured MCP servers.

- Webview CSP (tauri.conf.json): connect-src limited to the loopback bridge;
  script-src 'self' (Vite build emits only external self-hosted modules);
  object-src 'none'; frame-ancestors 'none'.
- Bridge guards (bridge.ts): DNS-rebinding guard (reject non-loopback Host
  -> 403); Origin guard (only loopback/tauri origins, reflected not '*');
  keeps loopback bind and fixed script/server surface.
- SECURITY.md documents the three enforcement layers and trust boundaries.

Verified: spoofed Host -> 403, evil Origin -> 403, loopback + localhost
origin allowed; scripts still run through the hardened bridge; built HTML is
CSP-safe (no inline scripts).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
Freezes the TypeScript Script bridge into one `mcp-bridge` executable that
embeds the Bun runtime and runs with nothing else installed.

- scripts/build-bridge.sh: `bun build --compile` the bridge; precompile
  authored scripts to .mjs; stage binary + scripts/ + example config into
  src-tauri/binaries/. Cross-compiles via BUN_TARGET.
- src-scripts: resolve scripts dir and mcp_config across dev and packaged
  layouts ($MCP_SCRIPTS_DIR / next-to-executable), since a packaged binary
  can't use the tsx loader — scripts load as external .mjs beside the binary.
- tauri.conf.json: bundle scripts/ + config as resources; main.rs points the
  sidecar at the resource dir via MCP_SCRIPTS_DIR.
- Drop the Node-SEA/postject approach (this Node build's ELF notes break
  postject); Bun compiles cleanly and cross-compiles. esbuild kept for
  compiling scripts; postject removed.

Verified: the compiled binary runs under `env -i` (no runtime installed),
lists its scripts, and completes real MCP calls that spawn a child stdio
server (everything get-sum -> 42; tool counts -> 13).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
Dashboards are now served by the bridge and loaded by the frontend at
runtime, so a new dashboard is just a JSON file -- no App.tsx registry edit,
no Vite rebuild.

- src-scripts/src/dashboards.ts + bridge routes GET /dashboards and
  GET /dashboards/:name; dashboards resolved across dev/packaged layouts
  ($MCP_DASHBOARDS_DIR / next-to-exe / ../dashboards).
- Move dashboard JSON from src-web/src/dashboards/ to src-scripts/dashboards/
  (authored content sits with scripts + config).
- App.tsx: fetch the dashboard list + selected definition from the bridge;
  drop the compile-time import map. Picker is populated from the bridge.
- Packaging + Tauri: build-bridge.sh stages dashboards/; tauri.conf bundles
  them as resources; main.rs sets MCP_DASHBOARDS_DIR.
- write-dashboard skill + READMEs updated (no wire-up, no rebuild).

Verified live: picker populated from the bridge; switching dashboards works;
dropping a new dashboards/ops.json while the app ran made it appear in the
picker and render on reload with no rebuild (screenshots).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011c8J7RdTEPqqi1Q6kdKKLu
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a Tauri MCP dashboard application with Python and TypeScript bridge implementations, configurable MCP servers, dashboard scripts and JSON definitions, a React/Vite frontend with interactive charts, desktop sidecar management, build scripts, security documentation, and authoring workflows.

Changes

MCP Dashboard Client

Layer / File(s) Summary
Python bridge and legacy client
tools/tauri-mcp-client/src-python/*, tools/tauri-mcp-client/src/*
Adds FastAPI/FastMCP endpoints for health, server discovery, tool listing, and tool calls, plus a legacy static frontend and PyInstaller sidecar packaging.
TypeScript MCP and script runtime
tools/tauri-mcp-client/src-scripts/src/*, tools/tauri-mcp-client/src-scripts/scripts/*
Adds MCP transport management, dynamic script loading, script execution, loopback HTTP routes, example scripts, and bridge build tooling.
Dashboard definitions and authoring workflow
tools/tauri-mcp-client/src-scripts/dashboards/*, tools/tauri-mcp-client/skills/*
Adds dashboard discovery and example definitions, with documented contracts for authoring scripts and chart panels.
React dashboard frontend
tools/tauri-mcp-client/src-web/src/*, tools/tauri-mcp-client/src-web/*
Adds dashboard selection and loading, script-backed panels, responsive SVG line and bar charts, tooltips, scaling helpers, sandboxed rendering, and theme styling.
Tauri integration and build orchestration
tools/tauri-mcp-client/src-tauri/*, tools/tauri-mcp-client/*.sh, tools/tauri-mcp-client/scripts/*
Adds the Tauri shell, sidecar lifecycle and resource wiring, desktop configuration, development launchers, and compiled bridge/sidecar staging.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard as React Dashboard
  participant Bridge as TypeScript Script Bridge
  participant Script as Dashboard Script
  participant MCP as Configured MCP Server
  Dashboard->>Bridge: GET /dashboards
  Bridge-->>Dashboard: Dashboard summaries
  Dashboard->>Bridge: POST /scripts/{name}/run
  Bridge->>Script: run(ctx, params)
  Script->>MCP: listTools or callTool
  MCP-->>Script: Tool result
  Script-->>Bridge: Chart-ready rows
  Bridge-->>Dashboard: Script result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.70% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the new tauri-mcp-client tool and its core Tauri, FastMCP sidecar, and HTML UI components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/tauri-fastmcp-tool-qjgc6w

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (9)
tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts-13-22 (1)

13-22: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate numeric script parameters before using them. Number() accepts invalid input as NaN or infinity, producing invalid chart data or forwarding unusable arguments to MCP tools.

  • tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts#L13-L22: fall back or reject unless seed is finite before calculating revenue.
  • tools/tauri-mcp-client/src-scripts/scripts/everything_sum.ts#L13-L17: validate a and b as finite numbers before calling get-sum.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts` around lines
13 - 22, Validate the numeric parameters before use: in
tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts lines 13-22,
ensure the seed used by run is finite, falling back or rejecting invalid values
before revenue calculation; in
tools/tauri-mcp-client/src-scripts/scripts/everything_sum.ts lines 13-17, ensure
both a and b are finite before invoking get-sum.
tools/tauri-mcp-client/src/styles.css-10-10 (1)

10-10: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Resolve the reported Stylelint errors.

Add the required declaration spacing and replace deprecated word-break: break-word with overflow-wrap: anywhere (and normal word breaking).

Also applies to: 118-118

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src/styles.css` at line 10, Update the CSS
declarations in styles.css to satisfy Stylelint: add the required spacing around
declarations, and replace deprecated word-break: break-word occurrences with
overflow-wrap: anywhere plus normal word breaking. Apply the same changes to the
additional reported location.

Source: Linters/SAST tools

tools/tauri-mcp-client/src-web/src/charts/BarChart.tsx-35-42 (1)

35-42: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Handle empty datasets before computing scales.

data: [] makes yMax -Infinity and band infinite, yielding invalid SVG output. Render a no-data state before calculating ticks and bar geometry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/src/charts/BarChart.tsx` around lines 35 - 42,
Handle an empty data array at the start of the BarChart rendering logic before
yMax, niceTicks, yScale, band, or bar geometry are computed. Return the
component’s no-data state for data.length === 0, while preserving the existing
scale and bar rendering path for non-empty datasets.
tools/tauri-mcp-client/src/app.js-47-74 (1)

47-74: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Discard stale tool-list responses.

Selecting server A and then B before A’s request resolves can render A’s tools while state.server remains B, causing calls to target the wrong server. Abort the prior request or verify a selection token after await.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src/app.js` around lines 47 - 74, Update selectServer
so each tool-list request is associated with the current server selection and
stale responses are discarded. After awaiting api, verify the selection still
matches the request (or use an abort mechanism) before mutating the tools list,
including success and error rendering; preserve the existing loading and
current-server behavior.
tools/tauri-mcp-client/SECURITY.md-3-7 (1)

3-7: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Correct the script-egress claim.

This says scripts can access the outside world only through configured MCP servers, but Lines 55-58 correctly state that scripts run with normal Node process privileges. State that the bridge confines the frontend only; trusted scripts can still use filesystem, process, and network APIs directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/SECURITY.md` around lines 3 - 7, Update the security
statement in SECURITY.md to limit the bridge-enforcement claim to the dashboard
frontend only. Clarify that trusted scripts run with normal Node process
privileges and may directly access filesystem, process, and network APIs, while
retaining the configured MCP-server restriction only for frontend access through
the Script bridge.
tools/tauri-mcp-client/SECURITY.md-13-18 (1)

13-18: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language hint to the CSP block.

Use ```text so the documentation passes the reported Markdown fenced-code-language check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/SECURITY.md` around lines 13 - 18, Update the CSP
fenced code block in SECURITY.md to specify the text language by changing its
opening fence to ```text, while leaving the CSP directives unchanged.

Source: Linters/SAST tools

tools/tauri-mcp-client/src-web/README.md-6-9 (1)

6-9: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language to the fenced diagram block.

Use text (or another suitable language) after the opening fence so markdownlint passes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/README.md` around lines 6 - 9, Update the
fenced diagram block in the README by adding a suitable language identifier,
preferably text, to its opening fence while preserving the diagram content
unchanged.

Source: Linters/SAST tools

tools/tauri-mcp-client/skills/write-dashboard/SKILL.md-3-3 (1)

3-3: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Correct the dashboard output path.

The description says to write into src-web/src/dashboards/, but the bridge discovers src-scripts/dashboards/. Following this instruction creates dashboards that are not listed at runtime.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/skills/write-dashboard/SKILL.md` at line 3, Update the
SKILL.md description to direct dashboard JSON files into src-scripts/dashboards/
instead of src-web/src/dashboards/, while preserving the existing guidance to
verify that the dashboard renders.
tools/tauri-mcp-client/src-web/src/charts/LineChart.tsx-41-45 (1)

41-45: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the hover coordinate calculation.

currentTarget is the overlay rect whose left edge is already at M.left, so subtracting M.left again shifts the selected point left. Calculate the index from px / iw.

Proposed fix
-    const i = Math.round(((px - M.left) / (iw || 1)) * (data.length - 1));
+    const i = Math.round((px / (iw || 1)) * (data.length - 1));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/src/charts/LineChart.tsx` around lines 41 -
45, Update the hover index calculation in onMove to derive the normalized
position from px / (iw || 1), removing the extra M.left subtraction while
preserving the existing rounding and clamping behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/tauri-mcp-client/README.md`:
- Around line 178-179: Update the Python bridge CORS configuration in server.py
to replace the wildcard origin, methods, and headers with the explicit
loopback/Tauri origin policy used by the TypeScript bridge. Preserve only the
required local origins and ensure credentialed requests remain restricted to
that allowlist.
- Around line 151-166: Update the documented Tauri packaging flow to avoid
staging the legacy Python bridge as mcp-bridge, since the packaged dashboard
requires /scripts and /dashboards. Use distinct sidecar names, or explicitly
stage the compiled TypeScript dashboard bridge, and align the references in the
build commands, tauri.conf.json, and main.rs runtime selection.

In `@tools/tauri-mcp-client/scripts/build-bridge.sh`:
- Around line 74-78: Use distinct staged binary names for the bridge
implementations so build-bridge.sh and build-sidecar.sh cannot overwrite each
other; update tools/tauri-mcp-client/scripts/build-bridge.sh and
tools/tauri-mcp-client/scripts/build-sidecar.sh accordingly. Align
tools/tauri-mcp-client/src-tauri/src/main.rs, including its mcp-bridge launch
configuration, with the selected staged name, and ensure only the intended
implementation is packaged and launched.
- Around line 30-50: Update the target-resolution logic before the `case
"$TRIPLE"` mapping so explicit `TRIPLE` and `BUN_TARGET` values are honored and
mutually consistent. Derive the Rust triple from `BUN_TARGET` when only the
bundle target is provided, preserve native detection when neither is set, and
fail clearly when the supplied values mismatch; ensure the staged bridge
filename uses the resolved intended triple.

In `@tools/tauri-mcp-client/src-python/server.py`:
- Around line 161-167: Update the CORSMiddleware configuration in the FastAPI
app to replace allow_origins=["*"] with an explicit allowlist of trusted
Tauri/Vite application origins. Preserve the existing methods and headers
settings, and add a per-launch authentication token for MCP endpoints if
required to exclude non-browser local clients.

In `@tools/tauri-mcp-client/src-scripts/mcp_config.example.json`:
- Around line 3-5: Pin the `@modelcontextprotocol/server-everything` package to
the reviewed version in the everything command’s args within
mcp_config.example.json, and apply the same pinned version to the mirrored
README examples. Keep the npx -y invocation and existing configuration structure
unchanged.

In `@tools/tauri-mcp-client/src-scripts/src/dashboards.ts`:
- Around line 54-57: Update getDashboard to validate the parsed dashboard
against the complete panel/chart contract before returning it, including
ensuring panels is an array with valid panel entries and chart data expected by
App.tsx. Throw an error for any invalid definition so the caller’s existing
error state is used, while preserving the current missing-file behavior.

In `@tools/tauri-mcp-client/src-scripts/src/mcp.ts`:
- Around line 68-97: Update the connection management around connect so
concurrent requests for the same server share one in-flight Promise<Client>
instead of creating duplicate clients. Add an in-flight map keyed by name, reuse
its promise after the existing clients check, and clear the entry in finally
while preserving the successful clients cache and existing transport setup.
- Around line 62-97: Update tools/tauri-mcp-client/src-scripts/src/mcp.ts lines
62-97 around serverNames() and connect() to fingerprint each loaded server
configuration, compare fingerprints before returning cached clients, close and
replace clients when configurations change, and evict cached clients for removed
servers. Update tools/tauri-mcp-client/README.md lines 25-28 to narrow the
runtime-reload claim until existing connections are invalidated on configuration
changes.

In `@tools/tauri-mcp-client/src-scripts/src/scripts.ts`:
- Around line 62-68: Dynamic import in importScript does not sandbox authored
scripts; execute them in a separately permission-restricted process or
container, or explicitly classify them as fully trusted code. Update
tools/tauri-mcp-client/README.md lines 17-19 to remove the sandbox-hardening
claim or document the trusted-script boundary.

In `@tools/tauri-mcp-client/src-tauri/Cargo.toml`:
- Line 6: Update the rust-version setting in Cargo.toml from 1.70 to 1.77.2,
then align the repository’s CI configuration and toolchain documentation with
Rust 1.77.2.

In `@tools/tauri-mcp-client/src-web/src/App.tsx`:
- Around line 31-43: Update the dashboard-loading useEffect around
listDashboards so it only runs when status === "ok", and clear the existing
error state after a successful dashboard load. Preserve the current list and
selection updates, ensuring a recovered bridge no longer leaves the stale error
panel visible.

In `@tools/tauri-mcp-client/src-web/src/charts/LineChart.tsx`:
- Around line 23-39: Handle an empty data array at the start of the LineChart
rendering logic before calculating ys, yMin, yMax, ticks, scales, or paths.
Render the chart’s explicit “No data” state for data.length === 0, while
preserving the existing geometry calculations for non-empty data.

In `@tools/tauri-mcp-client/src/app.js`:
- Around line 12-18: Update api() to create an AbortController and enforce a
configurable finite request deadline, passing its signal to fetch and ensuring
the timeout is cleared after completion or failure. Preserve the existing
response validation and error propagation while allowing callers to configure
the deadline through options or the established configuration mechanism.
- Around line 38-42: Update the list-item rendering around selectServer to use
native button controls inside each li instead of making the li itself clickable.
Move the server/tool selection handler onto the button, ensure the control is
keyboard-operable, and preserve the selected state with the appropriate semantic
state attribute.
- Around line 38-41: Replace the innerHTML assignments in the list-item
rendering and the related locations around lines 66-68 and 72-73 with DOM
construction using createElement, textContent, and replaceChildren. Ensure
server names, tool metadata, descriptions, and error messages are rendered
strictly as text while preserving the existing structure and displayed values.

---

Minor comments:
In `@tools/tauri-mcp-client/SECURITY.md`:
- Around line 3-7: Update the security statement in SECURITY.md to limit the
bridge-enforcement claim to the dashboard frontend only. Clarify that trusted
scripts run with normal Node process privileges and may directly access
filesystem, process, and network APIs, while retaining the configured MCP-server
restriction only for frontend access through the Script bridge.
- Around line 13-18: Update the CSP fenced code block in SECURITY.md to specify
the text language by changing its opening fence to ```text, while leaving the
CSP directives unchanged.

In `@tools/tauri-mcp-client/skills/write-dashboard/SKILL.md`:
- Line 3: Update the SKILL.md description to direct dashboard JSON files into
src-scripts/dashboards/ instead of src-web/src/dashboards/, while preserving the
existing guidance to verify that the dashboard renders.

In `@tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts`:
- Around line 13-22: Validate the numeric parameters before use: in
tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts lines 13-22,
ensure the seed used by run is finite, falling back or rejecting invalid values
before revenue calculation; in
tools/tauri-mcp-client/src-scripts/scripts/everything_sum.ts lines 13-17, ensure
both a and b are finite before invoking get-sum.

In `@tools/tauri-mcp-client/src-web/README.md`:
- Around line 6-9: Update the fenced diagram block in the README by adding a
suitable language identifier, preferably text, to its opening fence while
preserving the diagram content unchanged.

In `@tools/tauri-mcp-client/src-web/src/charts/BarChart.tsx`:
- Around line 35-42: Handle an empty data array at the start of the BarChart
rendering logic before yMax, niceTicks, yScale, band, or bar geometry are
computed. Return the component’s no-data state for data.length === 0, while
preserving the existing scale and bar rendering path for non-empty datasets.

In `@tools/tauri-mcp-client/src-web/src/charts/LineChart.tsx`:
- Around line 41-45: Update the hover index calculation in onMove to derive the
normalized position from px / (iw || 1), removing the extra M.left subtraction
while preserving the existing rounding and clamping behavior.

In `@tools/tauri-mcp-client/src/app.js`:
- Around line 47-74: Update selectServer so each tool-list request is associated
with the current server selection and stale responses are discarded. After
awaiting api, verify the selection still matches the request (or use an abort
mechanism) before mutating the tools list, including success and error
rendering; preserve the existing loading and current-server behavior.

In `@tools/tauri-mcp-client/src/styles.css`:
- Line 10: Update the CSS declarations in styles.css to satisfy Stylelint: add
the required spacing around declarations, and replace deprecated word-break:
break-word occurrences with overflow-wrap: anywhere plus normal word breaking.
Apply the same changes to the additional reported location.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d012acbb-d13f-4db6-93e1-27a65f7bc4bd

📥 Commits

Reviewing files that changed from the base of the PR and between 7f07fd8 and eb2b7d4.

⛔ Files ignored due to path filters (2)
  • tools/tauri-mcp-client/src-scripts/package-lock.json is excluded by !**/package-lock.json
  • tools/tauri-mcp-client/src-web/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (50)
  • tools/tauri-mcp-client/README.md
  • tools/tauri-mcp-client/SECURITY.md
  • tools/tauri-mcp-client/dev-dashboard.sh
  • tools/tauri-mcp-client/dev.sh
  • tools/tauri-mcp-client/scripts/build-bridge.sh
  • tools/tauri-mcp-client/scripts/build-sidecar.sh
  • tools/tauri-mcp-client/skills/inspect-mcps/SKILL.md
  • tools/tauri-mcp-client/skills/write-dashboard/SKILL.md
  • tools/tauri-mcp-client/skills/write-script/SKILL.md
  • tools/tauri-mcp-client/src-python/mcp_config.example.json
  • tools/tauri-mcp-client/src-python/requirements.txt
  • tools/tauri-mcp-client/src-python/server.py
  • tools/tauri-mcp-client/src-python/sidecar.spec
  • tools/tauri-mcp-client/src-scripts/README.md
  • tools/tauri-mcp-client/src-scripts/dashboards/mcp_overview.json
  • tools/tauri-mcp-client/src-scripts/dashboards/sales.json
  • tools/tauri-mcp-client/src-scripts/dev.sh
  • tools/tauri-mcp-client/src-scripts/mcp_config.example.json
  • tools/tauri-mcp-client/src-scripts/package.json
  • tools/tauri-mcp-client/src-scripts/scripts/demo_timeseries.ts
  • tools/tauri-mcp-client/src-scripts/scripts/everything_sum.ts
  • tools/tauri-mcp-client/src-scripts/scripts/mcp_tool_counts.ts
  • tools/tauri-mcp-client/src-scripts/src/bridge.ts
  • tools/tauri-mcp-client/src-scripts/src/dashboards.ts
  • tools/tauri-mcp-client/src-scripts/src/mcp.ts
  • tools/tauri-mcp-client/src-scripts/src/scripts.ts
  • tools/tauri-mcp-client/src-scripts/tsconfig.json
  • tools/tauri-mcp-client/src-tauri/Cargo.toml
  • tools/tauri-mcp-client/src-tauri/build.rs
  • tools/tauri-mcp-client/src-tauri/capabilities/default.json
  • tools/tauri-mcp-client/src-tauri/src/main.rs
  • tools/tauri-mcp-client/src-tauri/tauri.conf.json
  • tools/tauri-mcp-client/src-web/README.md
  • tools/tauri-mcp-client/src-web/index.html
  • tools/tauri-mcp-client/src-web/package.json
  • tools/tauri-mcp-client/src-web/src/App.tsx
  • tools/tauri-mcp-client/src-web/src/bridge.ts
  • tools/tauri-mcp-client/src-web/src/charts/BarChart.tsx
  • tools/tauri-mcp-client/src-web/src/charts/LineChart.tsx
  • tools/tauri-mcp-client/src-web/src/charts/Panel.tsx
  • tools/tauri-mcp-client/src-web/src/charts/scale.ts
  • tools/tauri-mcp-client/src-web/src/charts/useSize.ts
  • tools/tauri-mcp-client/src-web/src/main.tsx
  • tools/tauri-mcp-client/src-web/src/theme.css
  • tools/tauri-mcp-client/src-web/src/types.ts
  • tools/tauri-mcp-client/src-web/tsconfig.json
  • tools/tauri-mcp-client/src-web/vite.config.ts
  • tools/tauri-mcp-client/src/app.js
  • tools/tauri-mcp-client/src/index.html
  • tools/tauri-mcp-client/src/styles.css

Comment thread tools/tauri-mcp-client/README.md Outdated
Comment on lines +151 to +166
```bash
./scripts/build-sidecar.sh # -> src-tauri/binaries/mcp-bridge-<triple>
cd src-tauri && cargo tauri build
```

How it fits together:

- `src-python/sidecar.spec` — PyInstaller spec; bundles the fastmcp/fastapi/
uvicorn trees and `mcp_config.example.json` into one `mcp-bridge` executable.
- `scripts/build-sidecar.sh` — runs PyInstaller in a throwaway venv, then copies
the output to `src-tauri/binaries/mcp-bridge-<target-triple>` (the name Tauri
requires).
- `tauri.conf.json` → `bundle.externalBin` references `binaries/mcp-bridge`, so
Tauri copies the matching binary next to the app executable at bundle time.
- `src-tauri/src/main.rs` prefers that bundled `mcp-bridge` binary at runtime
and only falls back to `python server.py` when it isn't present (dev mode).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not package the legacy Python bridge as the dashboard sidecar.

These instructions stage Python as mcp-bridge, but the packaged Tauri flow expects that binary to serve script/dashboard resources. The Python bridge lacks /scripts and /dashboards, so the React dashboard fails after following this distributable build path. Use distinct sidecar names or make the dashboard build explicitly stage the compiled TypeScript bridge.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/README.md` around lines 151 - 166, Update the
documented Tauri packaging flow to avoid staging the legacy Python bridge as
mcp-bridge, since the packaged dashboard requires /scripts and /dashboards. Use
distinct sidecar names, or explicitly stage the compiled TypeScript dashboard
bridge, and align the references in the build commands, tauri.conf.json, and
main.rs runtime selection.

Comment thread tools/tauri-mcp-client/README.md Outdated
Comment on lines +178 to +179
- The bridge binds to `127.0.0.1` only and CORS is open — appropriate for a
local desktop bridge, not for exposing on a network.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Restrict Python bridge CORS; loopback alone is not sufficient.

src-python/server.py allows every origin, methods, and headers. A remote webpage can therefore read from and invoke this unauthenticated localhost bridge—including configured credentialed MCP tools. Replace allow_origins=["*"] with the same explicit loopback/Tauri origin policy used by the TypeScript bridge.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/README.md` around lines 178 - 179, Update the Python
bridge CORS configuration in server.py to replace the wildcard origin, methods,
and headers with the explicit loopback/Tauri origin policy used by the
TypeScript bridge. Preserve only the required local origins and ensure
credentialed requests remain restricted to that allowlist.

Comment on lines +30 to +50
if command -v rustc >/dev/null 2>&1; then
TRIPLE="$(rustc -vV | awk '/^host:/ {print $2}')"
else
case "$(uname -s)-$(uname -m)" in
Linux-x86_64) TRIPLE="x86_64-unknown-linux-gnu" ;;
Linux-aarch64) TRIPLE="aarch64-unknown-linux-gnu" ;;
Darwin-arm64) TRIPLE="aarch64-apple-darwin" ;;
Darwin-x86_64) TRIPLE="x86_64-apple-darwin" ;;
*) echo "error: unknown platform; set TRIPLE/BUN_TARGET manually" >&2; exit 1 ;;
esac
fi
case "$TRIPLE" in
x86_64-unknown-linux-gnu) BUN_TARGET="${BUN_TARGET:-bun-linux-x64}" ;;
aarch64-unknown-linux-gnu) BUN_TARGET="${BUN_TARGET:-bun-linux-arm64}" ;;
aarch64-apple-darwin) BUN_TARGET="${BUN_TARGET:-bun-darwin-arm64}" ;;
x86_64-apple-darwin) BUN_TARGET="${BUN_TARGET:-bun-darwin-x64}" ;;
*-windows-*) BUN_TARGET="${BUN_TARGET:-bun-windows-x64}"; EXE=".exe" ;;
*) BUN_TARGET="${BUN_TARGET:-bun-$(uname -s | tr A-Z a-z)-x64}" ;;
esac
EXE="${EXE:-}"
echo "==> Target triple: $TRIPLE (bun target: $BUN_TARGET)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## build-bridge.sh (around lines 1-120)\n'
sed -n '1,140p' tools/tauri-mcp-client/scripts/build-bridge.sh | cat -n

printf '\n## search for TRIPLE/BUN_TARGET/externalBin references\n'
rg -n "TRIPLE|BUN_TARGET|externalBin|mcp-bridge" tools/tauri-mcp-client -S

printf '\n## related build-sidecar script\n'
sed -n '1,200p' tools/tauri-mcp-client/scripts/build-sidecar.sh | cat -n

Repository: AM1010101/agent-skills

Length of output: 12198


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## file list under tools/tauri-mcp-client\n'
git ls-files tools/tauri-mcp-client | sed -n '1,200p'

printf '\n## tauri config files mentioning externalBin or sidecar\n'
rg -n "externalBin|sidecar|mcp-bridge|build-bridge" tools/tauri-mcp-client -S

Repository: AM1010101/agent-skills

Length of output: 11102


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## build-bridge.sh (around lines 1-140)\n'
sed -n '1,140p' tools/tauri-mcp-client/scripts/build-bridge.sh | cat -n

printf '\n## search for TRIPLE/BUN_TARGET/externalBin/mcp-bridge references\n'
rg -n "TRIPLE|BUN_TARGET|externalBin|mcp-bridge" tools/tauri-mcp-client -S

printf '\n## related build-sidecar script\n'
sed -n '1,200p' tools/tauri-mcp-client/scripts/build-sidecar.sh | cat -n

Repository: AM1010101/agent-skills

Length of output: 12209


Derive the staged triple from the intended bundle target. TRIPLE is always taken from rustc -vV, so an explicit TRIPLE is ignored and BUN_TARGET=bun-darwin-arm64 on Linux still stages mcp-bridge-<linux-triple>. That breaks Tauri’s target-specific externalBin lookup for cross-target builds. Accept a matching TRIPLE/target or map it from BUN_TARGET and fail on mismatches.

🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 47-47: Use '[:upper:]' to support accents and foreign alphabets.

(SC2019)


[info] 47-47: Use '[:lower:]' to support accents and foreign alphabets.

(SC2018)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/scripts/build-bridge.sh` around lines 30 - 50, Update
the target-resolution logic before the `case "$TRIPLE"` mapping so explicit
`TRIPLE` and `BUN_TARGET` values are honored and mutually consistent. Derive the
Rust triple from `BUN_TARGET` when only the bundle target is provided, preserve
native detection when neither is set, and fail clearly when the supplied values
mismatch; ensure the staged bridge filename uses the resolved intended triple.

Comment thread tools/tauri-mcp-client/scripts/build-bridge.sh Outdated
Comment on lines +161 to +167
app = FastAPI(title="Tauri MCP Client bridge", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # localhost-only server; fine for a desktop bridge
allow_methods=["*"],
allow_headers=["*"],
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## server.py outline\n'
ast-grep outline tools/tauri-mcp-client/src-python/server.py --view expanded || true

printf '\n## relevant route and middleware context\n'
sed -n '1,260p' tools/tauri-mcp-client/src-python/server.py

printf '\n## search for origin/auth/token checks in the Python client bridge\n'
rg -n "allow_origins|CORSMiddleware|origin|token|auth|middleware|FastAPI|`@app`\." tools/tauri-mcp-client/src-python -S

Repository: AM1010101/agent-skills

Length of output: 10220


Restrict CORS to trusted app origins.

allow_origins=["*"] lets any website read from and invoke this localhost bridge’s MCP tool endpoints. Loopback binding is not an origin boundary; use an explicit Tauri/Vite allowlist, and add a per-launch token if non-browser local clients need to be excluded.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-python/server.py` around lines 161 - 167, Update
the CORSMiddleware configuration in the FastAPI app to replace
allow_origins=["*"] with an explicit allowlist of trusted Tauri/Vite application
origins. Preserve the existing methods and headers settings, and add a
per-launch authentication token for MCP endpoints if required to exclude
non-browser local clients.

Comment on lines +31 to +43
useEffect(() => {
let alive = true;
listDashboards()
.then((ds) => {
if (!alive) return;
setList(ds);
setSelected((cur) => cur ?? ds[0]?.name ?? null);
})
.catch((e) => alive && setError((e as Error).message));
return () => {
alive = false;
};
}, [status === "ok"]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clear stale dashboard-list errors after bridge recovery.

This effect runs before the bridge is healthy, and a failed initial request sets error. When /health later becomes healthy, a successful retry updates list but never clears error, so the error panel continues to hide the recovered dashboard. Gate on status === "ok" and clear the error before or after a successful load.

Proposed fix
   useEffect(() => {
+    if (status !== "ok") return;
     let alive = true;
+    setError(null);
     listDashboards()
       .then((ds) => {
         if (!alive) return;
         setList(ds);
         setSelected((cur) => cur ?? ds[0]?.name ?? null);
       })
       .catch((e) => alive && setError((e as Error).message));
     return () => {
       alive = false;
     };
-  }, [status === "ok"]);
+  }, [status]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
let alive = true;
listDashboards()
.then((ds) => {
if (!alive) return;
setList(ds);
setSelected((cur) => cur ?? ds[0]?.name ?? null);
})
.catch((e) => alive && setError((e as Error).message));
return () => {
alive = false;
};
}, [status === "ok"]);
useEffect(() => {
if (status !== "ok") return;
let alive = true;
setError(null);
listDashboards()
.then((ds) => {
if (!alive) return;
setList(ds);
setSelected((cur) => cur ?? ds[0]?.name ?? null);
})
.catch((e) => alive && setError((e as Error).message));
return () => {
alive = false;
};
}, [status]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/src/App.tsx` around lines 31 - 43, Update the
dashboard-loading useEffect around listDashboards so it only runs when status
=== "ok", and clear the existing error state after a successful dashboard load.
Preserve the current list and selection updates, ensuring a recovered bridge no
longer leaves the stale error panel visible.

Comment on lines +23 to +39
const ys = data.map((d) => Number(d[y]));
const yMin = Math.min(...ys, 0);
const yMax = Math.max(...ys);
const ticks = niceTicks(yMin, yMax, 4);
const yScale = linear(
[ticks[0], ticks[ticks.length - 1]],
[M.top + ih, M.top],
);
const xAt = (i: number) =>
M.left + (data.length <= 1 ? iw / 2 : (i / (data.length - 1)) * iw);

const path = data
.map((d, i) => `${i === 0 ? "M" : "L"} ${xAt(i).toFixed(1)} ${yScale(Number(d[y])).toFixed(1)}`)
.join(" ");
const area =
`${path} L ${xAt(data.length - 1).toFixed(1)} ${(M.top + ih).toFixed(1)} ` +
`L ${xAt(0).toFixed(1)} ${(M.top + ih).toFixed(1)} Z`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Handle empty chart data before building scales and paths.

For data = [], Math.max(...ys) becomes -Infinity, niceTicks returns no ticks, and the area path uses data.length - 1. Render an explicit “No data” state (or reject empty rows upstream) before calculating chart geometry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/src/charts/LineChart.tsx` around lines 23 -
39, Handle an empty data array at the start of the LineChart rendering logic
before calculating ys, yMin, yMax, ticks, scales, or paths. Render the chart’s
explicit “No data” state for data.length === 0, while preserving the existing
geometry calculations for non-empty data.

Comment thread tools/tauri-mcp-client/src/app.js Outdated
Comment on lines +12 to +18
async function api(path, options) {
const res = await fetch(BASE + path, options);
if (!res.ok) {
const text = await res.text().catch(() => res.statusText);
throw new Error(`${res.status}: ${text}`);
}
return res.json();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add a finite timeout to bridge requests.

A stalled sidecar or MCP call leaves the UI indefinitely in calling…; the 5-second health poll also accumulates pending requests. Use an AbortController with a configurable deadline in api().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src/app.js` around lines 12 - 18, Update api() to
create an AbortController and enforce a configurable finite request deadline,
passing its signal to fetch and ensuring the timeout is cleared after completion
or failure. Preserve the existing response validation and error propagation
while allowing callers to configure the deadline through options or the
established configuration mechanism.

Comment thread tools/tauri-mcp-client/src/app.js Outdated
Comment on lines +38 to +41
const li = document.createElement("li");
li.innerHTML = `<span class="kind">${s.kind}</span>
<div class="name">${s.name}</div>
<div class="desc">${s.description || ""}</div>`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not render bridge data with innerHTML.

Server/tool metadata and error messages can contain externally controlled text. The Python bridge returns configured server names and remote tool metadata, so these assignments permit markup injection. Build nodes with textContent/replaceChildren() instead.

Also applies to: 66-68, 72-73

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 38-40: Avoid assigning untrusted data to innerHTML/outerHTML or document.write
Context: li.innerHTML = <span class="kind">${s.kind}</span> <div class="name">${s.name}</div> <div class="desc">${s.description || ""}</div>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').

(inner-outer-html)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src/app.js` around lines 38 - 41, Replace the
innerHTML assignments in the list-item rendering and the related locations
around lines 66-68 and 72-73 with DOM construction using createElement,
textContent, and replaceChildren. Ensure server names, tool metadata,
descriptions, and error messages are rendered strictly as text while preserving
the existing structure and displayed values.

Source: Linters/SAST tools

Comment thread tools/tauri-mcp-client/src/app.js Outdated
Comment on lines +38 to +42
const li = document.createElement("li");
li.innerHTML = `<span class="kind">${s.kind}</span>
<div class="name">${s.name}</div>
<div class="desc">${s.description || ""}</div>`;
li.onclick = () => selectServer(s.name, li);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make server and tool selection keyboard-operable.

Clickable <li> elements cannot be reached or activated by keyboard users. Use native <button> controls within each list item and retain the selected state semantically.

Also applies to: 66-70

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 38-40: Avoid assigning untrusted data to innerHTML/outerHTML or document.write
Context: li.innerHTML = <span class="kind">${s.kind}</span> <div class="name">${s.name}</div> <div class="desc">${s.description || ""}</div>
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting').

(inner-outer-html)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src/app.js` around lines 38 - 42, Update the list-item
rendering around selectServer to use native button controls inside each li
instead of making the li itself clickable. Move the server/tool selection
handler onto the button, ensure the control is keyboard-operable, and preserve
the selected state with the appropriate semantic state attribute.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/tauri-mcp-client/SECURITY.md`:
- Around line 18-21: Update the fenced CSP block in SECURITY.md to include the
text language identifier, preserving its contents unchanged.

In `@tools/tauri-mcp-client/src-scripts/src/bridge.ts`:
- Around line 102-105: Update the configuration parser around the returned
ServerConfig to handle config.env explicitly: validate it as a string-to-string
record and preserve it in the returned config so McpManager.connect can pass it
to StdioClientTransport, or reject the field with a clear validation error if
environment variables are unsupported. Do not silently discard a supplied
config.env.

In `@tools/tauri-mcp-client/src-scripts/src/mcp.ts`:
- Around line 145-148: Update connect and disconnect to track a per-server
generation or pending connection. In disconnect, invalidate the generation
before removing and closing the cached client; in connect, verify the generation
remains current before caching the newly connected client, and close and retry
the client when it has been invalidated.
- Around line 145-148: Update disconnect in the MCP client manager so
client.close() cleanup is best-effort and cannot reject after the configuration
has been saved; match the existing close() behavior by handling or suppressing
close failures while still deleting the client entry. Ensure bridge.ts does not
report the configuration update as failed when disconnect cleanup fails.

In `@tools/tauri-mcp-client/src-tauri/binaries/dashboards/sales.json`:
- Around line 17-19: Update the seed in the bar panel’s demo_timeseries params
from 6 to 3 so it uses the same series as the line panel; preserve the existing
chart configuration and subtitle.

In `@tools/tauri-mcp-client/src-tauri/binaries/mcp_config.example.json`:
- Around line 4-5: Update the MCP configuration represented by the command and
args entries to avoid runtime npx resolution: use a bundled, reviewed MCP server
binary or a pinned package with enforced signature/integrity verification,
ensuring release users do not need Node/npm or mutable package downloads.

In `@tools/tauri-mcp-client/src-tauri/binaries/scripts/demo_timeseries.mjs`:
- Around line 5-6: Validate every numeric parameter with a finite-number check
before computation: in
tools/tauri-mcp-client/src-tauri/binaries/scripts/demo_timeseries.mjs lines 5-6,
validate seed before generating revenue values; in
tools/tauri-mcp-client/src-tauri/binaries/scripts/everything_sum.mjs lines 5-7,
validate both a and b before calling ctx.callTool. Reject invalid, NaN, or
infinite inputs rather than allowing them across the bridge or into serialized
data.

In `@tools/tauri-mcp-client/src-tauri/binaries/scripts/everything_sum.mjs`:
- Line 8: Update the get-sum handling around ctx.callTool so the returned text
envelope is parsed to extract and return the numeric sum before the dashboard
consumes it. Preserve the existing a and b inputs, and ensure the result is
numeric rather than the full descriptive string.

In `@tools/tauri-mcp-client/src-tauri/binaries/scripts/mcp_tool_counts.mjs`:
- Around line 10-11: Update the catch block around ctx.listTools to normalize
unknown rejection values before accessing the message: use the Error message
only when e is an Error, otherwise convert e with String(e). Preserve the
existing skip log and fallback-row behavior for null, undefined, and other
non-Error rejections.
- Around line 10-12: Update the listTools failure handling in the catch block to
avoid pushing a server record with tools: 0, since that represents an outage as
a valid empty result. Propagate the failure or store an explicit error status,
and ensure downstream rendering distinguishes unavailable servers from servers
with no tools.
- Line 8: Update the MCP RPC flows around listTools(server), callTool(...), and
the HTTP bridge handler to enforce a bounded timeout for every connect,
client.listTools(), and tool invocation. Use the existing timeout or abort
mechanism where available, otherwise wrap each awaited call with cancellation or
a Promise.race, and ensure timed-out servers fail promptly so subsequent server
queries continue.

In `@tools/tauri-mcp-client/src-web/public/sandbox.js`:
- Around line 41-45: Update the message listener around the existing
dashboard-model validation to require event.source to equal window.parent before
calling render(data.model). Keep the current payload and panels checks
unchanged, and do not add an event.origin restriction because this frame uses an
opaque origin.

In `@tools/tauri-mcp-client/src-web/src/App.tsx`:
- Around line 71-80: Introduce a dedicated serversError state for the
listServers effect and update its catch handler to set that state instead of the
shared error state. Render serversError in the Connected MCPs/connections view,
leaving the dashboard error state and its existing loading flows unchanged.

In `@tools/tauri-mcp-client/src-web/src/DashboardSandbox.tsx`:
- Around line 44-51: The error path in DashboardSandbox.tsx forwards raw script
failure messages to the sandbox frame. Replace the Error.message value in the
Promise.all panel mapping with a generic non-identifying string before assigning
SandboxedPanel.error; re-verify the claim in tools/tauri-mcp-client/SECURITY.md
lines 23-27 after this code fix, with no direct documentation change unless
needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4181e491-a090-4564-9110-0fc3ba0b1273

📥 Commits

Reviewing files that changed from the base of the PR and between eb2b7d4 and 0e2a9a2.

⛔ Files ignored due to path filters (51)
  • tools/tauri-mcp-client/src-tauri/Cargo.lock is excluded by !**/*.lock
  • tools/tauri-mcp-client/src-tauri/icons/128x128.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/128x128@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/32x32.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/64x64.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square107x107Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square142x142Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square150x150Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square284x284Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square30x30Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square310x310Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square44x44Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square71x71Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/Square89x89Logo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/StoreLogo.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/icon.ico is excluded by !**/*.ico
  • tools/tauri-mcp-client/src-tauri/icons/icon.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/icon.svg is excluded by !**/*.svg
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-20x20@1x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-20x20@2x-1.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-20x20@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-20x20@3x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-29x29@1x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-29x29@2x-1.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-29x29@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-29x29@3x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-40x40@1x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-40x40@2x-1.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-40x40@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-40x40@3x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-512@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-60x60@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-60x60@3x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-76x76@1x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-76x76@2x.png is excluded by !**/*.png
  • tools/tauri-mcp-client/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png is excluded by !**/*.png
📒 Files selected for processing (25)
  • .gitignore
  • skills/mcp-apps/SKILL.md
  • skills/mcp-apps/agents/openai.yaml
  • tools/basic-crm/.gitignore
  • tools/phased-builder/.gitignore
  • tools/tauri-mcp-client/SECURITY.md
  • tools/tauri-mcp-client/src-scripts/src/bridge.ts
  • tools/tauri-mcp-client/src-scripts/src/mcp.ts
  • tools/tauri-mcp-client/src-tauri/.gitignore
  • tools/tauri-mcp-client/src-tauri/binaries/dashboards/mcp_overview.json
  • tools/tauri-mcp-client/src-tauri/binaries/dashboards/sales.json
  • tools/tauri-mcp-client/src-tauri/binaries/mcp_config.example.json
  • tools/tauri-mcp-client/src-tauri/binaries/scripts/demo_timeseries.mjs
  • tools/tauri-mcp-client/src-tauri/binaries/scripts/everything_sum.mjs
  • tools/tauri-mcp-client/src-tauri/binaries/scripts/mcp_tool_counts.mjs
  • tools/tauri-mcp-client/src-tauri/icons/icon.icns
  • tools/tauri-mcp-client/src-tauri/src/main.rs
  • tools/tauri-mcp-client/src-tauri/tauri.conf.json
  • tools/tauri-mcp-client/src-web/public/sandbox.css
  • tools/tauri-mcp-client/src-web/public/sandbox.html
  • tools/tauri-mcp-client/src-web/public/sandbox.js
  • tools/tauri-mcp-client/src-web/src/App.tsx
  • tools/tauri-mcp-client/src-web/src/DashboardSandbox.tsx
  • tools/tauri-mcp-client/src-web/src/bridge.ts
  • tools/tauri-mcp-client/src-web/src/theme.css
💤 Files with no reviewable changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (2)
  • tools/tauri-mcp-client/src-tauri/tauri.conf.json
  • tools/tauri-mcp-client/src-tauri/src/main.rs

Comment thread tools/tauri-mcp-client/SECURITY.md Outdated
Comment on lines +18 to +21
```
default-src 'none'; script-src 'self'; style-src 'self'; img-src data:;
connect-src 'none'; base-uri 'none'; form-action 'none'
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced CSP block.

markdownlint (MD040) flags this fenced code block for missing a language identifier.

Proposed fix
-```
+```text
 default-src 'none'; script-src 'self'; style-src 'self'; img-src data:;
 connect-src 'none'; base-uri 'none'; form-action 'none'
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 18-18: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/SECURITY.md` around lines 18 - 21, Update the fenced
CSP block in SECURITY.md to include the text language identifier, preserving its
contents unchanged.

Source: Linters/SAST tools

Comment on lines +102 to +105
if (typeof config.command !== "string" || !config.command.trim()) throw new Error("A local MCP command is required.");
const args = config.args === undefined ? [] : config.args;
if (!Array.isArray(args) || args.some((arg) => typeof arg !== "string")) throw new Error("Arguments must be strings.");
return { name, config: { command: config.command.trim(), args } };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve or reject config.env explicitly.

McpManager.connect passes cfg.env to StdioClientTransport, but this parser silently drops a supplied config.env. The route returns HTTP 201, then the local MCP process starts without its required environment variables.

Validate config.env as a string-to-string record and include it in the returned ServerConfig. If this endpoint must not accept environment variables, reject config.env instead of discarding it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-scripts/src/bridge.ts` around lines 102 - 105,
Update the configuration parser around the returned ServerConfig to handle
config.env explicitly: validate it as a string-to-string record and preserve it
in the returned config so McpManager.connect can pass it to
StdioClientTransport, or reject the field with a clear validation error if
environment variables are unsupported. Do not silently discard a supplied
config.env.

Comment on lines +145 to +148
async disconnect(name: string) {
const client = this.clients.get(name);
this.clients.delete(name);
if (client) await client.close();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make disconnect invalidate an in-progress connection.

A connect(name) call can load the old configuration and await its transport connection before it adds a client to this.clients. During that await, POST /servers saves the new configuration and disconnect(name) finds no cached client. The old connection then completes and is cached after the update.

Track a per-server generation or pending connection. Invalidate that generation before cleanup. Before caching a connected client, verify that its generation is still current. Close and retry the client when the generation changed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-scripts/src/mcp.ts` around lines 145 - 148, Update
connect and disconnect to track a per-server generation or pending connection.
In disconnect, invalidate the generation before removing and closing the cached
client; in connect, verify the generation remains current before caching the
newly connected client, and close and retry the client when it has been
invalidated.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Do not report a failed configuration update after saveConfig succeeds.

bridge.ts saves the configuration before it awaits disconnect(name). If client.close() rejects on Line 148, the route returns HTTP 400 although the new configuration is already persisted. Match close() behavior and make disconnection cleanup best-effort, or return a result that distinguishes a saved configuration from a cleanup failure.

Proposed fix
   async disconnect(name: string) {
     const client = this.clients.get(name);
     this.clients.delete(name);
-    if (client) await client.close();
+    if (client) {
+      try {
+        await client.close();
+      } catch {
+        /* ignore cleanup failure */
+      }
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async disconnect(name: string) {
const client = this.clients.get(name);
this.clients.delete(name);
if (client) await client.close();
async disconnect(name: string) {
const client = this.clients.get(name);
this.clients.delete(name);
if (client) {
try {
await client.close();
} catch {
/* ignore cleanup failure */
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-scripts/src/mcp.ts` around lines 145 - 148, Update
disconnect in the MCP client manager so client.close() cleanup is best-effort
and cannot reject after the configuration has been saved; match the existing
close() behavior by handling or suppressing close failures while still deleting
the client entry. Ensure bridge.ts does not report the configuration update as
failed when disconnect cleanup fails.

Comment on lines +17 to +19
"script": "demo_timeseries",
"params": { "seed": 6 },
"chart": { "type": "bar", "x": "month", "y": "revenue", "yLabel": "Revenue ($)" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the same seed for the “same series” comparison.

The line panel uses seed 3, but the bar panel uses seed 6. The panels therefore render different data. Set the bar seed to 3, or change the subtitle.

Proposed fix
-      "params": { "seed": 6 },
+      "params": { "seed": 3 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"script": "demo_timeseries",
"params": { "seed": 6 },
"chart": { "type": "bar", "x": "month", "y": "revenue", "yLabel": "Revenue ($)" }
"script": "demo_timeseries",
"params": { "seed": 3 },
"chart": { "type": "bar", "x": "month", "y": "revenue", "yLabel": "Revenue ($)" }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-tauri/binaries/dashboards/sales.json` around lines
17 - 19, Update the seed in the bar panel’s demo_timeseries params from 6 to 3
so it uses the same series as the line panel; preserve the existing chart
configuration and subtitle.

Comment on lines +4 to +5
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-everything"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 'server-everything|npx|mcp_config' tools/tauri-mcp-client
npm view `@modelcontextprotocol/server-everything` version versions dist.integrity --json

Repository: AM1010101/agent-skills

Length of output: 50380


Pin and package the MCP server before release.

The bundled example seeds mcp_config.json with "command": "npx" and "args": ["-y", "@model contextprotocol/server-everything"]. That resolves a mutable package at runtime and requires Node/npm on the user host. Pin the server and enforce a signature/integrity boundary, or bundle the reviewed server binary with Node/npm instead of relying around an unpinned package.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-tauri/binaries/mcp_config.example.json` around
lines 4 - 5, Update the MCP configuration represented by the command and args
entries to avoid runtime npx resolution: use a bundled, reviewed MCP server
binary or a pinned package with enforced signature/integrity verification,
ensuring release users do not need Node/npm or mutable package downloads.

Comment on lines +10 to +11
} catch (e) {
ctx.log(`skip ${server}: ${e.message}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Normalize unknown rejection values before reading e.message.

The catch block assumes that e is a non-null Error. If ctx.listTools rejects with null or undefined, the logger throws inside the catch block and the fallback row is not returned.

Use e instanceof Error ? e.message : String(e).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-tauri/binaries/scripts/mcp_tool_counts.mjs` around
lines 10 - 11, Update the catch block around ctx.listTools to normalize unknown
rejection values before accessing the message: use the Error message only when e
is an Error, otherwise convert e with String(e). Preserve the existing skip log
and fallback-row behavior for null, undefined, and other non-Error rejections.

Comment on lines +10 to +12
} catch (e) {
ctx.log(`skip ${server}: ${e.message}`);
rows.push({ server, tools: 0 });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not report an unavailable server as a server with zero tools.

When listTools fails, { tools: 0 } creates false dashboard data. The chart cannot distinguish an outage from a valid empty tool list. Return an explicit error status and render it, or propagate the failure instead of using zero.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-tauri/binaries/scripts/mcp_tool_counts.mjs` around
lines 10 - 12, Update the listTools failure handling in the catch block to avoid
pushing a server record with tools: 0, since that represents an outage as a
valid empty result. Propagate the failure or store an explicit error status, and
ensure downstream rendering distinguishes unavailable servers from servers with
no tools.

Comment on lines +41 to +45
window.addEventListener('message', (event) => {
const data = event.data;
if (!data || data.type !== 'dashboard-model' || !data.model || !Array.isArray(data.model.panels)) return;
render(data.model);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add a sender check to the message listener.

This listener accepts any dashboard-model message without checking event.source or event.origin. Static analysis flags this as CWE-346 (origin validation error). The frame has an opaque origin, so the parent must target it with "*" (confirmed against MDN's postMessage guidance for opaque-origin targets), but the receiver here should still confirm the message actually came from its own parent frame before rendering it.

Proposed fix
 window.addEventListener('message', (event) => {
+  if (event.source !== window.parent) return;
   const data = event.data;
   if (!data || data.type !== 'dashboard-model' || !data.model || !Array.isArray(data.model.panels)) return;
   render(data.model);
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
window.addEventListener('message', (event) => {
const data = event.data;
if (!data || data.type !== 'dashboard-model' || !data.model || !Array.isArray(data.model.panels)) return;
render(data.model);
});
window.addEventListener('message', (event) => {
if (event.source !== window.parent) return;
const data = event.data;
if (!data || data.type !== 'dashboard-model' || !data.model || !Array.isArray(data.model.panels)) return;
render(data.model);
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/public/sandbox.js` around lines 41 - 45,
Update the message listener around the existing dashboard-model validation to
require event.source to equal window.parent before calling render(data.model).
Keep the current payload and panels checks unchanged, and do not add an
event.origin restriction because this frame uses an opaque origin.

Source: Linters/SAST tools

Comment on lines +71 to +80
// The connection list belongs to the trusted shell. It never enters a
// dashboard definition or panel payload.
useEffect(() => {
if (status !== "ok") return;
let alive = true;
listServers()
.then((items) => alive && setServers(items))
.catch((e) => alive && setError((e as Error).message));
return () => { alive = false; };
}, [status]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Servers-loading failure overwrites the dashboard-view error state.

This effect calls setError on failure, the same state variable used by the dashboard-loading effect (line 65) and the dashboard-definition effect (line 104). Only the Dashboard view renders error (line 151). If listing MCP servers fails, the Dashboard tab shows an unrelated error message, even though the actual failure belongs to the Connected MCPs view. Conversely, a later dashboard load does not clear a stale error left by a servers failure.

Introduce a dedicated state for this effect's failures, consistent with how toolsError and saveError are already scoped to their own views.

Proposed fix
+  const [serversError, setServersError] = useState<string | null>(null);
+
   useEffect(() => {
     if (status !== "ok") return;
     let alive = true;
     listServers()
       .then((items) => alive && setServers(items))
-      .catch((e) => alive && setError((e as Error).message));
+      .catch((e) => alive && setServersError((e as Error).message));
     return () => { alive = false; };
   }, [status]);

Render serversError in the connections view instead of reusing error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/tauri-mcp-client/src-web/src/App.tsx` around lines 71 - 80, Introduce a
dedicated serversError state for the listServers effect and update its catch
handler to set that state instead of the shared error state. Render serversError
in the Connected MCPs/connections view, leaving the dashboard error state and
its existing loading flows unchanged.

Comment thread tools/tauri-mcp-client/src-web/src/DashboardSandbox.tsx Outdated
@AM1010101 AM1010101 closed this Jul 31, 2026
@AM1010101
AM1010101 deleted the claude/tauri-fastmcp-tool-qjgc6w branch July 31, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants