Skip to content

Commit ce519e8

Browse files
authored
Add flutter driver tool (#223)
Towards #222 (could close it, but probably we should do some more work to validate it works well). Adds the flutter driver tool, with a curated set of available commands. I decided to expose this as just a single tool, which mirrors exactly the flutter driver extension method. The schema for this is pretty weird and complex - but in general Gemini seems to do OK with it. Note that I only tested the tap/get_text commands, I think that is likely sufficient (really we just need to test we are forwarding commands through, we aren't doing anything special). Also updates the workflow client to handle enums and use updated model names.
1 parent 3bf650e commit ce519e8

File tree

9 files changed

+412
-68
lines changed

9 files changed

+412
-68
lines changed

mcp_examples/bin/workflow_client.dart

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ import 'package:google_generative_ai/google_generative_ai.dart' as gemini;
1515

1616
/// The list of Gemini models that are accepted as a "--model" argument.
1717
/// Defaults to the first one in the list.
18-
const List<String> allowedGeminiModels = [
19-
'gemini-2.5-pro-preview-03-25',
20-
'gemini-2.0-flash',
21-
'gemini-2.5-flash-preview-04-17',
22-
];
18+
const List<String> allowedGeminiModels = ['gemini-2.5-pro', 'gemini-2.5-flash'];
2319

2420
void main(List<String> args) {
2521
final geminiApiKey = Platform.environment['GEMINI_API_KEY'];
@@ -161,8 +157,6 @@ final class WorkflowClient extends MCPClient with RootsSupport {
161157
StreamSinkTransformer.fromHandlers(
162158
handleData: (String data, EventSink<List<int>> innerSink) {
163159
innerSink.add(utf8.encode(data));
164-
// It's a log, so we want to make sure it's always up-to-date.
165-
fileByteSink.flush();
166160
},
167161
handleError: (
168162
Object error,
@@ -552,6 +546,13 @@ final class WorkflowClient extends MCPClient with RootsSupport {
552546
description: description,
553547
nullable: nullable,
554548
);
549+
case JsonType.enumeration:
550+
final schema = inputSchema as EnumSchema;
551+
return gemini.Schema.enumString(
552+
enumValues: schema.values.toList(),
553+
description: description,
554+
nullable: nullable,
555+
);
555556
default:
556557
throw UnimplementedError(
557558
'Unimplemented schema type ${inputSchema.type}',

pkgs/dart_mcp_server/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
failure.
55
* Add failure reason field to analytics events so we can know why tool calls are
66
failing.
7+
* Add a flutter_driver command for executing flutter driver commands on a device.
78
* Allow for multiple package arguments to `pub add` and `pub remove`.
89
* Require dart_mcp version 0.3.1.
910

pkgs/dart_mcp_server/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,9 @@ For more information, see the official VS Code documentation for
140140
| `hot_reload` | Hot reload | Performs a hot reload of the active Flutter application. This is to apply the latest code changes to the running application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
141141
| `get_widget_tree` | Get widget tree | Retrieves the widget tree from the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
142142
| `get_selected_widget` | Get selected widget | Retrieves the selected widget from the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
143-
| `set_widget_selection_mode` | Set Widget Selection Mode | Enables or disables widget selection mode in the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. |
143+
| `set_widget_selection_mode` | Set Widget Selection Mode | Enables or disables widget selection mode in the active Flutter application. Requires "connect_dart_tooling_daemon" to be successfully called first. This is not necessary when using flutter driver, only use it when you want the user to select a widget. |
144144
| `get_active_location` | Get Active Editor Location | Retrieves the current active location (e.g., cursor position) in the connected editor. Requires "connect_dart_tooling_daemon" to be successfully called first. |
145+
| `flutter_driver` | Flutter Driver | Run a flutter driver command |
145146
| `pub_dev_search` | pub.dev search | Searches pub.dev for packages relevant to a given search query. The response will describe each result with its download count, package description, topics, license, and publisher. |
146147
| `remove_roots` | Remove roots | Removes one or more project roots previously added via the add_roots tool. |
147148
| `add_roots` | Add roots | Adds one or more project roots. Tools are only allowed to run under these roots, so you must call this function before passing any roots to any other tools. |

0 commit comments

Comments
 (0)