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.
Libraries
- mcp_toolkit
- MCP Toolkit for Flutter applications