expo.start
Launch the Expo/Metro development server for React Native applications, with optional cache clearing to resolve build issues.
Instructions
Start the Expo/Metro development server
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| clearCache | No | Clear Metro cache before starting. |
Implementation Reference
- src/expo/expo.ts:36-153 (handler)Core handler function that starts the Expo/Metro development server by executing the configured start command, managing the child process, parsing output for readiness detection, and updating state.export async function startExpo(options: ExpoStartOptions = {}): Promise<ExpoStartResult> { logger.info("expo", "Starting Expo/Metro..."); if (expoProcess) { const status = detectMetroReady(outputBuffer); if (status.ready) { logger.info("expo", "Expo is already running"); return { started: true, metroUrl: status.url, message: "Expo is already running", }; } // Process exists but not ready - kill it and restart await stopExpo(); } if (!hasConfig()) { throw createError("CONFIG_NOT_FOUND", "Configuration required to start Expo"); } const config = getConfig(); stateManager.updateExpo({ state: "starting" }); // Build command let command = config.expo.startCommand; if (options.clearCache) { command += ` ${config.expo.clearCacheFlag}`; } if (options.port) { command += ` --port ${options.port}`; } const [cmd, ...args] = command.split(" ").filter(Boolean); logger.info("expo", `Executing: ${command}`, { cwd: config.projectPath }); try { // Start Expo process expoProcess = execa(cmd, args, { cwd: config.projectPath, reject: false, env: { ...process.env, FORCE_COLOR: "1", CI: "false", // Ensure interactive mode }, }); startedAt = new Date().toISOString(); outputBuffer = ""; // Handle stdout expoProcess.stdout?.on("data", (chunk: Buffer) => { const text = chunk.toString(); outputBuffer += text; processExpoOutput(text, "stdout"); // Check for Metro ready const status = detectMetroReady(outputBuffer); if (status.ready && stateManager.getExpo().state !== "running") { stateManager.updateExpo({ state: "running", metroUrl: status.url, processId: expoProcess?.pid, }); logger.info("expo", `Metro ready at ${status.url}`); } }); // Handle stderr expoProcess.stderr?.on("data", (chunk: Buffer) => { const text = chunk.toString(); outputBuffer += text; processExpoOutput(text, "stderr"); // Check for errors if (isMetroError(text)) { stateManager.updateExpo({ state: "crashed" }); logger.error("expo", "Metro encountered an error", { output: text }); } }); // Handle process exit expoProcess.on("exit", (code: number | null) => { logger.info("expo", `Expo process exited with code ${code}`); if (code !== 0 && code !== null) { stateManager.updateExpo({ state: "crashed" }); } else { stateManager.updateExpo({ state: "stopped" }); } expoProcess = null; }); // Wait for Metro to be ready (with timeout) const waitResult = await waitForMetroReady(30000); if (waitResult.ready) { return { started: true, metroUrl: waitResult.url, message: "Expo started successfully", }; } return { started: true, message: "Expo started but Metro readiness not confirmed yet", }; } catch (error) { stateManager.updateExpo({ state: "crashed" }); throw createError("EXPO_START_FAILED", "Failed to start Expo", { details: error instanceof Error ? error.message : "Unknown error", }); } }
- src/mcp/schemas.ts:37-39 (schema)Zod schema defining the input parameters for the expo.start tool, including optional clearCache flag.export const ExpoStartInputSchema = z.object({ clearCache: z.boolean().optional().default(false).describe("Clear Metro cache before starting."), });
- src/mcp/server.ts:274-295 (registration)Registers the 'expo.start' tool in the MCP server, linking the schema and delegating to the startExpo handler function.server.tool( "expo.start", "Start the Expo/Metro development server", ExpoStartInputSchema.shape, async (args) => { try { const result = await startExpo({ clearCache: args.clearCache, }); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return handleToolError(error); } } );