marionette_mcp 0.7.0
marionette_mcp: ^0.7.0 copied to clipboard
MCP server that lets AI agents (Claude, Copilot, Cursor) inspect and interact with running Flutter apps — tap, scroll, type, and screenshot.
0.7.0 #
- Behaviour change:
get_interactive_elementsnow reports only primitive-valued properties (bool,num,String,Enum) for every caller. TheButtonStyle,TextStyle,InputDecorationand colour blobs that previously dominated the payload are gone from every level of output, which shrank by about a quarter on the example app. ATextField'sdecoration.labelText/hintTextis now surfaced aslabelso keyless fields keep a human-readable handle - Behaviour change:
get_interactive_elementsnow compacts its payload by default (MarionetteConfiguration.compactiondefaults toCompactionMode.compact). On top of the primitive filter it drops rendering details and text font metrics, drops aTextelement's duplicateddata, roundsboundsto whole logical pixels, and reportsvisibleonly when an element is not visible — about 65% smaller than before on the example app. Nothing it drops is read bytap,enter_text,scroll_toorswipe, which match on key, identifier, text, type or coordinates. Setcompaction: CompactionMode.noneto get the full property dump back - Add a
compactionparameter toget_interactive_elements(--compaction=<none|compact>in the CLI) that overridesMarionetteConfiguration.compactionin both directions, so an agent can ask for the full payload on an app that keeps the default.CompactionModedeliberately has onlynoneandcompact: a third level is planned, but shipping a value that behaves exactly likecompactwould mislead, and enum values can be added later - Add
isInteractiveElementandshouldStopTraversalAtElementconfiguration callbacks that receive anElement, and deprecate theType-basedisInteractiveWidgetandshouldStopTraversal(#125) - Fix
get_interactive_elementsnot recognizing generic built-in widgets (DropdownButton<T>,DropdownButtonFormField<T>,Radio<T>,RadioListTile<T>,PopupMenuButton<T>) and subclasses of built-in widgets, such asElevatedButton.icon - Fix
press_back_buttonon a page-basedNavigator(as produced bygo_router) that refuses the pop while a route is still animating in — it now waits for the route transition to finish before popping (other animations, such as a loading spinner, don't hold it up) instead of trippingnavigator.dart's internal route-lifecycle assertion, which used to fail every navigation for the rest of the session (#113) - Fix
register/unregisterrejecting instance names with dots or colons, such as device IDs like192.168.1.1:5555— only/,\, and control characters are disallowed now, and names are encoded into portable, Windows-safe file names on disk - Add
marionette-flutter-drive-app, an Agent Skill shipped inside themarionette_flutterpackage, installable viadart run skills@ get(Dart's package skills convention) ornpx skills add leancodepl/marionette_mcp— see the new "Agent Skill" section in the README - Add opt-in session reports: with
MarionetteConfiguration(enableSessionReports: true),connect/CLI commands log to a per-run.marionette/sessions/directory (steps.md, screenshots, and an agent-writtenreport.md) — see Session Reports - Add
set_device_configtool andset-device-configCLI command for overriding text scale, bold text, and platform brightness in a running app — opt in by wrapping your root widget in the newMarionetteDeviceConfig - Add
ancestor_keystotap,secondary_tap,double_tap,long_press,swipe,pinch_zoom,scroll_toandenter_text, and a repeatable--ancestor-keysto the matching CLI commands, to scope a match to one subtree when the same key repeats across identical subtrees (grid cells, repeated cards, embedded app instances) — keys nest outermost first, only descendants of the last one match, and a key with no element fails the call by name instead of widening the search;scroll_tokeeps scrolling first, so a scope inside a lazily built list works - Add
ancestor_keystoget_interactive_elements, and--ancestor-keystoget-interactive-elements, to list only one subtree — the same chain can then be passed to the matcher tools to act inside it - Add matching by Semantics
identifierto the matcher tools (--identifierin the CLI), and report each element'sidentifieringet_interactive_elements(#90) - Fix extension errors being reported as the generic
Server errorinstead of the detail the extension returned — this silently swallowed every validation message and setup instruction, including theget_logslog-collector onboarding help - Fix
press_keywithenternot submitting the focused text field: it now performs the field's text input action, soonSubmittedruns, while a multiline field still gets a new line (#117) - Fix
MarionetteBinding.ensureInitialized()silently hanging the app when another binding, such as the oneSentryFlutter.initinstalls, was created first — it now throws an error that says to initializeMarionetteBindingfirst (#96) - Fix
connecthanging forever when the app's Dart Development Service stops answering stream subscriptions: it now waits at most 500 ms for the Service stream and continues, andhot_reload/hot_restartreport failure in that state (#127) - Fix
scroll_toon layered UIs: scroll the list the user can reach and stop at the reachable copy of the target, instead of dragging a screen covered by a bottom sheet, dialog, or pushed route - Fix
scroll_tomissing a target that only comes into view on its final drag, at either end of a list - Fix
scroll_tobeing unable to reach targets in long lists: it now scrolls by a share of the visible viewport instead of a fixed 64px, so lists past roughly 170 rows are reachable and shorter ones take far fewer gestures - Fix
scroll_toon screens with more than one scrollable: when the target is not built yet it now tries the two best-ranked reachable scrollables in turn rather than committing to a single guess, so a chip row, tab strip or nav rail no longer swallows the gesture - Fix
scroll_toreporting an attempt count instead of the cause when no scrollable could move at all: it now fails withno Scrollable could be scrolled to reveal it - Fix every pointer gesture (
tap,double_tap,long_press,secondary_tap,swipe,pinch_zoom,scroll_to) silently doing nothing, and every element being reportedvisible: false, in an app whose content is not in the implicit view — as with the desktop windowing API: gestures are now dispatched to, and visibility measured against, the view the element is actually in
0.6.0 #
- Promote schema-bearing custom extensions to first-class MCP tools via the new
ExtensionInputSchema/ExtensionParamDSL - Add
press_keytool for dispatching hardware key events with modifiers - Add
hot_restarttool for fully restarting the app frommain() - Add
secondary_taptool for right mouse button clicks on desktop - Add
swipeCLI command for element- and coordinate-based swipe/drag gestures - Surface
Semantics(label:)andSemantics(value:)inget_interactive_elements - Exit the stdio MCP server on stdin EOF to prevent orphaned processes
- Bump
mcp_dartto^2.1.0and drop the bespoke Copilot-compat stdio transport - Add a
Dockerfilefor buildingmarionette_mcpas a container image
0.5.0 #
- Breaking: Pass
Elementinstead ofWidgetto theextractTextconfiguration callback, giving access to the full element context. Migration: change(widget)to(element)and useelement.widgetto access the widget. - Add gesture support across all layers:
swipe/drag,long_press,double_tap,pinch_zoom, andpress_back_button. - Add video recording with TCP/WS transport and Android auto-fallback.
- Improve screencast stability with broken-pipe race handling, concurrent stop safety, and orphaned session cleanup.
- Improve runtime robustness around input validation, resource cleanup, and non-monotonic timestamp handling.
- Strengthen release CI with explicit minimum-version compatibility checks and Flutter version sourced from
.fvmrc.
0.4.0 #
- Add
marionette_clipackage with multi-instance CLI support - Add
call_custom_extensiontool for arbitrary VM service extensions - Add custom extension registry with
registerMarionetteExtension - Add focused selector to
enter_text - Add version compatibility check on connect
- Decouple logging from
marionette_flutterintomarionette_loggerandmarionette_logging - Improve
ScrollSimulatorwith reverse scrolling direction and configurable max scroll attempts - Fix tap matching widgets behind modal route barriers
- Fix
onChangednot being called onenter_text - Fix pointer device collision with macOS mouse cursor
- Fix extracted text not being exposed in interactive elements
- Ensure correct status code range in
MarionetteExtensionError
0.3.0 #
- Add screenshot resizing configuration
- Fix SIGTERM handling on Windows
- Add GitHub Copilot support
- Require Dart 3.10 for the MCP server
- Fix
hot_reloadtool response handling
0.2.4 #
- Add CI workflow with analyze, format, and version checks
- Add version generation script with validation and robustness
- Replace example symlinks with actual directories in both packages
- Improve project structure and dependencies
0.2.3 #
- Add example symlinks for improved pub.dev package scoring
- Fix documentation lints for angle brackets in code references
0.2.2 #
- Add compatibility for Copilot
initializecall - Make configuration parameter optional in
MarionetteBinding.ensureInitialized()
0.2.1 #
- Update README
0.2.0 #
- Support tapping by widget type
- Support tapping by coordinates
- Return more info in
get_interactive_elements - Add hot reload tool, and return logs only since last hot reload
get_interactive_elementsreturns only hittable elements now- The tools have better naming to conform to the MCP implementations
scroll_todoes not assume that the widget is in the treeTextis a stopwidget now
0.1.0 #
- Initial version of Marionette MCP
- Support for getting the interactive widget tree
- Support for entering text
- Support for tapping and scrolling
- Support for getting logs from
loggingpackage