Flutter 语义 MCP 服务器
](https://pub.dev/packages/mcp_flutter_semantics) 
使AI编码助手能够“查看”并理解您正在运行的Flutter应用程序,通过 模型上下文协议(MCP)在使用AI进行调试时,省去手动截图和用户界面描述的步骤。
这是什么?
这个包在您的Flutter应用中嵌入了一个MCP服务器,使像Claude Code这样的AI助手能够:
- 查看你的用户界面查询完整的Flutter语义树以了解屏幕上的内容
- 调试错误访问包含完整上下文(堆栈跟踪、小部件路径、用户操作)的全面错误追踪功能
- 提问“为什么这个按钮被禁用了?”,“发生了什么错误?”,“当前可见的是什么?”
所有数据均保存在本地——无需网络传输,在发布版本中自动禁用。
特点/特性
- 语义树访问AI可以查询完整的Flutter UI层次结构
- 全面错误追踪自动捕获,包括堆栈跟踪、小部件上下文、语义快照和用户操作历史
- MCP协议集成人工智能工具通信的标准协议
- 隐私优先在发布版本中自动禁用,注重隐私的数据收集
- 轻松设置只需≤5行代码即可上手
- 平台支持macOS 和 iOS(模拟器和实体设备)
快速入门(\ value?.contains('@') == true
? null : 'Invalid email', onChanged: (_) => setState(() {}), )
**人工智能可以:**
- 填写字段: `trigger_action("email-field", "set_text", "john@example.com")`
- 清除字段: `trigger_action("email-field", "clear")`
- 读取值:检查元数据以获取当前值和验证状态
#### McpDropdown - 选择下拉菜单
McpDropdown( id: 'country-dropdown', label: 'Country', hint: 'Select your country', value: _selectedCountry, items: const [ DropdownMenuItem(value: 'US', child: Text('United States')), DropdownMenuItem(value: 'UK', child: Text('United Kingdom')), DropdownMenuItem(value: 'CA', child: Text('Canada')), ], onChanged: (value) => setState(() => _selectedCountry = value), metadata: { 'required': false, 'options': ['US', 'UK', 'CA'], // AI sees available options }, )
**人工智能可以:**
- 选择选项: `trigger_action("country-dropdown", "select", "UK")`
- 查看选项:元数据包含所有可用值
#### McpCheckbox - 复选框
McpCheckbox( id: 'terms-checkbox', label: 'I accept terms and conditions', value: _acceptedTerms, enabled: true, metadata: {'required': true}, title: const Text('I accept the terms and conditions'), onChanged: (value) => setState(() => _acceptedTerms = value ?? false), )
**人工智能可以:**
- 检查: `trigger_action("terms-checkbox", "check")`
- 取消选中: `trigger_action("terms-checkbox", "uncheck")`
- 切换: `trigger_action("terms-checkbox", "toggle")`
#### McpSlider - 值滑块
McpSlider( id: 'satisfaction-slider', label: 'Satisfaction Level', hint: 'Rate from 0 to 10', value: _satisfaction, min: 0, max: 10, divisions: 10, onChanged: (value) => setState(() => _satisfaction = value), metadata: { 'unit': 'rating', 'currentValue': _satisfaction, }, )
**人工智能可以:**
- 设置值: `trigger_action("satisfaction-slider", "set_value", "8.0")`
- 增加: `trigger_action("satisfaction-slider", "increase")`
- 减少: `trigger_action("satisfaction-slider", "decrease")`
### 导航追踪
注册路由以帮助AI导航您的应用程序:
void main() async { WidgetsFlutterBinding.ensureInitialized();
// Register routes with rich metadata McpNavigationMap.instance.registerRoute( path: '/profile', name: 'User Profile', description: 'View and edit user profile information', metadata: { 'purpose': 'Manage user account details', 'commonActions': ['Edit name', 'Change avatar', 'Update email'], 'prerequisites': 'User must be logged in', }, );
await McpSemanticsServer.instance.start(); runApp(MyApp()); }
在你的 MaterialApp 中添加导航观察者:
MaterialApp( navigatorObservers: [ McpNavigationObserver(sanitizeParams: true), McpRoutingObserver(logger: debugPrint), ], // ... rest of your app )
**人工智能可以:**
- 查询网站地图: `navigation://sitemap` 显示所有路线
- 导航: `navigate_to("/profile")`
- 返回: `go_back()`
### 带修复提示的表单验证
帮助AI理解和自动修复表单验证问题:
McpButton( id: 'submit-button', label: 'Submit', onPressed: _isValid ? _handleSubmit : null, enabled: _isValid, metadata: { 'disabledReasons': _getDisabledReasons(), // ["Name is empty", "Email invalid"]
// Healing hints tell AI how to fix issues 'healingHints': { 'canAutoHeal': true, 'autoHealableFields': ['name-field', 'email-field'], 'suggestedAction': 'Fill name and email fields', },
// Field status shows current validation state 'fieldStatus': { 'name': { 'id': 'name-field', 'valid': false, 'accessible': true, 'validationMessage': 'Name is required', }, 'email': { 'id': 'email-field', 'valid': false, 'accessible': true, 'validationMessage': 'Must contain @', }, },
'completionPercentage': 0, // Progress tracking }, child: const Text('Submit'), )
**人工智能可以:**
- 查看“查看原因”按钮为何被禁用
- 知道哪些字段需要修正
- 智能自动填充表单
- 追踪轨道完成进度
### 最佳实践
#### 1. 使用独特、描述性的ID
✅ GOOD: id: 'user-profile-save-button' ❌ BAD: id: 'button1'
#### 2. 提供丰富的元数据
McpTextField( id: 'age-field', label: 'Age', metadata: { 'required': true, 'minValue': 18, 'maxValue': 120, 'validationMessage': _ageError, 'isEmpty': _ageController.text.isEmpty, 'isValid': _isAgeValid(), }, // ... )
#### 3. 保持元数据更新
使用 `setState()` 当小部件状态发生变化时更新元数据:
onChanged: (_) => setState(() {}), // Triggers rebuild with fresh metadata
#### 4. 结合语义
你可以同时使用MCP小部件和Flutter的语义功能,以实现最佳的无障碍性:
Semantics( label: 'Submit form button', hint: 'Tap to submit your information', enabled: _formIsValid, button: true, child: McpButton( id: 'submit-button', label: 'Submit', onPressed: _formIsValid ? _handleSubmit : null, // ... ), )
### 完整示例
这是一个完全由人工智能控制的完整表单:
class MyForm extends StatefulWidget { @override State createState() => _MyFormState(); }
class _MyFormState extends State { final _nameController = TextEditingController(); final _emailController = TextEditingController(); bool _acceptedTerms = false;
bool get _isValid => _nameController.text.isNotEmpty && _emailController.text.contains('@') && _acceptedTerms;
@override Widget build(BuildContext context) { return Column( children: [ // Progress indicator McpWidget( id: 'form-progress', type: 'ProgressIndicator', label: 'Form Progress', metadata: { 'percentage': _calculateProgress(), 'fieldsRemaining': _getRemainingFields(), }, child: LinearProgressIndicator( value: _calculateProgress() / 100, ), ),
// Name field McpTextField( id: 'name-field', label: 'Full Name', controller: _nameController, metadata: { 'required': true, 'isEmpty': _nameController.text.isEmpty, }, onChanged: (_) => setState(() {}), ),
// Email field McpTextField( id: 'email-field', label: 'Email', controller: _emailController, metadata: { 'required': true, 'isValid': _emailController.text.contains('@'), }, onChanged: (_) => setState(() {}), ),
// Terms checkbox McpCheckbox( id: 'terms-checkbox', label: 'Accept terms', value: _acceptedTerms, onChanged: (val) => setState(() => _acceptedTerms = val ?? false), ),
// Submit button with healing hints McpButton( id: 'submit-button', label: 'Submit', onPressed: _isValid ? _submit : null, enabled: _isValid, metadata: { 'formValid': _isValid, 'disabledReasons': _getDisabledReasons(), 'healingHints': { 'canAutoHeal': !_isValid, 'autoHealableFields': _getFixableFields(), }, }, child: const Text('Submit'), ), ], ); } }
现在,人工智能可以:
- ✅ 查看所有表单字段
- ✅ 自动填充字段
- ✅ 理解验证规则
- ✅ 跟踪进度
- ✅ 准备好时提交
## 配置选项
自定义服务器行为以 `McpServerConfig`:
await McpSemanticsServer.instance.start( config: McpServerConfig( // App metadata for AI assistants appName: 'My App', appDescription: 'A demo app showing MCP integration',
// Logging verbosity logLevel: McpLogLevel.verbose, // none, basic, verbose, debug
// Error retention errorRetentionHours: 48, // Keep errors for 48 hours errorRetentionCount: 1000, // Max 1000 errors in database
// User action tracking captureUserActions: true, // Track taps, scrolls, navigation
// Privacy sanitizeRouteParams: true, // /user/123 → /user/:id enableInRelease: false, // Never enable in production! ), );
## 可用的MCP资源
MCP服务器提供了以下资源:
### `semantics://tree`
返回以JSON格式表示的完整Flutter语义树。包含所有语义数据字段:标签、值、提示、操作、边界、变换等。
### `errors://recent`
返回最近的错误(默认最后10条)。添加 `?limit=20` 进行定制。
### `errors://all`
返回数据库中当前所有的错误。
### `errors://unresolved`
仅返回尚未标记为已解决的错误。
## 可用的MCP工具
### `get_semantics_node`
通过ID获取特定节点的详细语义数据。
{"node_id": 42}
### `get_error_details`
获取完整的错误详细信息,包括所有上下文(堆栈跟踪、小部件路径、语义快照、用户操作)。
{"error_id": 123}
### `query_errors`
按类型、消息模式、时间范围或解决状态搜索和过滤错误。
{ "error_type": "RenderFlexOverflow", "since": "2025-10-21T10:00:00Z", "resolved": false, "limit": 20 }
### `mark_error_resolved`
将错误标记为已解决或未解决。
{"error_id": 123, "resolved": true}
### `clear_errors`
从数据库中清除错误,可选择过滤。
{"filter": "resolved", "older_than_hours": 24}
## 数据库模式错误
错误信息存储在 SQLite 中(`mcp_errors.db`(附带全面的上下文)
| 字段 | 类型 | 描述 |
|-------|------|-------------|
| (无) | (无) | (无) | `id` |
| 整数 | 自动递增的错误ID | `timestamp` |
| 文本 | ISO 8601 时间戳 | `error_type` |
| 文本 | 异常/错误类名 | `error_message` |
| 文本 | 完整错误信息 | `stack_trace` |
| 文本 | 完整堆栈跟踪 | `widget_context` |
| 文本 | 小部件树路径(JSON) | `semantics_snapshot` |
| TEXT | 错误发生时的语义树(JSON格式) | `app_state` |
| 文本 | 额外的应用状态(JSON) | `user_actions` |
| 文本 | 最近10次用户交互(JSON格式) | `is_fatal` |
| 整数 | 1 表示致命,0 表示非致命 | `is_resolved` |
## | 整数 | 标记为已解决时为1 |
### 故障排除
- 服务器无法启动 `WidgetsFlutterBinding.ensureInitialized()` 确保 `start()`
- 在……之前被调用
- 检查你是否在调试模式或性能分析模式下运行(服务器在发布模式下会自动禁用) `[MCP]` 在控制台中查找错误信息
### 前缀
- 克劳德代码无法连接
- 在Claude代码设置中验证您的MCP服务器配置
- 确保您的Flutter应用程序正在运行 `[MCP] Semantics Server started on stdio` 检查stdio传输是否正常工作(查找
- (在控制台中) [见](CLAUDE_CODE_SETUP.md) CLAUDE_CODE_SETUP.md(文件名,可译为“克劳德代码设置说明.md”或保持原样,因为文件名通常不翻译,除非有特定的翻译需求)
### 用于详细故障排除
- 错误未被捕获 `McpSemanticsServer.instance.start()` 检查一下
- 成功完成 `[MCP] Error capture initialized` 验证错误捕获是否已初始化(查找
- (在控制台中)
### 尝试触发一个故意错误以进行测试
- 性能问题 `logLevel` 减少 `basic` 到;向;对于;关于;在(某时间/某方面) `none`
- 或者 `errorRetentionCount` 较低的
- 如果数据库非常大 `captureUserActions` 禁用
## 如果不需要
隐私考量
- **这个包裹的设计充分考虑了隐私保护:**在发布构建中自动禁用
- **服务器除非明确启用,否则不会在生产环境中运行**文本输入未被捕获
- **用户按键输入和表单数据绝不会被存储**路由消毒(或路由清理)`/user/123` URL 参数默认情况下会被清理(或验证) `/user/:id`→
- **)**仅限本地
- **所有数据均存储在设备上,无需网络传输**用户行为追踪
- **捕获交互类型(点击、滚动),但不捕获内容**语义快照
**仅捕获无障碍数据,不捕获像素内容**警告 `enableInRelease: true` 永不设定
## 在生产应用中,这样做会暴露内部应用程序的状态。
平台支持
| 平台 | 状态 | 备注 |
|----------|--------|-------|
| macOS | ✅ 支持 | 完全支持(桌面版) |
| iOS | ✅ 支持 | 通过USB调试使用模拟器和物理设备 |
| Android | ⏳ 第二阶段 | 计划在未来发布 |
| 网站 | ⏳ 第二阶段 | 计划在未来发布 |
| Windows | ⏳ 第二阶段 | 计划在未来发布 |
## | Linux | ⏳ 第二阶段 | 计划在未来发布 |
示例应用程序 [`example/`](example/) 查看
- 一个完整演示应用程序的目录,展示:
- MCP服务器初始化
- 全面的语义标注
- 故意触发错误
- 错误恢复模式
用户交互追踪
cd example flutter run -d macos # or -d ios
## 运行示例:
API 文档
dart doc open doc/api/index.html
完整的API文档已提供: [或者查看生成的文档于](https://pub.dev/documentation/mcp_flutter_semantics/latest/)pub.dev(注:这个域名通常用于指向Flutter的包发布平台,但直接翻译为中文并无实际意义,因此保留原样)
## 。
1. **其工作原理**MCP 服务器
1. **在您的Flutter应用中运行,使用stdio传输方式**语义树 `WidgetsBinding.instance.pipelineOwner?.semanticsOwner`
1. **通过……访问**错误捕获 `FlutterError.onError` 挂钩于 `PlatformDispatcher.instance.onError`
1. **并且**SQLite 存储 `mcp_errors.db` 错误持续存在
1. **在应用文档目录中**用户操作
1. **通过手势检测器和导航观察者追踪(记录最近10个动作的循环缓冲区)**MCP协议 `mcp_dart` 通过(某种方式)暴露的资源和工具
## 包裹;软件包;程序包
性能影响
- **MCP服务器的设计旨在最小化对性能的影响:**帧渲染
- **\< 2毫秒影响(可忽略不计)**语义查询
- **对于典型应用(\<1000个节点),完成时间小于2秒**错误捕获
- **异步,不阻塞错误处理程序**记忆
## 错误数据库约5-10MB(保留策略可配置)
做出贡献
欢迎贡献!这是一个开源项目。 [仓库:](https://github.com/moinsen-dev/mcp-frontend-heor)
## https://github.com/moinsen-dev/mcp-前端-heor(注:这里的“heor”可能是特定项目或分支的名称,根据上下文无法确定其准确含义,因此直接音译。在实际应用中,应根据具体情况或项目文档来确定其确切含义。)
许可证 [MIT 许可证 - 详见](LICENSE) 许可证
## 文件中有详细信息。
- **[文档](SETUP.md)** SETUP.md 翻译为中文是:“安装指南/设置说明.md”
- **[- 安装、配置以及平台特定设置](HOW_TO.md)** HOW_TO.md 翻译为中文是:“如何操作指南.md” 或者简化为 “操作指南.md”,其中“.md”表示这是一个Markdown格式的文件
- **[- 使用指南、小部件、测试以及最佳实践](KNOW_HOW.md)** KNOW_HOW.md 翻译为中文是:“知识技能.md”(其中,“.md”是Markdown文件格式的扩展名,通常用于编写和格式化文档)
- **[- 架构、实现细节和故障排除](example/README.md)** 示例应用程序
## - 完整演示应用程序
- [了解更多](https://modelcontextprotocol.io)
- [模型上下文协议(MCP)](https://claude.ai/claude-code)
- [克劳德·科德](https://docs.flutter.dev/development/accessibility-and-localization/accessibility)
## Flutter 语义(或语义分析)
- **支持**问题 [:](https://github.com/moinsen-dev/mcp-frontend-heor/issues)
- **GitHub Issues(GitHub问题)**讨论 [:](https://github.com/moinsen-dev/mcp-frontend-heor/discussions)
______________________________________________________________________
**GitHub 讨论区**