Architecture
This document is written mostly for AI Agents.
Overview
This project is a monorepo containing the following packages:
mcp_server_dart: The core MCP server with dynamic registry capabilities.mcp_toolkit: The Flutter package that you include in your app.flutter_test_app: An example Flutter application demonstrating the toolkit.
System Overview
This project enables AI-powered development tools to interact with Flutter applications through a Dart-based MCP server with dynamic tools registration capabilities:
Architecture Flow
┌─────────────────────────────┐ ┌──────────────────┐ ┌─────────────────────────────┐
│ │ │ │ │ │
│ Flutter App │<--->│ Dart VM │<--->│ MCP Server Dart │
│ + mcp_toolkit │ │ Service │ │ + Dynamic Registry │
│ + Dynamic Tool Registration│ │ (Port 8181) │ │ │
│ │ │ │ │ │
└─────────────────────────────┘ └──────────────────┘ └─────────────────────────────┘
This unified architecture supports:
- Basic VM operations: Memory inspection, debugging, isolate management
- Flutter-specific operations: Widget inspection, layout analysis, error reporting, screenshots
- Dynamic tool registration: Runtime tool discovery and custom functionality
When to Use This
-
Direct VM Service Communication:
- Memory inspection
- Basic debugging operations
- Isolate management
- General VM state queries
-
Flutter-Specific Operations:
- Widget tree inspection
- Layout debugging
- State management analysis
- Performance profiling
- UI element interaction
-
Dynamic Tools Registration 🆕:
- Custom debugging tools
- App-specific functionality
- Runtime tool discovery
- Event-driven tool updates
1. Flutter Application Layer
Location: Your Flutter App Purpose: Debug target application Requirements:
- Must run in debug mode
mcp_toolkitpackage integrated, providing service extensions- Port 8181 available for VM Service
2. MCP Toolkit Layer (In-App Service Extensions)
Location: mcp_toolkit/mcp_toolkit/ (as a Dart package integrated into the Flutter Application)
Purpose: Exposes Flutter-specific functionalities to external tools (like AI assistants via the MCP/Forwarding server) through custom Dart VM Service extensions.
Key Features:
- Registers custom Dart VM Service extensions (e.g.,
ext.mcp.toolkit.app_errors,ext.mcp.toolkit.view_screenshots). - Captures and reports Flutter application errors.
- Provides screenshot capabilities of the application's UI.
- Enables retrieval of application view details.
- Facilitates interaction with the Flutter application at a higher level than raw VM service calls.
- 🆕 Dynamic Tool Registration: Allows runtime registration of custom tools and resources.
3. MCP Server Layer (Dart-based)
Location: mcp_server_dart/
Purpose: Protocol translation, request handling, and dynamic registry management
Key Features:
- JSON-RPC to VM Service Protocol translation
- Request routing and validation
- Error handling and logging
- Connection management
- Dynamic Registry: Manages runtime-registered tools and resources
- Event-Driven Discovery: Real-time tool detection via DTD events
4. AI Assistant Integration Layer
Location: AI Tool (e.g., Cline, Claude, Cursor) Purpose: Developer interaction and analysis Features:
- Code analysis and suggestions
- Widget tree visualization
- Debug information display
- Performance recommendations
- Dynamic Tool Discovery: Access to runtime-registered tools
Standard Flow
-
Request Initiation:
AI Assistant -> MCP JSON-RPC Request -> MCP Server Dart -
Protocol Translation & Interaction:
MCP Server Dart -> Dart VM Service (invoking mcp_toolkit extensions on Flutter App) -
Response Flow:
mcp_toolkit in Flutter App -> Dart VM Service -> MCP Server Dart -> AI Assistant
Communication Details
graph TD
A[AI Assistant] <-->|stdin/stdout| B(MCP Server);
B <-->|Dart VM Service| C(Flutter App with mcp_toolkit);
B <-->|DTD Events| D(Dynamic Registry);
C <-->|Tool Registration| D;
- The AI assistant sends a request to the MCP server.
- The MCP server forwards the request to the Flutter app through the Dart VM service.
- The Flutter app executes the requested tool and sends the result back to the server.
- The server forwards the result to the AI assistant.
- Dynamic tools are discovered via DTD events and registered in real-time.
1. MCP (Model Context Protocol)
- JSON-RPC 2.0 based
- Standardized message format
- Type-safe interactions
- Extensible command system
- Dynamic tool support
2. VM Service Protocol
- Flutter's native debugging protocol
- Real-time state access
- Widget tree manipulation
- Performance metrics collection
3. Dynamic Registry Protocol 🆕
- Event-driven tool discovery
- Runtime registration/unregistration
- Type-safe tool definitions
- Hot reload support
Security Considerations
-
Debug Mode Only:
- All operations require debug mode
- No production access
- Controlled environment execution
-
Port Security:
- Default ports: 8181 (VM), 8182 (MCP)
- Local-only connections
- Port validation and verification
-
Data Safety:
- No sensitive data exposure
- Sanitized error messages
- Controlled access scope
-
Dynamic Registration Security 🆕:
- Debug mode enforcement
- Local-only tool registration
- Sandboxed execution environment
Performance Optimization
-
Connection Management:
- Connection pooling
- Automatic reconnection
- Resource cleanup
-
Data Efficiency:
- Response caching
- Batch operations
- Optimized protocol translation
-
Error Handling:
- Graceful degradation
- Detailed error reporting
- Recovery mechanisms
-
Dynamic Registry Performance:
- Event-driven updates (no polling)
- Efficient tool lookup
- Minimal overhead registration
1. Custom Commands
// Add new commands via dynamic registration
final customTool = MCPCallEntry.tool(
handler: (request) {
// Your custom logic
return MCPCallResult(message: 'Success');
},
definition: MCPToolDefinition(
name: 'custom_command',
description: 'Your custom functionality',
inputSchema: {...},
),
);
await MCPToolkitBinding.instance.addEntries(entries: {customTool});
Common Use Cases
-
Widget Analysis:
// Example: Get widget tree final widgetTree = await inspector.getRootWidget(); -
Layout Debugging:
// Example: Analyze layout issues final layoutInfo = await inspector.debugDumpRenderTree(); -
Performance Profiling:
// Example: Profile widget builds await inspector.profileWidgetBuilds({ enabled: true });