start_gui
Launch a web interface to manage Claude Code conversation sessions through your browser.
Instructions
Start the web GUI for session management and open it in browser
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| port | No | Port to run the web server on (default: 5173) | |
| open_browser | No | Whether to open browser automatically (default: true) | |
| restart | No | Restart the server if already running (default: false) |
Implementation Reference
- src/mcp/index.ts:195-272 (handler)Registration of the 'start_gui' MCP tool, including input schema with Zod validation and the inline asynchronous handler function that manages the web server instance (restart if requested, start via helper, return MCP-formatted response with URL or error).server.tool( 'start_gui', 'Start the web GUI for session management and open it in browser', { port: z.number().default(5173).describe('Port to run the web server on (default: 5173)'), open_browser: z .boolean() .default(true) .describe('Whether to open browser automatically (default: true)'), restart: z .boolean() .default(false) .describe('Restart the server if already running (default: false)'), }, async ({ port, open_browser, restart }) => { try { if (webServerInstance) { if (restart) { await stopWebServer(webServerInstance) webServerInstance = null } else { return { content: [ { type: 'text', text: JSON.stringify( { success: true, message: 'Web GUI is already running', url: `http://localhost:${port}`, }, null, 2 ), }, ], } } } webServerInstance = await startWebServer(port, open_browser) return { content: [ { type: 'text', text: JSON.stringify( { success: true, message: 'Web GUI started successfully', url: `http://localhost:${port}`, pid: process.pid, }, null, 2 ), }, ], } } catch (error) { return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: String(error), }, null, 2 ), }, ], } } } )
- src/server.ts:5-67 (helper)Helper functions to start and stop the web GUI server: computes path to built SvelteKit app, spawns Node process, waits for startup signal, opens browser cross-platform; stop sends SIGTERM to process. Used by the start_gui handler.const __dirname = path.dirname(fileURLToPath(import.meta.url)) // dist/web/index.js is the built SvelteKit server (adapter-node) const webServerPath = path.join(__dirname, 'web', 'index.js') interface WebServer { process: ChildProcess port: number } export async function startWebServer( port: number = 5173, openBrowser: boolean = true ): Promise<WebServer> { // Run the built SvelteKit server directly with Node const child = spawn('node', [webServerPath], { stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env, PORT: String(port) }, }) // Wait for server to start await new Promise<void>((resolve, reject) => { const timeout = setTimeout(() => reject(new Error('Server startup timeout')), 10000) child.stdout?.on('data', (data: Buffer) => { const output = data.toString() // SvelteKit adapter-node outputs "Listening on http://0.0.0.0:PORT" if ( output.includes('Listening on') || output.includes('localhost') || output.includes('Local:') ) { clearTimeout(timeout) resolve() } }) child.on('error', (err) => { clearTimeout(timeout) reject(err) }) child.on('exit', (code) => { if (code !== 0) { clearTimeout(timeout) reject(new Error(`Server exited with code ${code}`)) } }) }) // Open browser if requested if (openBrowser) { const url = `http://localhost:${port}` const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open' spawn(openCmd, [url], { stdio: 'ignore', detached: true }).unref() } return { process: child, port } } export async function stopWebServer(server: WebServer): Promise<void> { server.process.kill('SIGTERM') }