| name | tauri-mcp-server-development |
| description | Build, test, and debug Tauri v2 applications using AI assistants with the Model Context Protocol server for UI automation, IPC monitoring, and mobile development |
| triggers | ["set up Tauri MCP for AI development","automate Tauri app testing with screenshots","monitor Tauri IPC calls in my app","debug my Tauri webview with AI","add MCP bridge plugin to Tauri project","capture console logs from Tauri app","interact with Tauri UI elements programmatically","use visual element picker in Tauri"] |
Tauri MCP Server Development
Skill by ara.so — MCP Skills collection.
A Model Context Protocol (MCP) server that enables AI assistants to build, test, and debug Tauri v2 applications through UI automation, IPC monitoring, log streaming, and mobile device management.
What It Does
The Tauri MCP server provides 21 tools across four categories:
- UI Automation: Screenshots, element finding, clicking, typing, scrolling, visual element picker
- IPC Monitoring: Capture and inspect Tauri IPC calls in real-time
- Mobile Development: List iOS simulators and Android emulators
- Logs: Stream console, Android logcat, iOS, and system logs
It consists of two components:
- MCP Server (Node.js) - Connects to AI assistants via stdio
- MCP Bridge Plugin (Rust) - Installed in your Tauri app, exposes automation APIs via WebSocket
Installation
Install MCP Server for AI Assistant
Use install-mcp to add the server to your AI assistant:
npx -y install-mcp @hypothesi/tauri-mcp-server --client claude-code
npx -y install-mcp @hypothesi/tauri-mcp-server --client cursor
npx -y install-mcp @hypothesi/tauri-mcp-server --client vscode
npx -y install-mcp @hypothesi/tauri-mcp-server --client windsurf
Supported clients: claude-code, cursor, windsurf, vscode, cline, roo-cline, claude, zed, goose, warp, codex
Restart your AI assistant after installation.
CLI Usage (Optional)
Install the CLI to call tools directly from terminal:
npm install -g @hypothesi/tauri-mcp-cli
tauri-mcp driver-session start --port 9223
tauri-mcp webview-screenshot --file screenshot.png
tauri-mcp webview-find-element --selector "button.submit"
tauri-mcp read-logs --type console
Add MCP Bridge Plugin to Tauri App
Automated Setup
Ask your AI assistant:
"Help me set up the Tauri MCP Bridge plugin"
The AI will examine your project, show required changes, and ask permission before modifying files.
Or use the /setup slash command in your AI assistant.
Manual Setup
1. Add dependency to Cargo.toml:
[dependencies]
tauri-plugin-mcp-bridge = "0.1"
2. Register plugin in src-tauri/src/lib.rs:
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_mcp_bridge::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
3. Add permissions to src-tauri/capabilities/default.json:
{
"permissions": [
"mcp-bridge:default"
]
}
4. (Optional) Initialize frontend bindings:
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
await listen('mcp-bridge://element-selected', (event) => {
console.log('Selected element:', event.payload);
});
const state = await invoke('plugin:mcp-bridge|get_backend_state');
console.log('App state:', state);
Key Tools Reference
Setup & Configuration
get_setup_instructions
Get instructions for setting up or updating the MCP Bridge plugin.
UI Automation
driver_session
Start, stop, or check status of automation session.
tauri-mcp driver-session start --port 9223
tauri-mcp driver-session status
tauri-mcp driver-session stop
Parameters:
action: "start" | "stop" | "status"
port: WebSocket port (default: 9223)
host: Host address (default: "localhost")
webview_screenshot
Capture screenshots of webview or specific elements.
tauri-mcp webview-screenshot --file screenshot.png
tauri-mcp webview-screenshot --selector ".main-content" --file content.png
tauri-mcp webview-screenshot --format base64
Parameters:
selector?: CSS selector for element to capture
format?: "png" | "base64" (default: "png")
file?: Output file path (CLI only)
windowId?: Target specific window
webview_find_element
Find elements using CSS selectors.
tauri-mcp webview-find-element --selector "button.submit"
tauri-mcp webview-find-element --selector "input[type='text']" --all
Returns:
{
"selector": "button.submit",
"found": true,
"count": 1,
"elements": [{
"tagName": "BUTTON",
"text": "Submit",
"visible": true,
"bounds": {"x": 100, "y": 200, "width": 80, "height": 40}
}]
}
Parameters:
selector: CSS selector
all?: Return all matches (default: false)
windowId?: Target specific window
webview_interact
Click, scroll, swipe, focus, or long-press elements.
tauri-mcp webview-interact --action click --selector "button#login"
tauri-mcp webview-interact --action scroll --selector ".content" --x 0 --y 100
tauri-mcp webview-interact --action swipe --direction up --duration 300
tauri-mcp webview-interact --action longPress --selector ".context-menu-trigger"
Parameters:
action: "click" | "scroll" | "swipe" | "focus" | "longPress"
selector?: CSS selector (required for click, scroll, focus, longPress)
x?, y?: Coordinates for scroll
direction?: "up" | "down" | "left" | "right" (for swipe)
duration?: Duration in ms (for swipe, longPress)
windowId?: Target specific window
webview_keyboard
Type text or send key events.
tauri-mcp webview-keyboard --action type --text "Hello, World!"
tauri-mcp webview-keyboard --action press --key Enter
tauri-mcp webview-keyboard --action press --key c --modifiers '["Control"]'
Parameters:
action: "type" | "press"
text?: Text to type (for type action)
key?: Key name (for press action)
modifiers?: Array of "Control" | "Shift" | "Alt" | "Meta"
windowId?: Target specific window
webview_wait_for
Wait for elements, text, or events.
tauri-mcp webview-wait-for --type element --selector ".loaded" --timeout 5000
tauri-mcp webview-wait-for --type text --text "Success"
tauri-mcp webview-wait-for --type event --eventName "data-loaded"
Parameters:
type: "element" | "text" | "event"
selector?: CSS selector (for element)
text?: Text to wait for
eventName?: Event name to listen for
timeout?: Timeout in ms (default: 5000)
windowId?: Target specific window
webview_execute_js
Execute JavaScript in webview.
tauri-mcp webview-execute-js --code "document.title"
tauri-mcp webview-execute-js --code "document.querySelector('.count').textContent"
Parameters:
code: JavaScript code to execute
windowId?: Target specific window
webview_dom_snapshot
Get structured accessibility tree snapshot.
tauri-mcp webview-dom-snapshot --selector ".main-content"
tauri-mcp webview-dom-snapshot --max-depth 3
Returns structured DOM tree with accessibility information.
Parameters:
selector?: Root selector (default: "body")
maxDepth?: Maximum tree depth
windowId?: Target specific window
webview_select_element
Visual element picker - user clicks element in app, returns metadata and screenshot.
tauri-mcp webview-select-element --timeout 30000
Process:
- App enters selection mode
- User hovers/clicks element
- Returns element metadata + screenshot with highlight
Parameters:
timeout?: Selection timeout in ms (default: 30000)
windowId?: Target specific window
webview_get_pointed_element
Get metadata for element user Alt+Shift+Clicked.
tauri-mcp webview-get-pointed-element
Returns most recently pointed element metadata.
manage_window
List windows, get info, or resize.
tauri-mcp manage-window --action list
tauri-mcp manage-window --action info --window-id "main"
tauri-mcp manage-window --action resize --window-id "main" --width 800 --height 600
Parameters:
action: "list" | "info" | "resize"
windowId?: Window ID (for info, resize)
width?, height?: Dimensions (for resize)
IPC & Plugin Tools
ipc_execute_command
Execute Tauri IPC commands.
tauri-mcp ipc-execute-command --command "get_app_version"
tauri-mcp ipc-execute-command --command "save_data" --args '{"key": "value"}'
Parameters:
command: Command name
args?: Command arguments (JSON object)
ipc_get_backend_state
Get app metadata and backend state.
tauri-mcp ipc-get-backend-state
Returns:
{
"metadata": {
"name": "my-app",
"version": "1.0.0",
"os": "macos",
"arch": "aarch64"
},
"capabilities": {
"windows": ["main"],
"commands": ["get_app_version", "save_data"]
}
}
ipc_monitor
Start or stop IPC monitoring.
tauri-mcp ipc-monitor --action start --events '["command", "event"]'
tauri-mcp ipc-monitor --action stop
Parameters:
action: "start" | "stop"
events?: Array of event types to capture
ipc_get_captured
Get captured IPC traffic.
tauri-mcp ipc-get-captured --clear
Parameters:
clear?: Clear captured events after reading (default: false)
ipc_emit_event
Emit custom events to Tauri app.
tauri-mcp ipc-emit-event --event "data-updated" --payload '{"id": 123}'
Parameters:
event: Event name
payload?: Event payload (any JSON value)
Logs
read_logs
Read console, Android, iOS, or system logs.
tauri-mcp read-logs --type console
tauri-mcp read-logs --type android --device "emulator-5554"
tauri-mcp read-logs --type ios --device "iPhone 15 Pro"
tauri-mcp read-logs --type system
Parameters:
type: "console" | "android" | "ios" | "system"
device?: Device ID (for android, ios)
follow?: Stream logs continuously
windowId?: Target specific window (for console logs)
Mobile Development
list_devices
List Android devices and iOS simulators.
tauri-mcp list-devices --platform android
tauri-mcp list-devices --platform ios
tauri-mcp list-devices --platform all
Returns:
{
"android": [
{"id": "emulator-5554", "name": "Pixel 7", "status": "booted"}
],
"ios": [
{"id": "...", "name": "iPhone 15 Pro", "status": "Booted"}
]
}
Configuration
MCP Server Config
If you manually configure (not using install-mcp), add to your AI assistant's MCP config:
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"tauri": {
"command": "npx",
"args": ["-y", "@hypothesi/tauri-mcp-server"]
}
}
}
Cursor (~/.cursor/config.json or similar):
{
"mcp": {
"servers": {
"tauri": {
"command": "npx",
"args": ["-y", "@hypothesi/tauri-mcp-server"]
}
}
}
}
Environment Variables
Set via MCP server config or CLI:
TAURI_MCP_PORT: Default WebSocket port (default: 9223)
TAURI_MCP_HOST: Default host (default: "localhost")
DEBUG: Enable debug logging (e.g., DEBUG=tauri-mcp:*)
Multi-Window Support
All webview tools accept optional windowId parameter:
const windows = await useMcpTool('manage_window', { action: 'list' });
await useMcpTool('webview_screenshot', {
windowId: 'settings',
file: 'settings.png'
});
Common Patterns
Debug Webview Errors
Use the /fix-webview-errors slash command, or manually:
const logs = await useMcpTool('read_logs', { type: 'console' });
const screenshot = await useMcpTool('webview_screenshot', {});
const dom = await useMcpTool('webview_dom_snapshot', {});
const result = await useMcpTool('webview_execute_js', {
code: 'window.lastError || "no errors"'
});
Visual Element Selection Workflow
Use /select slash command or:
const selection = await useMcpTool('webview_select_element', {
timeout: 30000
});
await useMcpTool('webview_interact', {
action: 'click',
selector: selection.selector
});
Monitor IPC Traffic
await useMcpTool('ipc_monitor', {
action: 'start',
events: ['command', 'event']
});
const traffic = await useMcpTool('ipc_get_captured', { clear: true });
Mobile Testing
const devices = await useMcpTool('list_devices', { platform: 'all' });
const logs = await useMcpTool('read_logs', {
type: 'android',
device: 'emulator-5554',
follow: true
});
Automated Testing Workflow
await useMcpTool('driver_session', { action: 'start', port: 9223 });
await useMcpTool('webview_wait_for', {
type: 'element',
selector: '.app-loaded',
timeout: 5000
});
await useMcpTool('webview_interact', {
action: 'click',
selector: 'input[name="username"]'
});
await useMcpTool('webview_keyboard', {
action: 'type',
text: 'testuser'
});
await useMcpTool('webview_interact', {
action: 'click',
selector: 'button[type="submit"]'
});
await useMcpTool('webview_wait_for', {
type: 'text',
text: 'Login successful'
});
const screenshot = await useMcpTool('webview_screenshot', {});
Troubleshooting
Connection Issues
Problem: Failed to connect to WebSocket
Solution:
ps aux | grep tauri
tauri-mcp driver-session status
tauri-mcp driver-session start --port 9224
Element Not Found
Problem: Element not found despite element being visible
Solution:
await useMcpTool('webview_wait_for', {
type: 'element',
selector: '.my-element',
timeout: 5000
});
const element = await useMcpTool('webview_select_element', {});
console.log('Correct selector:', element.selector);
const dom = await useMcpTool('webview_dom_snapshot', {});
Screenshots Empty or Black
Problem: Screenshots are blank
Solution:
await useMcpTool('webview_wait_for', {
type: 'element',
selector: 'body.loaded'
});
const windows = await useMcpTool('manage_window', { action: 'list' });
console.log('Windows:', windows);
await useMcpTool('webview_screenshot', {
windowId: 'main'
});
Permission Errors
Problem: Command not found: plugin:mcp-bridge|...
Solution:
{
"permissions": [
"mcp-bridge:default",
"mcp-bridge:allow-get-backend-state",
"mcp-bridge:allow-execute-command"
]
}
Mobile Logs Not Appearing
Problem: Android/iOS logs are empty
Solution:
adb devices
adb -s emulator-5554 logcat
xcrun simctl list | grep Booted
xcrun simctl spawn <device-id> log stream
Real-World Examples
E2E Test Automation
async function testLoginFlow() {
await useMcpTool('driver_session', { action: 'start' });
await useMcpTool('webview_interact', {
action: 'click',
selector: 'a[href="/login"]'
});
await useMcpTool('webview_keyboard', {
action: 'type',
text: 'user@example.com'
});
await useMcpTool('webview_keyboard', {
action: 'press',
key: 'Tab'
});
await useMcpTool('webview_keyboard', {
action: 'type',
text: 'password123'
});
await useMcpTool('webview_keyboard', {
action: 'press',
key: 'Enter'
});
await useMcpTool('webview_wait_for', {
type: 'element',
selector: '.dashboard',
timeout: 5000
});
const screenshot = await useMcpTool('webview_screenshot', {
file: 'dashboard.png'
});
console.log('✓ Login successful');
}
Debug Performance Issue
async function debugSlowRender() {
await useMcpTool('ipc_monitor', { action: 'start' });
await useMcpTool('webview_interact', {
action: 'click',
selector: '.load-data'
});
const logs = await useMcpTool('read_logs', {
type: 'console'
});
const traffic = await useMcpTool('ipc_get_captured', {});
console.log('IPC Commands:', traffic.commands.length);
console.log('Console Logs:', logs.length);
await useMcpTool('webview_screenshot', {
file: 'after-load.png'
});
}
Mobile Screenshot Testing
async function captureScreensOnAllDevices() {
const devices = await useMcpTool('list_devices', { platform: 'all' });
for (const device of devices.android) {
console.log(`Testing on ${device.name}...`);
await useMcpTool('webview_wait_for', {
type: 'element',
selector: '.app-ready',
timeout: 10000
});
await useMcpTool('webview_screenshot', {
file: `screenshots/${device.name.replace(/\s/g, '-')}.png`
});
const logs = await useMcpTool('read_logs', {
type: 'android',
device: device.id
});
console.log(`✓ Captured ${device.name}`);
}
}
Additional Resources