MCP Flutter 调试工具
一个MCP服务器,其简单目标是通过赋予AI代码助手(Cline、Cursor、Claude等)分析widget树、导航和布局问题的工具,从而调试Flutter应用程序。 请查看架构以了解其工作原理:https://github.com/Arenukvern/mcp_flutter/blob/main/ARCHITECTURE.md
服务介绍
Flutter Inspector MCP Server 用于 AI 辅助开发
🔍 一个强大的 Model Context Protocol (MCP) 服务器,将您的 Flutter 应用程序与 Cursor、Claude 和 Cline 等 AI 编码助手连接起来。
此项目仍在进行中,尚未实现所有方法(主要是与 Flutter Inspector 相关的方法)。
但是,有两个方法已通过 Flutter 测试:
- 截图
- 获取根组件
目前 Flutter 通过转发服务器与 MCP 服务器配合工作。更多详情请参阅 架构。
其他一些方法尚未经过测试 - 它们可能有效也可能无效。请谨慎使用。稍后可能会从 MCP 服务器中移除大部分方法,以便专注于 Flutter 应用程序,也许还有 Jaspr。
!!警告!!
所有转储工具都是非常重的操作,很容易使 AI 代理的上下文窗口过载。请务必谨慎使用。
🚀 快速开始
前提条件
- Node.js (v14 或更高版本)
- 在调试模式下运行的 Flutter 应用
- 其中之一:Cursor、Claude 或 Cline AI 助手
通过 Smithery 安装
要通过 Smithery 自动为 Claude Desktop 安装 Flutter Inspector:
npx -y @smithery/cli install @Arenukvern/mcp_flutter --client claude
从 GitHub 安装
对于希望为项目贡献或直接从源代码运行最新版本的开发者,请按照以下步骤操作:
-
克隆仓库:
git clone https://github.com/Arenukvern/mcp_flutter cd flutter-inspector -
安装并构建依赖项:
make install该命令会安装
package.json中列出的所有必要依赖项,然后构建 MCP 服务器和转发服务器。 -
启动转发服务器:
make forward -
将 DevTools Flutter 扩展添加到 Flutter 应用中:
flutter pub add --dev devtools_mcp_extension -
以调试模式启动您的 Flutter 应用
! 出于安全原因,当前的解决方法是使用
--disable-service-auth-codes运行。如果您知道如何修复这个问题,请告诉我!flutter run --debug --observatory-port=8181 --enable-vm-service --disable-service-auth-codes -
🛠️ 将 Flutter Inspector 添加到您的 AI 工具中
本地开发注意事项(GitHub 安装):
如果您从 GitHub 安装了 Flutter Inspector 并在本地构建了它,则需要调整 AI 工具配置中的路径,使其指向您的本地
build/index.js文件。请参考“从 GitHub 安装”部分,了解有关克隆和构建项目的说明。Cline 设置
- 在您的
.cline/config.json中添加:{ "mcpServers": { "flutter-inspector": { "command": "node", "args": [ "/path/to/your/cloned/flutter-inspector/mcp_server/build/index.js" ], "env": { "PORT": "3334", "LOG_LEVEL": "critical" }, "disabled": false } } } - 重启 Cline
- Flutter 检查器将在您的对话中自动可用
Cursor 设置
- 打开 Cursor 的设置
- 转到功能标签页
- 在“Model Context Protocol”下,添加服务器:
{ "mcpServers": { "flutter-inspector": { "command": "node", "args": [ "/path/to/your/cloned/flutter-inspector/mcp_server/build/index.js" ], "env": {}, "disabled": false, "autoApprove": [] } } } - 重启 Cursor
- 打开代理面板(macOS 上为 cmd + L)
- 您已经准备好了!尝试使用如“分析我的 Flutter 应用的小部件树”等命令
Claude 设置
- 在您的 Claude 配置文件中添加:
{ "mcpServers": { "flutter-inspector": { "command": "node", "args": [ "/path/to/your/cloned/flutter-inspector/mcp_server/build/index.js" ], "env": { "PORT": "3334", "LOG_LEVEL": "critical" }, "disabled": false } } } - 重启 Claude
- Flutter 检查器工具将自动可用
- 在您的
🎯 您可以做什么(希望如此)
- 分析 Widget 树:获取有关 Flutter 应用结构的详细信息
- 检查导航:查看当前路由和导航状态
- 调试布局问题:理解 widget 之间的关系及其属性
🔧 配置选项
环境变量(.env)
# will be used for direct connections to the dart vm
DART_VM_PORT=8181
DART_VM_HOST=localhost
# will be used for this MCP server
MCP_SERVER_PORT=3535
MCP_SERVER_HOST=localhost
# will be used for the forwarding server
FORWARDING_SERVER_PORT=8143
FORWARDING_SERVER_HOST=localhost
# Logging configuration
LOG_LEVEL=critical
# Development configuration
NODE_ENV=development
命令行参数
--port, -p # Server port
--stdio # Run in stdio mode (default: true)
--log-level # Set logging level (debug, info, notice, warning, error, critical, alert, emergency) according to https://spec.modelcontextprotocol.io/specification/2025-03-26/server/utilities/logging/#log-levels
--help # Show help
端口配置
所有 Flutter Inspector 工具会自动连接到默认的 Flutter 调试端口 (8181)。只有在以下情况下才需要指定端口:
- 您正在不同的端口上运行 Flutter
- 您同时运行了多个 Flutter 实例
- 您配置了一个自定义的调试端口
示例用法:
// Default port (8181)
{
"name": "debug_dump_render_tree"
}
// Custom port
{
"name": "debug_dump_render_tree",
"arguments": {
"port": 8182
}
}
🔧 故障排除
-
连接问题
- 确保您的 Flutter 应用处于调试模式
- 验证 Flutter 应用和 Inspector 中的端口是否匹配
- 检查该端口是否未被其他进程占用
-
AI 工具无法检测到 Inspector
- 在更改配置后重新启动 AI 工具
- 验证配置 JSON 语法
- 检查工具的日志以查找连接错误
📚 可用工具
如果未指定端口,所有工具默认使用 8181 端口。您可以通过提供特定的端口号来覆盖此设置。
辅助方法(非直接 RPC 调用)
这些是提供超出直接 Flutter RPC 调用功能的辅助方法:
get_active_ports: 列出所有监听端口的 Flutter/Dart 进程get_supported_protocols: 从 Flutter 应用中检索支持的协议get_vm_info: 从正在运行的 Flutter 应用中获取详细的 VM 信息get_extension_rpcs: 列出 Flutter 应用中的所有可用扩展 RPC
调试方法(ext.flutter.debug*)
用于调试 Flutter 应用程序的直接 RPC 方法:
debug_dump_render_tree: 导出渲染树结构debug_dump_layer_tree: 导出层树以进行渲染分析debug_dump_semantics_tree: 导出语义树以进行可访问性分析debug_paint_baselines_enabled: 开关基线绘制调试debug_dump_focus_tree: 导出焦点树以进行输入处理分析
Inspector 方法(ext.flutter.inspector.*)
用于检查 Flutter widget 树和布局的直接 RPC 方法:
inspector_screenshot: 对 Flutter 应用截图
DartIO 方法(ext.dart.io.*)
用于 Dart I/O 操作的直接 RPC 方法:
dart_io_get_version: 获取 Flutter 版本信息
方法类别
-
直接RPC方法
这些方法直接映射到Flutter的扩展RPC:- 所有以
debug_、inspector_或dart_io_开头的方法 - 每个方法对应一个特定的Flutter RPC端点
- 参数和返回值与Flutter的规范相匹配
- 所有以
-
实用方法
这些是提供额外功能的帮助方法:- 进程发现 (
get_active_ports) - 协议检查 (
get_supported_protocols) - VM交互 (
get_vm_info) - RPC发现 (
get_extension_rpcs)
- 进程发现 (
方法命名约定
所有方法遵循一致的命名模式:
- 实用方法:描述性名称
- 调试方法:debug_*
- 检查器方法:inspector_*
- DartIO方法:dartio*
- 流方法:stream_*
每个方法名指示其类别和功能,使其目的和能力更容易理解。
方法文档格式
每个方法包括:
- 功能的清晰描述
- 必需和可选参数
- 返回值格式
- 类别指示(RPC vs 实用)
- 对应的Flutter RPC端点(如果适用)
有关详细的实现说明,请参阅“实现新的RPC方法”部分。
🔧 实现新的RPC方法
逐步指南
-
添加RPC方法定义
// 在src/index.ts中,将方法添加到FlutterRPC中的适当组 const FlutterRPC = { GroupName: { METHOD_NAME: createRPCMethod(RPCPrefix.GROUP, "methodName"), // ... 其他方法 }, }; -
添加工具定义
// 在ListToolsRequestSchema处理程序中 { name: "method_name", description: "对方法功能的清晰描述", inputSchema: { type: "object", properties: { port: { type: "number", description: "运行Flutter应用的端口号(默认为8181)", }, // 根据需要添加其他参数 paramName: { type: "string", // 或boolean, number等 description: "参数描述", } }, required: ["paramName"], // 列出必需的参数 } } -
实现处理程序
// 在CallToolRequestSchema处理程序中 case "method_name": { const port = handlePortParam(); // 获取并验证参数(如果有) const { paramName } = request.params.arguments as { paramName: string }; if (!paramName) { throw new McpError( ErrorCode.InvalidParams, "paramName参数是必需的" ); } // 调用RPC方法 return wrapResponse( this.invokeFlutterExtension(port, FlutterRPC.GroupName.METHOD_NAME, { paramName, }) ); }
实现检查清单
-
方法定义
- 添加到
FlutterRPC中的适当组 - 使用正确的
RPCPrefix - 遵循命名约定
- 添加到
-
工具定义
- 添加清晰的描述
- 定义所有参数
- 标记必需参数
- 添加端口参数
- 文档化参数类型
-
处理器实现
- 在 switch 语句中添加 case
- 处理端口参数
- 验证所有参数
- 添加错误处理
- 使用适当的类型
- 返回包装后的响应
-
测试
- 验证方法在调试模式下是否正常工作
- 使用不同的参数值进行测试
- 测试错误情况
- 使用默认端口进行测试
示例实现
// 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,
})
);
}
常见模式
-
参数验证
- 始终验证必需参数
- 使用 TypeScript 类型以确保类型安全
- 抛出带有明确消息的
McpError
-
错误处理
- 对异步操作使用 try-catch 块
- 在需要时验证 Flutter 调试模式
- 处理连接错误
-
响应包装
- 使用
wrapResponse进行一致的格式化 - 同时处理成功和错误情况
- 适当地格式化响应数据
- 使用
-
端口处理
- 使用
handlePortParam()进行端口管理 - 如果未指定,则默认为 8181
- 验证端口号
- 使用
AI 代理注意事项
在从 todo.yaml 实现方法时:
- 按照上述逐步指南操作
- 使用示例实现作为模板
- 确保完成所有检查表项目
- 添加适当的错误处理和参数验证
- 遵循常见模式部分
- 彻底测试实现
对于每个新方法:
- 检查方法所属的组(UI、DartIO、Inspector 等)
- 从方法名称和上下文中确定所需的参数
- 按照标准模式实现
- 添加适当的错误处理
- 遵循现有的代码风格
Smithery 集成
Flutter Inspector 已注册到 Smithery 的注册表中,使其可以通过标准化接口被其他 AI 工具发现和使用。
集成架构
┌─────────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ ┌─────────────┐
│ │ │ │ │ │ │ │ │ │
│ Flutter App │<--->│ DevTools │<--->│ Forwarding │<--->│ MCP Server │<--->│ Smithery │
│ (Debug Mode) │ │ Extension │ │ Server │ │ (Registered) │ │ Registry │
│ │ │ │ │ │ │ │ │ │
└─────────────────┘ └──────────────┘ └──────────────┘ └─────────────────┘ └─────────────┘
🤝 贡献
欢迎贡献!请随时在 GitHub 仓库 提交拉取请求或报告问题。
📖 了解更多
📄 许可证
MIT - 可自由用于您的项目!
Flutter 和 Dart 是 Google LLC 的商标。