Skip to main content
Glama

tauri-plugin-mcp

Cross-platform Tauri test automation plugin via MCP (Model Context Protocol).

Enables AI assistants like Claude to interact with your Tauri desktop app for testing and automation.

Features

  • Cross-platform: Windows (Named Pipes) + macOS/Linux (Unix Sockets)

  • No CDP dependency: Works on all WebView backends including macOS WKWebView

  • MCP integration: Direct integration with Claude Code and other MCP clients

Prerequisites

  • Node.js >= 18

  • Tauri v2.x

  • pnpm (recommended) or npm

  • Rust with cargo

Quick Start

  1. Add Rust plugin to src-tauri/Cargo.toml

  2. Install npm package: pnpm add github:DaveDev42/tauri-plugin-mcp#main

  3. Register plugin in src-tauri/src/lib.rs

  4. Add mcp:default permission

  5. Initialize bridge in main.tsx

  6. Create .mcp.json for Claude Code

Installation

1. Rust Plugin (src-tauri/Cargo.toml)

[dependencies] tauri-plugin-mcp = { git = "https://github.com/DaveDev42/tauri-plugin-mcp" }

2. Frontend API (package.json)

pnpm add github:DaveDev42/tauri-plugin-mcp#main

3. MCP Server

The MCP server binary (tauri-mcp) is automatically available after installation. No additional setup required.

Setup

1. Register the plugin (src-tauri/src/lib.rs)

pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_mcp::init()) .run(tauri::generate_context!()) .expect("error while running tauri application"); }

2. Add permissions

Option A: In tauri.conf.json or config/*.json5 (recommended)

{ "security": { "capabilities": [{ "identifier": "main-capability", "windows": ["main"], "permissions": ["core:default", "mcp:default"] }] } }

Option B: Separate file (src-tauri/capabilities/default.json)

{ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "windows": ["main"], "permissions": ["core:default", "mcp:default"] }

3. Initialize the bridge (main.tsx)

// Initialize MCP bridge for E2E testing (dev mode only) if (import.meta.env.DEV) { import('tauri-plugin-mcp').then(({ initMcpBridge }) => { initMcpBridge().catch(err => { console.warn('[MCP] Bridge initialization failed:', err); }); }); }

Production-Safe Setup (Optional Dependency)

The basic setup above includes MCP in all builds. For production apps, you likely want MCP only in development and completely stripped from release binaries.

This approach uses Cargo's optional dependency feature so the plugin is compiled in only when explicitly requested.

1. Cargo optional dependency (src-tauri/Cargo.toml)

[features] default = [] dev-tools = ["dep:tauri-plugin-mcp"] [dependencies] tauri-plugin-mcp = { git = "https://github.com/DaveDev42/tauri-plugin-mcp", optional = true }

2. Conditional plugin registration (src-tauri/src/lib.rs)

pub fn run() { let mut builder = tauri::Builder::default(); #[cfg(feature = "dev-tools")] { builder = builder.plugin(tauri_plugin_mcp::init()); } builder .run(tauri::generate_context!()) .expect("error while running tauri application"); }

3. Capabilities file split

Separate mcp:default into its own capability file so it can be toggled at build time.

capabilities/default.json — always active, no MCP permission:

{ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "windows": ["main"], "permissions": ["core:default"] }

capabilities/.dev-tools.json.disabled — MCP permission template (git-tracked):

{ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "dev-tools", "windows": ["main"], "permissions": ["mcp:default"] }

capabilities/dev-tools.json — add to .gitignore (generated at build time):

# Dev-tools capability (generated from .disabled at build time) src-tauri/capabilities/dev-tools.json

4. build.rs — conditional capabilities management

build.rs copies the template into place when the feature is enabled, and removes it otherwise:

fn main() { let dev_tools_cap = std::path::Path::new("capabilities/dev-tools.json"); let source_path = std::path::Path::new("capabilities/.dev-tools.json.disabled"); if std::env::var("CARGO_FEATURE_DEV_TOOLS").is_ok() { // Copy .disabled → active (skip if already identical to avoid rebuild churn) let should_copy = if dev_tools_cap.exists() { std::fs::read(source_path).ok() != std::fs::read(dev_tools_cap).ok() } else { true }; if should_copy { std::fs::copy(source_path, dev_tools_cap) .expect("Failed to copy dev-tools capability file"); } } else if dev_tools_cap.exists() { std::fs::remove_file(dev_tools_cap).ok(); } tauri_build::try_build( tauri_build::Attributes::default() ).expect("Failed to build tauri"); }

5. Dev script (package.json)

{ "scripts": { "dev": "tauri dev --features dev-tools" } }

Now pnpm dev enables MCP, while tauri build (without the feature) produces a clean release with zero MCP code.

Note: The frontend bridge guard (import.meta.env.DEV) from the basic setup still applies — it prevents the bridge from initializing even if the plugin were somehow present at runtime.

MCP Server Configuration

Add to .mcp.json in your project root:

{ "mcpServers": { "tauri-mcp": { "command": "npx", "args": ["tauri-mcp"], "env": { "TAURI_PROJECT_ROOT": "." } } } }

Note: pnpm users can also use pnpx tauri-mcp or pnpm exec tauri-mcp.

Monorepo Configuration

If the package is installed in a subdirectory (e.g., apps/desktop):

{ "mcpServers": { "tauri-mcp": { "command": "npx", "args": ["tauri-mcp"], "env": { "TAURI_PROJECT_ROOT": "./apps/desktop" }, "cwd": "./apps/desktop" } } }

Available Tools

Tool

Parameters

Description

app_status

-

Check if app is running

launch_app

wait_for_ready?: boolean, timeout_secs?: number, features?: string[]

Launch Tauri app via pnpm tauri dev

stop_app

-

Stop the app

snapshot

-

Get accessibility tree (returns ref numbers)

click

ref?: number, selector?: string

Click element by ref or CSS selector

fill

ref?: number, selector?: string, value: string

Fill input field

press_key

key: string

Press keyboard key

navigate

url: string

Navigate to URL

screenshot

-

Take screenshot (uses html2canvas)

evaluate_script

script: string

Execute custom JavaScript

get_console_logs

-

Get console logs

get_network_logs

-

Get network logs

Using features parameter

To launch with Cargo features:

launch_app({ features: ["my_feature"] })

This runs: pnpm tauri dev --features my_feature

Usage Example

Typical testing workflow:

1. launch_app({ timeout_secs: 120 }) 2. snapshot() # Get element refs 3. click({ ref: 5 }) # Click button by ref 4. fill({ selector: "input[name='email']", value: "test@example.com" }) 5. screenshot() # Verify result 6. stop_app()

How It Works

Claude Code <-> MCP Server <-> Socket <-> Tauri Plugin <-> JS Bridge <-> Your App
  1. Rust Plugin creates IPC server (Unix socket or Windows named pipe)

  2. MCP Server connects to IPC and exposes tools to Claude

  3. JS Bridge (initMcpBridge()) enables DOM operations in WebView

Socket Paths

  • Unix: {project_root}/.tauri-mcp.sock

  • Windows: \\.\pipe\tauri-mcp-{hash} (hash derived from project path)

Troubleshooting

"MCP bridge not initialized"

The JS bridge isn't running. Check:

  • initMcpBridge() is called in your frontend code

  • App is running in dev mode (import.meta.env.DEV)

  • Check browser console for initialization errors

Socket connection failed

  • Ensure the app is running (launch_app first)

  • On Windows, check pipe path in logs: [tauri-plugin-mcp] full_path: \\.\pipe\tauri-mcp-XXXXX

  • On Unix, check if .tauri-mcp.sock exists in project root

App launch timeout

  • Increase timeout_secs (default: 60)

  • Check if pnpm tauri dev works manually

  • Look for build errors in terminal output

snapshot returns empty

  • Wait for app to fully load (use wait_for_ready: true)

  • Check if bridge initialized (look for [MCP] logs in console)

Development

After cloning, pnpm install automatically configures git hooks and builds the project.

The dist/ directories are committed to the repo so that git-based installs (pnpm add github:...) work without a build step. A pre-commit hook verifies that dist/ stays in sync with TypeScript sources — if the hook blocks your commit, run:

pnpm build git add packages/*/dist/

Then retry your commit.

License

MIT OR Apache-2.0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/DaveDev42/tauri-plugin-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server