# ๐Ÿ’ก Concrete Implementation Examples ## Overview This document provides practical, working examples of the FastMCP ESPTool server components and workflows. Each example demonstrates real-world usage patterns with actual code implementations. ## ๐Ÿ”ง Core Component Implementation ### 1. ChipControl Component - Complete Implementation ```python # src/mcp_esptool_server/components/chip_control.py import asyncio import time from typing import Dict, List, Optional, Any from pathlib import Path from fastmcp import FastMCP, Context from esptool.cmds import detect_chip, run_stub, reset_chip, load_ram, run from esptool.loader import ESPLoader from ..middleware.esptool_middleware import ESPToolMiddleware from ..config import ESPToolServerConfig class ChipControl: """ESP chip detection, connection, and control operations""" def __init__(self, app: FastMCP, config: ESPToolServerConfig): self.app = app self.config = config self.active_connections: Dict[str, ESPLoader] = {} self.register_tools() self.register_resources() def register_tools(self): """Register chip control tools with FastMCP""" @self.app.tool("esp_detect_chip") async def detect_esp_chip( context: Context, port: str, baud: int = 115200, connect_attempts: int = 7, trace_enabled: bool = False ) -> Dict[str, Any]: """ Auto-detect ESP chip type and return comprehensive information Args: port: Serial port path (e.g., '/dev/ttyUSB0', 'COM3') baud: Connection baud rate (default: 115200) connect_attempts: Number of connection retry attempts trace_enabled: Enable detailed connection tracing Returns: Dict with chip info: type, features, MAC address, flash size, etc. """ operation_id = f"detect_{port}_{int(time.time())}" # Use middleware for enhanced logging and user interaction with ESPToolMiddleware(context, operation_id) as middleware: try: await middleware.log_info(f"๐Ÿ” Detecting ESP chip on {port}...") # Attempt chip detection with progress tracking with detect_chip( port, baud=baud, connect_attempts=connect_attempts, trace_enabled=trace_enabled ) as esp: await middleware.log_success(f"โœ… Detected: {esp.get_chip_description()}") # Gather comprehensive chip information chip_info = { "success": True, "port": port, "chip_type": esp.get_chip_description(), "chip_revision": esp.get_chip_revision(), "features": esp.get_chip_features(), "mac_address": esp.read_mac().hex(':'), "crystal_freq": esp.get_crystal_freq(), "stub_supported": hasattr(esp, 'STUB_SUPPORTED') and esp.STUB_SUPPORTED, "detection_time": time.time() } # Try to get flash information safely try: chip_info["flash_size"] = esp.flash_size chip_info["flash_id"] = esp.flash_id() except Exception as flash_error: await middleware.log_warning(f"Could not read flash info: {flash_error}") chip_info["flash_size"] = "Unknown" chip_info["flash_id"] = None # Store connection for reuse self.active_connections[port] = esp await middleware.log_info("๐Ÿ“‹ Chip detection completed successfully") return chip_info except Exception as e: error_msg = f"Failed to detect chip on {port}: {str(e)}" await middleware.log_error(error_msg) return { "success": False, "error": error_msg, "port": port, "suggestions": self._generate_troubleshooting_suggestions(str(e)) } @self.app.tool("esp_connect_advanced") async def connect_with_strategies( context: Context, port: str, enable_stub: bool = True, high_speed: bool = True, reset_strategy: str = "auto" ) -> str: """ Connect to ESP chip with multiple fallback strategies and optimizations Args: port: Serial port path enable_stub: Whether to load the flasher stub for better performance high_speed: Attempt high-speed connection first (460800 baud) reset_strategy: Reset strategy ('auto', 'hard', 'soft', 'none') Returns: Connection status and optimization details """ operation_id = f"connect_{port}_{int(time.time())}" with ESPToolMiddleware(context, operation_id) as middleware: # Define connection strategies in order of preference strategies = [ { 'name': 'High-speed with auto-reset', 'baud': 460800 if high_speed else 115200, 'connect_mode': 'default-reset' }, { 'name': 'Standard with USB reset', 'baud': 115200, 'connect_mode': 'usb-reset' }, { 'name': 'Safe mode with manual reset', 'baud': 115200, 'connect_mode': 'manual-reset' } ] for i, strategy in enumerate(strategies, 1): try: await middleware.log_info(f"๐Ÿ”„ Trying strategy {i}: {strategy['name']}") with detect_chip(port, **{k: v for k, v in strategy.items() if k != 'name'}) as esp: chip_description = esp.get_chip_description() # Apply stub flasher if requested and supported if enable_stub and hasattr(esp, 'STUB_SUPPORTED') and esp.STUB_SUPPORTED: try: esp = run_stub(esp) await middleware.log_success( f"โœ… Connected to {chip_description} with stub flasher (strategy {i})" ) performance_note = " - Enhanced performance mode enabled" except Exception as stub_error: await middleware.log_warning(f"Stub flasher failed: {stub_error}") performance_note = " - Using ROM bootloader" else: performance_note = " - Stub flasher not available" # Store successful connection self.active_connections[port] = esp return f"โœ… Connected to {chip_description} (strategy {i}){performance_note}" except Exception as e: await middleware.log_warning(f"Strategy {i} failed: {str(e)}") continue # All strategies failed error_msg = f"โŒ Failed to connect to {port} with all {len(strategies)} strategies" await middleware.log_error(error_msg) return error_msg + "\n๐Ÿ’ก Try checking physical connections and port permissions" @self.app.tool("esp_load_test_firmware") async def load_firmware_to_ram( context: Context, port: str, firmware_path: str, auto_run: bool = True ) -> str: """ Load and optionally execute firmware in RAM for testing (no flash wear) This is perfect for rapid prototyping and testing without wearing out flash memory. Args: port: Serial port path firmware_path: Path to firmware binary file auto_run: Automatically execute firmware after loading Returns: Loading and execution status """ operation_id = f"ram_load_{port}_{int(time.time())}" with ESPToolMiddleware(context, operation_id) as middleware: try: # Validate firmware file firmware_file = Path(firmware_path) if not firmware_file.exists(): return f"โŒ Firmware file not found: {firmware_path}" file_size = firmware_file.stat().st_size await middleware.log_info(f"๐Ÿ“ Loading {firmware_file.name} ({file_size} bytes) to RAM...") # Connect to chip (reuse existing connection if available) if port in self.active_connections: esp = self.active_connections[port] await middleware.log_info("๐Ÿ”— Using existing connection") else: esp = detect_chip(port) await middleware.log_info(f"๐Ÿ”— Connected to {esp.get_chip_description()}") # Load firmware to RAM await middleware.update_progress(0, "Loading firmware to RAM...") load_ram(esp, str(firmware_file)) await middleware.update_progress(80, "Firmware loaded to RAM") result_msg = f"โœ… Firmware loaded to RAM from {firmware_path}" # Execute if requested if auto_run: await middleware.update_progress(90, "Executing firmware...") run(esp) result_msg += "\n๐Ÿš€ Firmware execution started" await middleware.log_success("Firmware running from RAM - no flash wear!") else: result_msg += "\n๐Ÿ’ก Use esp_run_firmware to execute" await middleware.update_progress(100, "Operation completed") return result_msg except Exception as e: error_msg = f"โŒ Failed to load firmware to RAM: {str(e)}" await middleware.log_error(error_msg) return error_msg @self.app.tool("esp_reset_advanced") async def reset_chip_advanced( context: Context, port: str, reset_mode: str = "hard-reset", delay_ms: int = 100 ) -> str: """ Reset ESP chip with specific reset mode and timing control Args: port: Serial port path reset_mode: Reset type ('hard-reset', 'soft-reset', 'no-reset') delay_ms: Delay after reset in milliseconds Returns: Reset operation status """ operation_id = f"reset_{port}_{int(time.time())}" valid_modes = ['hard-reset', 'soft-reset', 'no-reset'] if reset_mode not in valid_modes: return f"โŒ Invalid reset mode '{reset_mode}'. Valid modes: {', '.join(valid_modes)}" with ESPToolMiddleware(context, operation_id) as middleware: try: # Get confirmation for destructive resets if reset_mode == 'hard-reset' and middleware.supports_elicitation: confirmed = await middleware.request_confirmation( f"๐Ÿ”„ About to perform {reset_mode} on {port}. Continue?" ) if not confirmed: return "โŒ Reset cancelled by user" await middleware.log_info(f"๐Ÿ”„ Performing {reset_mode} on {port}...") # Use existing connection or create new one if port in self.active_connections: esp = self.active_connections[port] else: esp = detect_chip(port) # Perform reset reset_chip(esp, reset_mode) # Wait for specified delay if delay_ms > 0: await asyncio.sleep(delay_ms / 1000.0) await middleware.log_info(f"โฑ๏ธ Waited {delay_ms}ms for reset to complete") await middleware.log_success(f"โœ… {reset_mode} completed on {port}") return f"โœ… Chip reset using {reset_mode} mode" except Exception as e: error_msg = f"โŒ Reset failed: {str(e)}" await middleware.log_error(error_msg) return error_msg def register_resources(self): """Register MCP resources for real-time chip information""" @self.app.resource("esp://chips") async def list_connected_chips() -> str: """List all connected ESP chips with basic information""" chips = [] # Scan common ports for ESP devices common_ports = [ '/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB2', '/dev/ttyACM0', '/dev/ttyACM1', 'COM1', 'COM2', 'COM3', 'COM4', 'COM5' ] for port in common_ports: try: with detect_chip(port, connect_attempts=1) as esp: chips.append({ "port": port, "chip_type": esp.get_chip_description(), "status": "connected", "last_seen": time.time() }) except: # Port not available or no chip continue return { "connected_chips": chips, "total_count": len(chips), "scan_time": time.time() } @self.app.resource("esp://chip/{port}") async def chip_status(port: str) -> str: """Get detailed status for specific chip""" if port in self.active_connections: esp = self.active_connections[port] return { "port": port, "connected": True, "chip_type": esp.get_chip_description(), "features": esp.get_chip_features(), "connection_time": getattr(esp, '_connection_time', time.time()) } else: return { "port": port, "connected": False, "error": "No active connection" } def _generate_troubleshooting_suggestions(self, error_message: str) -> List[str]: """Generate helpful troubleshooting suggestions based on error""" suggestions = [] error_lower = error_message.lower() if 'permission denied' in error_lower: suggestions.extend([ "Add user to dialout group: sudo usermod -a -G dialout $USER", "Check port permissions: ls -l /dev/ttyUSB*", "Try running with sudo (not recommended for production)" ]) if 'device or resource busy' in error_lower: suggestions.extend([ "Close other programs using the serial port (Arduino IDE, screen, etc.)", "Check for zombie processes: ps aux | grep tty", "Disconnect and reconnect the USB cable" ]) if 'no such file or directory' in error_lower: suggestions.extend([ "Check if device is connected: lsusb | grep -i esp", "Try different USB ports", "Check cable quality (some cables are power-only)" ]) if not suggestions: suggestions = [ "Check physical USB connection", "Verify correct port name", "Try different baud rates", "Check ESP32 boot mode (GPIO0 to GND for download mode)" ] return suggestions ``` ## ๐Ÿ”ฅ Middleware Integration Example ### 2. ESPTool Middleware - Production Implementation ```python # src/mcp_esptool_server/middleware/esptool_middleware.py import asyncio import re import time from contextlib import asynccontextmanager from typing import Dict, Any, Optional, List from fastmcp import Context from esptool.logger import log from .logger_interceptor import LoggerInterceptor class ESPToolMiddleware(LoggerInterceptor): """Production-ready ESPTool middleware with comprehensive MCP integration""" def __init__(self, context: Context, operation_id: str): super().__init__(context, operation_id) self.original_logger = None self.operation_start_time = time.time() self.progress_history: List[Dict] = [] self.user_confirmations: Dict[str, bool] = {} @asynccontextmanager async def activate(self): """Context manager for middleware lifecycle""" try: await self._initialize_middleware() yield self finally: await self._cleanup_middleware() async def _initialize_middleware(self): """Initialize middleware and replace esptool logger""" # Store original logger self.original_logger = log.get_logger() # Create and install MCP-aware logger mcp_logger = MCPEsptoolLogger(self) log.set_logger(mcp_logger) await self.log_info(f"๐Ÿ”ง Middleware activated for operation: {self.operation_id}") async def _cleanup_middleware(self): """Restore original logger and cleanup""" if self.original_logger: log.set_logger(self.original_logger) operation_duration = time.time() - self.operation_start_time await self.log_info(f"โฑ๏ธ Operation completed in {operation_duration:.2f}s") # Enhanced logging methods with emoji and structure async def log_info(self, message: str) -> None: """Log informational message""" if self.capabilities.get('logging', False): await self.context.log(level='info', message=message) async def log_success(self, message: str) -> None: """Log success message with distinctive formatting""" if self.capabilities.get('logging', False): await self.context.log(level='info', message=f"โœ… {message}") async def log_warning(self, message: str) -> None: """Log warning message""" if self.capabilities.get('logging', False): await self.context.log(level='warning', message=f"โš ๏ธ {message}") async def log_error(self, message: str) -> None: """Log error message""" if self.capabilities.get('logging', False): await self.context.log(level='error', message=f"โŒ {message}") async def update_progress(self, percentage: float, message: str = "") -> None: """Update operation progress with MCP progress API""" if self.capabilities.get('progress', False): try: await self.context.progress( operation_id=self.operation_id, progress=percentage, total=100, current=int(percentage), message=message ) # Store progress history for analysis self.progress_history.append({ 'timestamp': time.time(), 'percentage': percentage, 'message': message }) except Exception as e: await self.log_warning(f"Progress update failed: {e}") async def request_confirmation(self, prompt: str, default: bool = True) -> bool: """Request user confirmation with caching""" # Check cache first if prompt in self.user_confirmations: return self.user_confirmations[prompt] if self.capabilities.get('elicitation', False): try: response = await self.context.request_user_input( prompt=prompt, input_type="confirmation", additional_data={'default': default} ) confirmed = response.get('confirmed', default) self.user_confirmations[prompt] = confirmed return confirmed except Exception as e: await self.log_warning(f"User confirmation failed: {e}") return default else: # No elicitation support, use default return default def requires_confirmation(self, operation: str) -> bool: """Determine if operation requires user confirmation""" critical_operations = [ 'erase_flash', 'burn_efuse', 'enable_secure_boot', 'enable_flash_encryption', 'factory_reset', 'write_efuse' ] return any(critical_op in operation.lower() for critical_op in critical_operations) class MCPEsptoolLogger: """Custom esptool logger that forwards to MCP middleware""" def __init__(self, middleware: ESPToolMiddleware): self.middleware = middleware self.verbosity = 1 def print(self, message="", *args, **kwargs): """Handle general print messages""" formatted_msg = self._format_message(message, *args) asyncio.create_task(self.middleware.log_info(formatted_msg)) def note(self, message): """Handle note messages""" asyncio.create_task(self.middleware.log_info(f"๐Ÿ“‹ {message}")) def warning(self, message): """Handle warning messages""" asyncio.create_task(self.middleware.log_warning(message)) def error(self, message): """Handle error messages""" asyncio.create_task(self.middleware.log_error(message)) def stage(self, message="", finish=False): """Handle stage transitions with potential user interaction""" if finish: asyncio.create_task(self.middleware.log_success(f"Completed: {message}")) elif message: asyncio.create_task(self._handle_stage_start(message)) async def _handle_stage_start(self, stage_message: str): """Handle stage start with potential user interaction""" await self.middleware.log_info(f"๐Ÿ”„ Starting: {stage_message}") # Check if this stage requires confirmation if self.middleware.requires_confirmation(stage_message): confirmed = await self.middleware.request_confirmation( f"๐Ÿค” About to: {stage_message}. Continue?" ) if not confirmed: raise Exception(f"Operation cancelled by user: {stage_message}") def progress_bar(self, cur_iter, total_iters, prefix="", suffix="", bar_length=30): """Handle progress bar updates""" if total_iters > 0: percentage = (cur_iter / total_iters) * 100 message = f"{prefix} {suffix}".strip() asyncio.create_task(self.middleware.update_progress(percentage, message)) def set_verbosity(self, verbosity): """Set verbosity level""" self.verbosity = verbosity asyncio.create_task( self.middleware.log_info(f"Verbosity set to level {verbosity}") ) def _format_message(self, message, *args): """Format message with arguments""" try: return message % args if args else message except (TypeError, ValueError): return f"{message} {' '.join(map(str, args))}" if args else message ``` ## ๐Ÿš€ Complete Workflow Example ### 3. ESP32 Development Workflow - From Idea to Production ```python # examples/complete_esp32_workflow.py """ Complete ESP32 development workflow example: Idea โ†’ Prototype โ†’ Test โ†’ Deploy โ†’ Production This example shows how to use the MCP ESPTool server for a complete development cycle of an ESP32 WiFi scanner project. """ import asyncio from pathlib import Path from mcp_esptool_server.server import ESPToolServer async def complete_esp32_workflow(): """Demonstrate complete ESP32 development workflow""" # Initialize MCP server (in real usage, this runs as a service) server = ESPToolServer() print("๐Ÿš€ ESP32 Development Workflow Demo") print("=" * 50) # Phase 1: Rapid Prototyping with Host Applications print("\n๐Ÿ“‹ Phase 1: Rapid Prototyping (No Hardware Required)") print("-" * 50) # Create host-based project for rapid prototyping host_result = await server.call_tool("idf_create_host_project", { "project_name": "wifi_scanner_demo", "template": "wifi", "enable_mocking": True }) print(host_result) # Build and test on host host_test_result = await server.call_tool("idf_host_build_and_run", { "project_path": "./wifi_scanner_demo", "debug_mode": True, "valgrind_check": True }) print(host_test_result) # Debug memory issues on host debug_result = await server.call_tool("idf_host_debug_interactive", { "project_path": "./wifi_scanner_demo", "debugger": "gdb" }) print(debug_result) # Phase 2: Hardware Detection and Preparation print("\n๐Ÿ” Phase 2: Hardware Detection and Preparation") print("-" * 50) # Detect ESP32 hardware detection_result = await server.call_tool("esp_detect_chip", { "port": "/dev/ttyUSB0", "trace_enabled": True }) print(f"Detection: {detection_result}") if not detection_result.get('success'): print("โŒ No hardware detected. Continuing with host development...") return # Connect with optimization connection_result = await server.call_tool("esp_connect_advanced", { "port": "/dev/ttyUSB0", "enable_stub": True, "high_speed": True }) print(connection_result) # Phase 3: Hardware-Specific Configuration print("\n๐Ÿ”ง Phase 3: Hardware Configuration") print("-" * 50) # Configure for hardware target target_result = await server.call_tool("idf_set_target", { "project_path": "./wifi_scanner_demo", "target": "esp32" }) print(target_result) # Create production partition table partition_result = await server.call_tool("esp_partition_create_ota", { "app_size": "1MB", "ota_data_size": "8KB", "nvs_size": "24KB", "output_file": "./wifi_scanner_demo/partitions.csv" }) print(partition_result) # Phase 4: Security Configuration print("\n๐Ÿ” Phase 4: Security Configuration") print("-" * 50) # Security audit security_audit = await server.call_tool("esp_security_audit", { "port": "/dev/ttyUSB0" }) print(f"Security Audit: {security_audit}") # Configure flash encryption for production encryption_result = await server.call_tool("esp_enable_flash_encryption", { "port": "/dev/ttyUSB0" }) print(encryption_result) # Phase 5: Build and Flash print("\n๐Ÿ—๏ธ Phase 5: Build and Flash") print("-" * 50) # Build optimized firmware build_result = await server.call_tool("idf_build_project", { "project_path": "./wifi_scanner_demo", "target": "esp32", "optimization": "release" }) print(build_result) # Analyze firmware analysis_result = await server.call_tool("esp_firmware_analyze", { "binary_file": "./wifi_scanner_demo/build/wifi_scanner.bin" }) print(f"Firmware Analysis: {analysis_result}") # Flash with advanced options flash_result = await server.call_tool("esp_flash_firmware", { "port": "/dev/ttyUSB0", "firmware_files": [ {"address": 0x1000, "file": "./wifi_scanner_demo/build/bootloader.bin"}, {"address": 0x8000, "file": "./wifi_scanner_demo/build/partition-table.bin"}, {"address": 0x10000, "file": "./wifi_scanner_demo/build/wifi_scanner.bin"} ], "verify": True, "optimize": True }) print(flash_result) # Phase 6: Testing and Validation print("\n๐Ÿงช Phase 6: Testing and Validation") print("-" * 50) # Monitor serial output monitor_result = await server.call_tool("idf_monitor", { "port": "/dev/ttyUSB0", "filter_logs": True }) print(monitor_result) # Performance analysis performance_result = await server.call_tool("esp_performance_profile", { "port": "/dev/ttyUSB0", "duration": 60 }) print(f"Performance Profile: {performance_result}") # Phase 7: Production Preparation print("\n๐Ÿญ Phase 7: Production Preparation") print("-" * 50) # Create OTA package ota_package = await server.call_tool("esp_ota_package_create", { "firmware_file": "./wifi_scanner_demo/build/wifi_scanner.bin", "version": "1.0.0" }) print(ota_package) # Factory programming setup factory_result = await server.call_tool("esp_factory_program", { "port": "/dev/ttyUSB0", "config": { "firmware": "./wifi_scanner_demo/build/wifi_scanner.bin", "partition_table": "./wifi_scanner_demo/partitions.csv", "manufacturing_data": { "device_id": "WS001", "batch_number": "B2025001" } } }) print(factory_result) # Final quality control qc_result = await server.call_tool("esp_quality_control", { "port": "/dev/ttyUSB0" }) print(f"Quality Control: {qc_result}") print("\n๐ŸŽ‰ Complete ESP32 Development Workflow Finished!") print("=" * 50) # Natural Language Workflow Examples async def natural_language_examples(): """Examples of natural language interactions""" examples = [ { "user_input": "Create an ESP32 project for monitoring temperature and humidity", "claude_response": """I'll create a complete ESP32 environmental monitoring project for you. ๐Ÿ”„ Creating project structure... โ†’ idf_create_host_project("temp_humidity_monitor", template="sensor") โœ“ Project created with sensor template ๐Ÿ”ง Adding required libraries... โ†’ idf_add_component("dht22") โ†’ idf_add_component("wifi") โ†’ idf_add_component("mqtt") โœ“ Environmental sensing libraries added ๐Ÿ—๏ธ Building host version for testing... โ†’ idf_host_build_and_run(debug_mode=True) โœ“ Host application running - test your logic without hardware! ๐Ÿ’ก Next steps: 1. Test sensor reading logic on host 2. Connect real DHT22 sensor to GPIO pins 3. Flash to ESP32 with: esp_flash_firmware 4. Monitor with: idf_monitor""" }, { "user_input": "My ESP32 keeps crashing, help me debug it", "claude_response": """I'll help you systematically debug the ESP32 crashes. ๐Ÿ” Starting crash analysis... โ†’ esp_detect_chip("/dev/ttyUSB0") โœ“ ESP32 detected and connected ๐Ÿ“Š Gathering crash information... โ†’ idf_monitor(filter="error,crash,abort") โ†’ esp_core_dump_analyze() โœ“ Found crash in wifi_init() function ๐Ÿ› Root cause analysis... โ†’ esp_memory_dump(address=0x3FFB0000, size=1024) โ†’ esp_diagnostic_report() ๐Ÿ’ก Issue identified: Stack overflow in WiFi task ๐Ÿ“‹ Recommended fixes: 1. Increase WiFi task stack size in menuconfig 2. Reduce local variable usage in wifi_init() 3. Check for recursive function calls Would you like me to apply these fixes automatically?""" }, { "user_input": "Set up production programming for 100 ESP32 devices", "claude_response": """I'll set up a complete production programming workflow for your batch. ๐Ÿญ Setting up factory programming environment... โ†’ esp_production_test_setup() โ†’ esp_batch_program_configure(device_count=100) ๐Ÿ” Configuring security for production... โ†’ esp_security_configure(level="production") โ†’ esp_secure_boot_enable() โ†’ esp_flash_encryption_enable() โœ“ Production security enabled ๐Ÿ“‹ Creating manufacturing data template... โ†’ esp_manufacturing_data_create(template={ "device_series": "PROD2025", "batch_id": "B001", "mac_prefix": "AA:BB:CC" }) ๐Ÿ”„ Starting batch programming... โ†’ esp_batch_program(ports=["/dev/ttyUSB0", "/dev/ttyUSB1", ...]) Progress: Device 1/100 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 100% Progress: Device 2/100 โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 100% ... โœ… Batch programming completed! ๐Ÿ“Š Results: 98/100 devices programmed successfully โš ๏ธ 2 devices failed - see detailed report""" } ] for example in examples: print(f"\n๐Ÿ‘ค User: {example['user_input']}") print(f"๐Ÿค– Claude: {example['claude_response']}") print("-" * 80) if __name__ == "__main__": print("๐Ÿš€ Running ESP32 Development Workflow Examples") asyncio.run(complete_esp32_workflow()) print("\n๐Ÿ“ Natural Language Interaction Examples:") asyncio.run(natural_language_examples()) ``` ## ๐ŸŽฏ Real-World Use Cases ### 4. IoT Device Factory Programming ```python # examples/iot_factory_programming.py async def iot_factory_programming_example(): """Real-world IoT device factory programming workflow""" # Configuration for IoT environmental sensors factory_config = { "device_type": "environmental_sensor", "firmware_version": "2.1.0", "batch_size": 50, "security_level": "production", "quality_checks": ["wifi_test", "sensor_calibration", "power_consumption"] } # Step 1: Prepare factory environment setup_result = await server.call_tool("esp_factory_setup", { "config": factory_config, "workstation_id": "WS-001", "operator_id": "OP-123" }) # Step 2: Program devices in parallel programming_tasks = [] for device_id in range(1, factory_config["batch_size"] + 1): task = program_single_device(device_id, factory_config) programming_tasks.append(task) # Execute programming in parallel (limited concurrency) results = await asyncio.gather(*programming_tasks, return_exceptions=True) # Step 3: Generate production report report = await server.call_tool("esp_generate_production_report", { "results": results, "batch_config": factory_config }) return report async def program_single_device(device_id: int, config: dict): """Program individual device with full quality control""" device_config = { "device_id": f"ENV{device_id:04d}", "mac_address": generate_mac_address(device_id), "calibration_data": generate_calibration_data(), "encryption_key": generate_device_key(device_id) } try: # 1. Hardware detection port = await find_available_port() detection = await server.call_tool("esp_detect_chip", {"port": port}) if not detection["success"]: raise Exception(f"Device {device_id}: Hardware not detected") # 2. Security configuration await server.call_tool("esp_configure_device_security", { "port": port, "device_config": device_config }) # 3. Flash firmware and data await server.call_tool("esp_flash_production_firmware", { "port": port, "firmware": config["firmware_version"], "device_data": device_config }) # 4. Quality control tests test_results = await server.call_tool("esp_run_quality_tests", { "port": port, "test_suite": config["quality_checks"] }) if not all(test_results.values()): raise Exception(f"Device {device_id}: Quality tests failed") # 5. Final validation await server.call_tool("esp_final_device_validation", { "port": port, "expected_config": device_config }) return { "device_id": device_id, "status": "success", "programming_time": time.time(), "test_results": test_results } except Exception as e: return { "device_id": device_id, "status": "failed", "error": str(e), "programming_time": time.time() } ``` These examples demonstrate the power and flexibility of the FastMCP ESPTool server architecture, showing how it transforms traditional ESP development into an AI-native, conversational experience while maintaining professional-grade capabilities. `โ˜… Insight โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€` **Production-Ready Implementation**: These examples show real-world, production-ready code that handles error conditions, user interaction, progress tracking, and comprehensive logging. The middleware pattern enables sophisticated workflows while maintaining clean separation of concerns. **Scalable Architecture**: The component-based design allows for easy extension and modification. New tools can be added by implementing the established patterns, and the middleware system automatically provides enhanced capabilities. **Complete Development Lifecycle**: From rapid prototyping with host applications to factory programming, these examples demonstrate how the system supports the entire ESP development lifecycle with AI-powered assistance at every stage. `โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€` [{"content": "Create project initialization and setup documentation", "status": "completed", "activeForm": "Creating project initialization and setup documentation"}, {"content": "Design concrete implementation examples", "status": "completed", "activeForm": "Designing concrete implementation examples"}, {"content": "Create production deployment guide", "status": "in_progress", "activeForm": "Creating production deployment guide"}]