driver_session
Start, stop, or check status of WebSocket sessions to control Tauri app automation. Required before using webview and IPC tools.
Instructions
[Tauri Apps Only] Start/stop automation session to connect to a RUNNING Tauri app. Supports multiple concurrent app connections - each app runs on a unique port. The most recently connected app becomes the "default" app used when no appIdentifier is specified. Use action "status" to check connection state: returns single app format when 1 app connected, or array format with "isDefault" indicator when multiple apps connected. Action "stop" without appIdentifier stops ALL sessions; with appIdentifier stops only that app. The identifier field (e.g., "com.example.myapp") uniquely identifies each app. REQUIRED before using other webview_* or ipc_* tools. Connects via WebSocket to the MCP Bridge plugin in the Tauri app. For browser automation, use Chrome DevTools MCP instead. For Electron apps, this tool will NOT work.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Action to perform: start or stop the session, or check status | |
| host | No | Host address to connect to (e.g., 192.168.1.100). Falls back to MCP_BRIDGE_HOST or TAURI_DEV_HOST env vars | |
| port | No | Port to connect to (default: 9223) | |
| appIdentifier | No | App identifier (port number or bundle ID) to stop. Only used with action "stop". If omitted, stops all sessions. |
Implementation Reference
- packages/mcp-server/src/tools-registry.ts:154-182 (registration)Registration of the 'driver_session' tool in the TOOLS registry. Defines name, description, category, schema reference, and handler. The handler parses args via ManageDriverSessionSchema then delegates to manageDriverSession().
{ name: 'driver_session', description: '[Tauri Apps Only] Start/stop automation session to connect to a RUNNING Tauri app. ' + 'Supports multiple concurrent app connections - each app runs on a unique port. ' + 'The most recently connected app becomes the "default" app used when no appIdentifier is specified. ' + 'Use action "status" to check connection state: returns single app format when 1 app connected, ' + 'or array format with "isDefault" indicator when multiple apps connected. ' + 'Action "stop" without appIdentifier stops ALL sessions; with appIdentifier stops only that app. ' + 'The identifier field (e.g., "com.example.myapp") uniquely identifies each app. ' + 'REQUIRED before using other webview_* or ipc_* tools. ' + 'Connects via WebSocket to the MCP Bridge plugin in the Tauri app. ' + 'For browser automation, use Chrome DevTools MCP instead. ' + 'For Electron apps, this tool will NOT work.', category: TOOL_CATEGORIES.UI_AUTOMATION, schema: ManageDriverSessionSchema, annotations: { title: 'Manage Tauri Session', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, handler: async (args) => { const parsed = ManageDriverSessionSchema.parse(args); return await manageDriverSession(parsed.action, parsed.host, parsed.port, parsed.appIdentifier); }, }, - The manageDriverSession function - the core handler implementation that dispatches to handleStartAction, handleStopAction, or handleStatusAction based on the 'action' parameter.
export async function manageDriverSession( action: 'start' | 'stop' | 'status', host?: string, port?: number, appIdentifier?: string | number ): Promise<string> { switch (action) { case 'status': { return handleStatusAction(); } case 'start': { return handleStartAction(host, port); } case 'stop': { return handleStopAction(appIdentifier); } default: { return handleStopAction(appIdentifier); } } } - ManageDriverSessionSchema - Zod schema defining the input for driver_session: action (enum start/stop/status), optional host, optional port, and optional appIdentifier for targeted stop.
export const ManageDriverSessionSchema = z.object({ action: z.enum([ 'start', 'stop', 'status' ]).describe('Action to perform: start or stop the session, or check status'), host: z.string().optional().describe( 'Host address to connect to (e.g., 192.168.1.100). Falls back to MCP_BRIDGE_HOST or TAURI_DEV_HOST env vars' ), port: z.number().optional().describe('Port to connect to (default: 9223)'), appIdentifier: z.union([ z.string(), z.number() ]).optional().describe( 'App identifier (port number or bundle ID) to stop. Only used with action "stop". If omitted, stops all sessions.' ), }); - handleStatusAction helper - returns JSON with connection state, session info, and multi-app support.
async function handleStatusAction(): Promise<string> { if (activeSessions.size === 0) { return JSON.stringify({ connected: false, app: null, identifier: null, host: null, port: null, }); } if (activeSessions.size === 1) { const session = activeSessions.values().next().value; if (!session) { return JSON.stringify({ connected: false, app: null, identifier: null, host: null, port: null, }); } return JSON.stringify({ connected: true, app: session.name, identifier: session.identifier, host: session.host, port: session.port, }); } const apps = Array.from(activeSessions.values()).map((session) => { return { name: session.name, identifier: session.identifier, host: session.host, port: session.port, isDefault: session.port === defaultPort, }; }); return JSON.stringify({ connected: true, apps, totalCount: apps.length, defaultPort, }); } - handleStartAction helper - attempts to connect to Tauri app via localhost or configured host, auto-discovers ports, creates PluginClient, and stores session info.
async function handleStartAction(host?: string, port?: number): Promise<string> { const configuredHost = host ?? getDefaultHost(); const configuredPort = port ?? getDefaultPort(); if (activeSessions.has(configuredPort)) { return `Already connected to app on port ${configuredPort}`; } let connectedSession: { name: string; host: string; port: number } | null = null; if (configuredHost !== 'localhost' && configuredHost !== '127.0.0.1') { try { connectedSession = await tryConnect('localhost', configuredPort); } catch{ // ignore } } if (!connectedSession) { try { connectedSession = await tryConnect(configuredHost, configuredPort); } catch{ // ignore } } if (!connectedSession) { const localhostDiscovery = getAppDiscovery('localhost'); const firstApp = await localhostDiscovery.getFirstAvailableApp(); if (firstApp) { try { connectedSession = await tryConnect('localhost', firstApp.port); } catch{ // ignore } } } if (!connectedSession) { return `Session start failed - no Tauri app found at localhost or ${configuredHost}:${configuredPort}`; } const client = new PluginClient(connectedSession.host, connectedSession.port); await client.connect(); const identifier = await fetchAppIdentifier(client); const sessionInfo: SessionInfo = { name: connectedSession.name, identifier, host: connectedSession.host, port: connectedSession.port, client, connected: true, }; activeSessions.set(connectedSession.port, sessionInfo); defaultPort = connectedSession.port; sessionLogger.info( `Session started: ${sessionInfo.name} (${sessionInfo.host}:${sessionInfo.port}) [DEFAULT]` ); return `Session started with app: ${sessionInfo.name} (${sessionInfo.host}:${sessionInfo.port}) [DEFAULT]`; }