Skip to main content
Glama

flutter_run

Start a Flutter development session with hot reload enabled to run and test mobile applications during development.

Instructions

Start a Flutter development session (hot reload enabled)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cwdYesWorking directory (Flutter project root)
deviceIdNoTarget device ID
targetNoTarget dart file (e.g., lib/main.dart)
flavorNoBuild flavor
debugPortNoDebug port number

Implementation Reference

  • The handler function for 'flutter_run' tool. It validates input parameters using FlutterRunSchema, checks for existing sessions, constructs flutter run command with options (device, target, flavor, debugPort), spawns a detached child process, tracks the session in runningFlutterSessions map, sets up exit handler, and returns session details including ID and PID.
    handler: async (args: any) => { const validation = FlutterRunSchema.safeParse(args); if (!validation.success) { throw new Error(`Invalid request: ${validation.error.message}`); } const { cwd, deviceId, target, flavor, debugPort } = validation.data; // Validate that it's a Flutter project await validateFlutterProject(cwd); // Check if there's already a running session for this project const existingSession = Array.from(runningFlutterSessions.entries()).find( ([_, session]) => session.projectPath === cwd ); if (existingSession) { return { success: true, data: { sessionId: existingSession[0], pid: existingSession[1].pid, status: 'already_running', projectPath: cwd, deviceId: existingSession[1].deviceId, message: 'Flutter run session is already active for this project', }, }; } const flutter_args = ['run']; if (deviceId) { flutter_args.push('-d', deviceId); } if (target) { // Validate target path (must be .dart file) if (!target.endsWith('.dart')) { throw new Error(`Target must be a .dart file. Invalid target: ${target}`); } flutter_args.push('--target', target); } if (flavor) { flutter_args.push('--flavor', flavor); } if (debugPort) { flutter_args.push('--debug-port', debugPort.toString()); } // Start flutter run in background const flutterProcess = spawn('flutter', flutter_args, { cwd, detached: true, stdio: ['ignore', 'pipe', 'pipe'], }); const sessionId = `flutter_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // Track the process runningFlutterSessions.set(sessionId, { pid: flutterProcess.pid!, deviceId: deviceId || 'default', projectPath: cwd, }); // Handle process exit flutterProcess.on('exit', () => { runningFlutterSessions.delete(sessionId); }); // Unref to allow the parent process to exit flutterProcess.unref(); return { success: true, data: { sessionId, pid: flutterProcess.pid, status: 'started', projectPath: cwd, deviceId: deviceId || 'default', target: target || 'lib/main.dart', flavor, debugPort, }, }; }
  • Zod validation schema defining input parameters for flutter_run: cwd (required string), optional deviceId, target, flavor (strings), debugPort (number 1024-65535).
    const FlutterRunSchema = z.object({ cwd: z.string().min(1), deviceId: z.string().optional(), target: z.string().optional(), flavor: z.string().optional(), debugPort: z.number().min(1024).max(65535).optional(), });
  • Registration of the 'flutter_run' tool in the createFlutterTools factory function's tools Map, including name, description, inputSchema (JSON schema equivalent), and reference to the handler function.
    tools.set('flutter_run', { name: 'flutter_run', description: 'Start a Flutter development session (hot reload enabled)', inputSchema: { type: 'object', properties: { cwd: { type: 'string', minLength: 1, description: 'Working directory (Flutter project root)' }, deviceId: { type: 'string', description: 'Target device ID' }, target: { type: 'string', description: 'Target dart file (e.g., lib/main.dart)' }, flavor: { type: 'string', description: 'Build flavor' }, debugPort: { type: 'number', minimum: 1024, maximum: 65535, description: 'Debug port number' } }, required: ['cwd'] }, handler: async (args: any) => { const validation = FlutterRunSchema.safeParse(args); if (!validation.success) { throw new Error(`Invalid request: ${validation.error.message}`); } const { cwd, deviceId, target, flavor, debugPort } = validation.data; // Validate that it's a Flutter project await validateFlutterProject(cwd); // Check if there's already a running session for this project const existingSession = Array.from(runningFlutterSessions.entries()).find( ([_, session]) => session.projectPath === cwd ); if (existingSession) { return { success: true, data: { sessionId: existingSession[0], pid: existingSession[1].pid, status: 'already_running', projectPath: cwd, deviceId: existingSession[1].deviceId, message: 'Flutter run session is already active for this project', }, }; } const flutter_args = ['run']; if (deviceId) { flutter_args.push('-d', deviceId); } if (target) { // Validate target path (must be .dart file) if (!target.endsWith('.dart')) { throw new Error(`Target must be a .dart file. Invalid target: ${target}`); } flutter_args.push('--target', target); } if (flavor) { flutter_args.push('--flavor', flavor); } if (debugPort) { flutter_args.push('--debug-port', debugPort.toString()); } // Start flutter run in background const flutterProcess = spawn('flutter', flutter_args, { cwd, detached: true, stdio: ['ignore', 'pipe', 'pipe'], }); const sessionId = `flutter_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // Track the process runningFlutterSessions.set(sessionId, { pid: flutterProcess.pid!, deviceId: deviceId || 'default', projectPath: cwd, }); // Handle process exit flutterProcess.on('exit', () => { runningFlutterSessions.delete(sessionId); }); // Unref to allow the parent process to exit flutterProcess.unref(); return { success: true, data: { sessionId, pid: flutterProcess.pid, status: 'started', projectPath: cwd, deviceId: deviceId || 'default', target: target || 'lib/main.dart', flavor, debugPort, }, }; } });
  • Exported Zod schema for FlutterRun parameters (shared types, slightly less constrained than the implementation schema).
    export const FlutterRunSchema = z.object({ cwd: z.string(), deviceId: z.string().optional(), target: z.string().optional(), flavor: z.string().optional(), debugPort: z.number().optional(), });
  • Helper function to validate that the provided cwd is a valid Flutter project by checking for pubspec.yaml with flutter section. Called in the handler.
    const validateFlutterProject = async (cwd: string): Promise<void> => { const pubspecPath = path.join(cwd, 'pubspec.yaml'); try { await fs.access(pubspecPath); const pubspecContent = await fs.readFile(pubspecPath, 'utf8'); if (!pubspecContent.includes('flutter:')) { throw new Error(`Directory does not appear to be a Flutter project. No flutter section found in ${pubspecPath}`); } } catch { throw new Error(`pubspec.yaml not found. Flutter project must contain pubspec.yaml at: ${pubspecPath}`); } };

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/cristianoaredes/mcp-mobile-server'

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