🔍 A powerful Model Context Protocol (MCP) server that connects your Flutter apps with AI coding assistants like Cursor, Claude, and Cline.
This project is a work in progress and not all methods (mostly Flutter Inspector related) are implemented yet.
To install Flutter Inspector for Claude Desktop automatically via Smithery:
npx -y @smithery/cli install @Arenukvern/mcp_flutter --client claude
For developers who want to contribute to the project or run the latest version directly from source, follow these steps:
Clone the repository:
shell
git clone https://github.com/Arenukvern/mcp_flutter
cd flutter-inspector
Install and build dependencies:
shell
make install
Start forwarding server:
shell
make forward
Add DevTools Flutter Extension to Flutter App:
shell
flutter pub add --dev devtools_mcp_extension
Start your Flutter app in debug mode:
shell
flutter run --debug --observatory-port=8181 --enable-vm-service --disable-service-auth-codes
🛠️ Add Flutter Inspector to your AI tool
Note for Local Development (GitHub Install):
If you installed the Flutter Inspector from GitHub and built it locally, you need to adjust the paths in the AI tool configurations to point to your local build/index.js
file.
Add to your .cline/config.json
:
json
{
"mcpServers": {
"flutter-inspector": {
"command": "node",
"args": ["/path/to/your/cloned/flutter-inspector/mcp_server/build/index.js"],
"env": {
"PORT": "3334",
"LOG_LEVEL": "info"
},
"disabled": false
}
}
}
Restart Cline
Under "Model Context Protocol", add the server:
json
{
"mcpServers": {
"flutter-inspector": {
"command": "node",
"args": ["/path/to/your/cloned/flutter-inspector/mcp_server/build/index.js"],
"env": {},
"disabled": false,
"autoApprove": []
}
}
}
Restart Cursor
Add to your Claude configuration file:
json
{
"mcpServers": {
"flutter-inspector": {
"command": "node",
"args": ["/path/to/your/cloned/flutter-inspector/mcp_server/build/index.js"],
"env": {
"PORT": "3334",
"LOG_LEVEL": "info"
},
"disabled": false
}
}
}
Restart Claude
.env
)PORT=3334 # Server port (default: 3334)
LOG_LEVEL=info # Logging level (error, warn, info, debug)
--port, -p # Server port
--stdio # Run in stdio mode (default: true)
--log-level # Set logging level
--help # Show help
All Flutter Inspector tools automatically connect to the default Flutter debug port (8181). You only need to specify a port if:
Example usage:
// Default port (8181)
{
"name": "debug_dump_render_tree"
}
// Custom port
{
"name": "debug_dump_render_tree",
"arguments": {
"port": 8182
}
}
All tools default to using port 8181 if no port is specified. You can override this by providing a specific port number.
These are helper methods that provide additional functionality beyond direct Flutter RPC calls:
get_active_ports
: Lists all Flutter/Dart processes listening on portsget_supported_protocols
: Retrieves supported protocols from a Flutter appget_vm_info
: Gets detailed VM information from a running Flutter appget_extension_rpcs
: Lists all available extension RPCs in the Flutter appDirect RPC methods for debugging Flutter applications:
debug_dump_render_tree
: Dumps the render tree structuredebug_dump_layer_tree
: Dumps the layer tree for rendering analysisdebug_dump_semantics_tree
: Dumps the semantics tree for accessibility analysisdebug_paint_baselines_enabled
: Toggles baseline paint debuggingdebug_dump_focus_tree
: Dumps the focus tree for input handling analysisDirect RPC methods for inspecting Flutter widget trees and layout:
inspector_screenshot
: Takes a screenshot of the Flutter appDirect RPC methods for Dart I/O operations:
dart_io_get_version
: Gets Flutter version informationdebug_
, inspector_
, or dart_io_
get_active_ports
)get_supported_protocols
)get_vm_info
)get_extension_rpcs
)All methods follow a consistent naming pattern:
Each method name indicates its category and functionality, making it easier to understand its purpose and capabilities.
Each method includes:
For detailed implementation instructions, see the "Implementing New RPC Methods" section.
Add RPC Method Definition
ts
// In src/index.ts, add to appropriate group in FlutterRPC
const FlutterRPC = {
GroupName: {
METHOD_NAME: createRPCMethod(RPCPrefix.GROUP, "methodName"),
// ... other methods
},
};
Add Tool Definition
ts
// In ListToolsRequestSchema handler
{
name: "method_name",
description: "Clear description of what the method does",
inputSchema: {
type: "object",
properties: {
port: {
type: "number",
description: "Port number where the Flutter app is running (defaults to 8181)",
},
// Add other parameters if needed
paramName: {
type: "string", // or boolean, number, etc.
description: "Parameter description",
}
},
required: ["paramName"], // List required parameters
}
}
Implement Handler
ts
// In CallToolRequestSchema handler
case "method_name": {
const port = handlePortParam();
// Get and validate parameters if any
const { paramName } = request.params.arguments as { paramName: string };
if (!paramName) {
throw new McpError(
ErrorCode.InvalidParams,
"paramName parameter is required"
);
}
// Call the RPC method
return wrapResponse(
this.invokeFlutterExtension(port, FlutterRPC.GroupName.METHOD_NAME, {
paramName,
})
);
}
FlutterRPC
RPCPrefix
// 1. Add RPC Method
const FlutterRPC = {
Inspector: {
GET_WIDGET_DETAILS: createRPCMethod(RPCPrefix.INSPECTOR, "getWidgetDetails"),
}
};
// 2. Add Tool Definition
{
name: "get_widget_details",
description: "Get detailed information about a specific widget",
inputSchema: {
type: "object",
properties: {
port: {
type: "number",
description: "Port number where the Flutter app is running (defaults to 8181)",
},
widgetId: {
type: "string",
description: "ID of the widget to inspect",
}
},
required: ["widgetId"],
}
}
// 3. Implement Handler
case "get_widget_details": {
const port = handlePortParam();
const { widgetId } = request.params.arguments as { widgetId: string };
if (!widgetId) {
throw new McpError(
ErrorCode.InvalidParams,
"widgetId parameter is required"
);
}
await this.verifyFlutterDebugMode(port);
return wrapResponse(
this.invokeFlutterExtension(port, FlutterRPC.Inspector.GET_WIDGET_DETAILS, {
widgetId,
})
);
}
McpError
with clear messageswrapResponse
for consistent formattinghandlePortParam()
for port managementWhen implementing methods from todo.yaml:
For each new method:
The Flutter Inspector is registered with Smithery's registry, making it discoverable and usable by other AI tools through a standardized interface.
┌─────────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ ┌─────────────┐
│ │ │ │ │ │ │ │ │ │
│ Flutter App │<--->│ DevTools │<--->│ Forwarding │<--->│ MCP Server │<--->│ Smithery │
│ (Debug Mode) │ │ Extension │ │ Server │ │ (Registered) │ │ Registry │
│ │ │ │ │ │ │ │ │ │
└─────────────────┘ └──────────────┘ └──────────────┘ └─────────────────┘ └─────────────┘
Contributions are welcome! Please feel free to submit pull requests or report issues on the GitHub repository.
MIT - Feel free to use in your projects!
Flutter and Dart are trademarks of Google LLC.