mcp_toolkit 3.0.0
mcp_toolkit: ^3.0.0 copied to clipboard
Flutter MCP Toolkit to add Flutter-specific methods to the MCP server
MCP Toolkit for Flutter #
Note
This is not official package - it's a personal project.
For official package - please see ai repository
This package is a core component of the mcp_flutter project. It acts as the "client-side" library within your Flutter application, enabling the Model Context Protocol (MCP) MCP Server to perform Flutter-specific operations like retrieving application errors, capturing screenshots, and getting view details.
Note
Please notice:
- The architecture of package may change significantly.
Data Transparency #
This package is designed to be transparent and easy to understand. It is built on top of the Dart VM Service Protocol, which is a public protocol for interacting with the Dart VM.
To make it simple and customizable - it divided into groups of methods which acts as method handlers.
For example, the default first-pass path is bootstrapFlutter().
All methods are available only in debug mode and wrapped in assert statements.
await MCPToolkitBinding.instance.bootstrapFlutter(
additionalEntries: {
MCPCallEntry.resource(
definition: MCPResourceDefinition(
name: 'app_runtime_status',
description: 'Read-only app diagnostics',
mimeType: 'application/json',
),
handler: (final request) => MCPCallResult(
message: 'App runtime diagnostics',
parameters: {'ready': true},
),
),
},
runApp: () => runApp(const MyApp()),
);
App-side permission bridging is separate and opt-in:
MCPToolkitBinding.instance
..initialize()
..initializeFlutterToolkit()
..initializeFlutterPermissionToolkit(delegate: MyPermissionDelegate());
Features #
- Auto register tools and resources in MCP server:
addMcpTool(
MCPCallEntry.tool(
definition: MCPToolDefinition(
name: 'calculate_fibonacci',
description: 'Calculate the nth Fibonacci number and return the sequence',
inputSchema: ObjectSchema(
required: ['n'],
properties: {
'n': IntegerSchema(
description: 'The position in the Fibonacci sequence (0-100)',
minimum: 0,
maximum: 100,
),
},
),
),
handler: (final request) {
final n = int.tryParse(request['n'] ?? '0') ?? 0;
return MCPCallResult(
message: 'Fibonacci number at position $n is ${fibonacci(n)}',
parameters: {'result': fibonacci(n)},
);
},
),
);
- VM Service Extensions: Registers a set of custom VM service extensions (e.g.,
ext.mcp.toolkit.app_errors,ext.mcp.toolkit.view_screenshots,ext.mcp.toolkit.view_details,ext.mcp.toolkit.semantic_snapshot,ext.mcp.toolkit.tap_widget, …). - Error Reporting: Captures and makes available runtime errors from the Flutter application.
- Screenshot Capability: Allows external tools to request screenshots of the application's views.
- Application Details: Provides a mechanism to fetch basic details about the application's views.
- Semantic Snapshot + Gestures (
SemanticSnapshotService,GestureInteractionService): Compact JSON snapshot of interactive widgets with stable refs, plus ref-driventap/long_press/enter_text/scroll/swipe/dragusing a two-tier (semantic-action → pointer-event) dispatch. - Log Capture (
LogCaptureService): Ring buffer of recentprint/debugPrintoutput surfaced viaget_recent_logs. - Optional Permission Bridge: Lets the app expose permission status/request/open-settings handlers only when you register a delegate.
Integration #
-
Add as a Dependency: Add
mcp_toolkitto your Flutter project'spubspec.yamlfile.If you have the
mcp_flutterrepository cloned locally, you can use a path dependency:dependencies: flutter: sdk: flutter # ... other dependencies mcp_toolkit: ^3.0.0 # Use the latest versionThen, run
flutter pub getin your Flutter project's directory. -
Initialize in Your App: In your Flutter application's
main.dartfile, use the canonical bootstrap path:import 'package:flutter/material.dart'; import 'dart:async'; import 'package:mcp_toolkit/mcp_toolkit.dart'; Future<void> main() async { await MCPToolkitBinding.instance.bootstrapFlutter( additionalEntries: { MCPCallEntry.tool( definition: MCPToolDefinition( name: 'calculate_fibonacci', description: 'Calculate the nth Fibonacci number', inputSchema: ObjectSchema( properties: { 'n': IntegerSchema(description: 'Fibonacci position'), }, required: ['n'], ), ), handler: (final request) { final n = int.tryParse(request['n'] ?? '0') ?? 0; return MCPCallResult( message: 'Calculated Fibonacci number for position $n', parameters: {'result': fibonacci(n)}, ); }, ), MCPCallEntry.resource( definition: MCPResourceDefinition( name: 'app_runtime_status', description: 'Read-only runtime diagnostics', mimeType: 'application/json', ), handler: (final request) => MCPCallResult( message: 'Runtime diagnostics', parameters: {'ready': true, 'screen': 'home'}, ), ), }, runApp: () => runApp(const MyApp()), ); } // ... rest of your app codebootstrapFlutter()does the boring parts in one place:WidgetsFlutterBinding.ensureInitialized(),initialize(),initializeFlutterToolkit(), optional app entry registration, and zone error forwarding viahandleZoneError.Keep the older low-level calls only when you need custom startup choreography.
-
Optional: Register an App-Side Permission Delegate: Keep
initializeFlutterToolkit()unchanged and add the permission bridge only if the app owns the relevant permission flow.final class MyPermissionDelegate implements MCPPermissionDelegate { @override Iterable<String> listSupportedPermissionKinds() => const <String>[ 'visual_capture', ]; @override Future<MCPPermissionResult> getPermissionStatus({ required final String kind, }) async => const MCPPermissionResult( kind: 'visual_capture', status: 'granted', canRequest: false, canOpenSettings: false, ); @override Future<MCPPermissionResult> requestPermission({ required final String kind, }) async => await getPermissionStatus(kind: kind); @override Future<MCPPermissionResult> openPermissionSettings({ required final String kind, }) async => await getPermissionStatus(kind: kind); } MCPToolkitBinding.instance.initializeFlutterPermissionToolkit( delegate: MyPermissionDelegate(), );When the delegate is present,
mcp_toolkitregisters:permissions_supported_kinds,permission_status,request_permission, andopen_permission_settings. Without a delegate, those entries are not exposed.
Golden Path #
- Add
mcp_toolkitto your app. - Call
bootstrapFlutter(...)inmain(). - Launch the app in debug mode.
- Run
flutter-mcp-toolkit validate-runtime(pass--targetor global--vm-service-uriwithapp.debugPort.wsUri; hostdesktop_windowfailures retry once withflutter_layer— seedata.summary.captureFallbackUsed). - Then use dynamic registry commands in this order:
fmt_list_client_tools_and_resources,fmt_client_resource,fmt_client_tool.
Use resources for read-only state, tools for actions, and prefer lowercase underscore names.
Agent authoring (skills) #
End-user docs for AI assistants live in the mcp_flutter repo:
- Cursor / Codex plugin (
plugin/skills/): start withflutter-mcp-toolkit-guide, thenflutter-mcp-toolkit-custom-toolswhen registeringMCPCallEntrytools or resources from app code. - Claude Code marketplace plugin (
plugin/skills/):flutter-mcpfor driving the app;flutter-mcp-toolkit-custom-toolsfor the same registration workflow.
Run make sync-skills after editing plugin skills so mcp_server_dart/lib/src/skill_assets.g.dart stays in sync.
Role in mcp_flutter #
For the full setup and more details on the MCP Server and AI tool integration, please refer to the main QUICK_START.md in the root of the mcp_flutter repository.
🤝 Contributing #
Contributions are welcome! Please feel free to submit pull requests or report issues on the GitHub repository.
📖 Learn More #
📄 License #
MIT - Feel free to use in your projects!
Flutter and Dart are trademarks of Google LLC.