mcpField
F
flutter-mcp-toolkit-custom-tools

flutter-mcp-toolkit-custom-tools

github.com/arenukvern开发39460 次安装2 周前更新
代码仓库

关于 flutter-mcp-toolkit-custom-tools

面向 Flutter 开发者的技能,介绍如何通过动态注册表添加应用专属的 MCP 工具和资源,并说明条目类型选择、注册方式与 Agent 发现流程。

主要功能

  1. 01选择工具或只读资源
  2. 02在应用启动时注册条目
  3. 03定义严格的 JSON Schema
  4. 04发现并调用应用条目
  5. 05避免生命周期与命名冲突

适用场景

  1. 01向 Agent 提供购物车摘要
  2. 02提供只读路由或诊断数据
  3. 03添加带参数的应用操作
  4. 04排查动态条目未显示的问题

MCP 相关

介绍如何在 Flutter 进程中注册自定义工具和资源,并通过动态注册表向 MCP 客户端公开。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/arenukvern/mcp_flutter --skill flutter-mcp-toolkit-custom-tools

安装后在 Claude Code 中输入/flutter-mcp-toolkit-custom-tools确认已加载。

详细介绍

自定义 MCP Toolkit 工具与资源(动态注册表)

当捆绑的 MCP 工具(截图、语义快照、点击等)不够用,且你需要特定于应用的读取接口或操作时使用——例如购物车总额、功能标志、精心整理的内部状态调试快照。条目在 Flutter 进程中注册,并通过动态注册表暴露给 Agent。

迁移: 旧版调用条目类型已在 intentcall Phase 6b 中移除。请使用 AgentCallEntry 或 mcpToolkitTool / mcpToolkitResource。参见 flutter-mcp-toolkit-intentcall-migration。

边界: 在此处更改应用发现、Flutter VM-service 扩展或 应用自有调试接口。请在上游 IntentCall 仓库中更改规范注册表/会话语义、 架构策略、平台投影或发布行为。

选择合适的原语

需求使用
一次性读取简单值fmt_evaluate_dart_expression(无需更改应用代码)。
稳定的只读载荷(诊断信息、JSON 快照、“当前路由”)AgentCallEntry.resource + fmt_client_resource。当契约类似“GET”且具备幂等性时,优先使用资源。
带参数或会修改状态的操作,或可复用的命名操作AgentCallEntry.tool + fmt_client_tool。

处理程序签名

原生 AgentCallEntry(新代码首选)

处理程序接收 AgentArguments(Map<String, Object?>)并返回 AgentResult:

import 'package:mcp_toolkit/mcp_toolkit.dart';

final tool = AgentCallEntry.tool(
  namespace: 'app',
  name: 'cart_get_snapshot',
  description: 'Return current cart total and items for a user.',
  inputSchema: const {
    'type': 'object',
    'additionalProperties': false,
    'properties': {
      'userId': {'type': 'string'},
    },
    'required': ['userId'],
  },
  handler: (final args) async {
    final userId = args['userId']?.toString() ?? '';
    final cart = CartRepository.instance.forUser(userId);
    return AgentResult.success(
      message: 'ok',
      data: {
        'total': cart.total,
        'items': cart.items.map((final i) => i.toJson()).toList(),
      },
    );
  },
);

await MCPToolkitBinding.instance.addEntries(entries: {tool});
旧版 MCPToolDefinition + MCPCallResult(桥接)

内置工具包仍使用 mcpToolkitTool / mcpToolkitResource,以适配 Map<String, String> 服务扩展处理程序:

final tool = mcpToolkitTool(
  namespace: 'app',
  handler: (final request) async {
    final userId = request['userId'] ?? '';
    return MCPCallResult(
      message: 'ok',
      parameters: {'userId': userId},
    );
  },
  definition: MCPToolDefinition(
    name: 'cart_get_snapshot',
    description: 'Return current cart total and items for a user.',
    inputSchema: ObjectSchema(
      properties: {
        'userId': StringSchema(),
      },
      required: ['userId'],
    ),
  ),
);
  • 线上传输的工具参数是以架构属性名称为键的字符串——使用 int.tryParse、jsonDecode 等进行解析。
  • 在应用端不要使用 request.arguments。

优先在 bootstrapFlutter(runApp: ...) 之前调用 MCPToolkitBinding.instance.addEntries(entries: { ... }),这样工具/资源可在同一处注册,并设置 zone/错误处理。

在启动时仅注册一次——不要在 build 或每个组件的 initState 中注册。

自定义资源

final resource = AgentCallEntry.resource(
  namespace: 'app',
  name: 'app_cart_digest',
  description: 'Compact cart summary for agents (read-only).',
  mimeType: 'application/json',
  handler: (final args) async => AgentResult.success(
    message: 'Cart digest',
    data: {
      'itemCount': CartRepository.instance.visibleCount,
      'currency': CartRepository.instance.currencyCode,
    },
  ),
);

或者通过桥接方式:

mcpToolkitResource(
  namespace: 'app',
  definition: MCPResourceDefinition(
    name: 'app_cart_digest',
    description: 'Compact cart summary for agents (read-only).',
    mimeType: 'application/json',
  ),
  handler: (final request) async => MCPCallResult(
    message: 'Cart digest',
    parameters: {'itemCount': 3},
  ),
),
  • name 必须为 snake_case。已发布的资源 URI 遵循 visual://localhost/... 约定;Agent 使用 fmt_client_resource,并通过 fmt_list_client_tools_and_resources 获取资源列表。

架构规则(工具)

MCP 服务会强制执行严格的 JSON Schema:

  • 除非你有意接受任意键,否则优先设置 additionalProperties: false。
  • 对处理程序会无条件读取的所有字段标记为 required。
  • AgentResult.data / MCPCallResult.parameters 必须可序列化为 JSON。

从 Agent 端发现

  1. fmt_list_client_tools_and_resources——列出应用注册的工具和资源。
  2. fmt_client_tool——使用 JSON 参数按名称调用动态工具。
  3. fmt_client_resource——从列表中的 URI 获取已注册资源。

如果预期内容未出现:确认 addEntries 已完成(使用 await),然后执行热重启。

生命周期注意事项

  • 热重载时从组件代码调用 addEntries → 会重复注册。请在 main() / bootstrap 中注册一次。
  • 仅限调试模式——发布版本不会暴露 VM service 扩展。
  • 命名: 应用使用扁平的全局命名空间。请为工具/资源添加前缀(cart_、flags_、nav_)。如果内置条目已使用某个名称,自定义条目会被跳过且不会发出警告;内置条目会处理调用,自定义处理程序不会运行。
  • 命名运行中的实例: 使用 MCPToolkitBinding.instance.setAppIdentity(label: 'Fleet app · staging'),并在名称发生变化时再次调用(登录、工作区切换)。发现时会读取该标签;你自行创建的名为 app_identity 的工具也属于上述冲突之一。

当 Agent 为用户的应用创建界面时

  1. 确保 pubspec.yaml 中包含 mcp_toolkit。
  2. 添加返回 Set<AgentCallEntry> 或调用一次 addEntries 的 lib/mcp_tools/<domain>_surfaces.dart。
  3. 在 bootstrapFlutter(...) 之前通过 addEntries(...) 接入——切勿在 StatefulWidget 生命周期中接入。
  4. 使用精简的架构;热重启;然后在首次调用客户端之前运行 fmt_list_client_tools_and_resources。

安全性和范围

  • 将处理程序视为强大的调试钩子:避免使用机密信息和未经检查的 IO。
  • 保持处理程序精简:委托给现有的应用服务。

常见陷阱

  • 混用 AgentArguments 和 Map<String, String>——选择一种 API(原生 API 或 mcpToolkitTool)。
  • addEntries 缺少 await → 在发现前发生竞态。
  • inputSchema 与处理程序不同步 → Agent 会信任架构;请同时更新两者。

相关内容

  • flutter-mcp-toolkit-intentcall-migration——CLI 迁移工具,用于破坏性升级
  • flutter-mcp-toolkit-guide → 检查 / 控制 / 调试技能
  • 仓库 ARCHITECTURE.md → “动态注册表架构”

评论

支持 Markdown