Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,72 @@ await use_mcp_tool("tauri-mcp", "send_keyboard_input", {
- **Windows** - Full support with native window APIs
- **Linux** - X11 support (Wayland in progress)

### macOS WebView Debugging

On macOS, WKWebView doesn't expose Chrome DevTools Protocol (CDP) like WebView2 on Windows or WebKitGTK on Linux. This means some debugging tools (`execute_js`, screenshots via CDP) require an alternative approach.

#### Solution: tauri-plugin-native-webview

For full WebView debugging support on macOS, Tauri apps can install the `tauri-plugin-native-webview` plugin:

```toml
# In the Tauri app's Cargo.toml
[dependencies]
tauri-plugin-native-webview = "0.1"
```

Then register the plugin:

```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_native_webview::init())
.run(tauri::generate_context!())
.expect("failed to run app");
}
```

#### Using Plugin Commands via MCP

Once installed, use `call_ipc_command` to access native WebView capabilities:

```javascript
// Take screenshot (works even when window is hidden!)
await use_mcp_tool("tauri-mcp", "call_ipc_command", {
process_id: "uuid-here",
command_name: "plugin:native-webview|snapshot",
args: {}
});
// Returns: { data: "base64png...", width: 1920, height: 1080 }

// Execute JS and get return value
await use_mcp_tool("tauri-mcp", "call_ipc_command", {
process_id: "uuid-here",
command_name: "plugin:native-webview|eval_js",
args: { code: "return document.title" }
});
// Returns: { success: true, result: "\"Page Title\"" }

// Get WebView debug info
await use_mcp_tool("tauri-mcp", "call_ipc_command", {
process_id: "uuid-here",
command_name: "plugin:native-webview|debug_info",
args: {}
});
// Returns: { windowTitle, url, isVisible, size, ... }
```

#### Plugin Advantages

| Feature | CDP (Windows/Linux) | Native Plugin (macOS) |
|---------|---------------------|----------------------|
| Screenshot when hidden | ❌ Requires visible window | ✅ Works when hidden |
| JS with return values | ✅ Via Runtime.evaluate | ✅ Via IPC callback |
| Window state | ✅ Via Page APIs | ✅ Via Tauri APIs |
| Setup required | DevTools port flag | Plugin installation |

The native plugin uses `WKWebView.takeSnapshotWithConfiguration:` which captures the actual WebView content even when the window is minimized or occluded - perfect for CI/CD pipelines and automated testing.

## Development

### Building
Expand Down
43 changes: 41 additions & 2 deletions src/tools/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,46 @@ impl DebugTools {
}
}
}

Err(TauriMcpError::WebDriverError("No debug port found".to_string()))

// Provide helpful error message with macOS guidance
#[cfg(target_os = "macos")]
{
Err(TauriMcpError::WebDriverError(
"No Chrome DevTools Protocol port found. On macOS, WKWebView doesn't expose CDP. \
For WebView debugging, install tauri-plugin-native-webview in your Tauri app and use \
call_ipc_command with 'plugin:native-webview|eval_js' or 'plugin:native-webview|snapshot'. \
See: https://github.com/AHornerr/tauri-mcp#macos-webview-debugging".to_string()
))
}

#[cfg(not(target_os = "macos"))]
{
Err(TauriMcpError::WebDriverError(
"No debug port found. Ensure the Tauri app was launched with --remote-debugging-port \
or that DevTools is enabled.".to_string()
))
}
}

/// Check if the native webview plugin is likely available
///
/// This is a hint - actual availability depends on the Tauri app having
/// tauri-plugin-native-webview installed.
pub fn suggest_native_plugin(&self) -> Option<&'static str> {
#[cfg(target_os = "macos")]
{
Some(
"On macOS, consider using tauri-plugin-native-webview for WebView debugging. \
Use call_ipc_command with these commands:\n\
- 'plugin:native-webview|snapshot' - Capture WebView (works when hidden)\n\
- 'plugin:native-webview|eval_js' - Execute JS with return values\n\
- 'plugin:native-webview|debug_info' - Get window state"
)
}

#[cfg(not(target_os = "macos"))]
{
None
}
}
}
27 changes: 23 additions & 4 deletions src/tools/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,34 @@ impl WindowManager {
Self {}
}

/// Take a screenshot of the screen
///
/// Note: This uses screen capture which requires the window to be visible.
/// On macOS, for WebView screenshots that work when the window is hidden,
/// use `call_ipc_command` with `plugin:native-webview|snapshot` if the
/// Tauri app has tauri-plugin-native-webview installed.
pub async fn take_screenshot(&self, process_id: &str, output_path: Option<PathBuf>) -> Result<String> {
info!("Taking screenshot for process: {}", process_id);

let screens = Screen::all().map_err(|e| TauriMcpError::ScreenshotError(e.to_string()))?;


let screens = Screen::all().map_err(|e| {
#[cfg(target_os = "macos")]
{
TauriMcpError::ScreenshotError(format!(
"{}. Tip: For WebView screenshots on macOS (even when hidden), use \
call_ipc_command with 'plugin:native-webview|snapshot' if the app has \
tauri-plugin-native-webview installed.", e
))
}
#[cfg(not(target_os = "macos"))]
{
TauriMcpError::ScreenshotError(e.to_string())
}
})?;

if screens.is_empty() {
return Err(TauriMcpError::ScreenshotError("No screens found".to_string()));
}

let screen = &screens[0];
let image = screen.capture().map_err(|e| TauriMcpError::ScreenshotError(e.to_string()))?;

Expand Down