NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #953 most downloaded on pub.dev
Flutter extensions for AI agent interaction via MCP — lets Claude, Copilot, and Cursor tap, scroll, type, and screenshot your app.
Last release 2 days ago
05 Oct 2026
Ships fairly regularly
a new release about every 2 months
Nearly every release is documented
notes for 11 of 11 stable releases
Nothing withdrawn
no release was ever pulled
8 months old
11 releases · first in 2026
One column per month.
See changelog on pub.dev
get_interactive_elements now reports only primitive-valued properties (bool, num, String, Enum) for every caller. The ButtonStyle, TextStyle, InputDecoration and colour blobs that previously dominated the payload are gone from every level of output, which shrank by about a quarter on the example app. A TextField's decoration.labelText/hintText is now surfaced as label so keyless fields keep a human-readable handleget_interactive_elements now compacts its payload by default (MarionetteConfiguration.compaction defaults to CompactionMode.compact). On top of the primitive filter it drops rendering details and text font metrics, drops a Text element's duplicated data, rounds bounds to whole logical pixels, and reports visible only when an element is not visible — about 65% smaller than before on the example app. Nothing it drops is read by tap, enter_text, scroll_to or swipe, which match on key, identifier, text, type or coordinates. Set compaction: CompactionMode.none to get the full property dump backcompaction parameter to get_interactive_elements (--compaction=<none|compact> in the CLI) that overrides MarionetteConfiguration.compaction in both directions, so an agent can ask for the full payload on an app that keeps the default. CompactionMode deliberately has only none and compact: a third level is planned, but shipping a value that behaves exactly like compact would mislead, and enum values can be added laterisInteractiveElement and shouldStopTraversalAtElement configuration callbacks that receive an Element, and deprecate the Type-based isInteractiveWidget and shouldStopTraversal (#125)get_interactive_elements not recognizing generic built-in widgets (DropdownButton<T>, DropdownButtonFormField<T>, Radio<T>, RadioListTile<T>, PopupMenuButton<T>) and subclasses of built-in widgets, such as ElevatedButton.iconpress_back_button on a page-based Navigator (as produced by go_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 tripping navigator.dart's internal route-lifecycle assertion, which used to fail every navigation for the rest of the session (#113)register/unregister rejecting instance names with dots or colons, such as device IDs like 192.168.1.1:5555 — only /, \, and control characters are disallowed now, and names are encoded into portable, Windows-safe file names on diskmarionette-flutter-drive-app, an Agent Skill shipped inside the marionette_flutter package, installable via dart run skills@ get (Dart's package skills convention) or npx skills add leancodepl/marionette_mcp — see the new "Agent Skill" section in the READMEMarionetteConfiguration(enableSessionReports: true), connect/CLI commands log to a per-run .marionette/sessions/ directory (steps.md, screenshots, and an agent-written report.md) — see Session Reportsset_device_config tool and set-device-config CLI command for overriding text scale, bold text, and platform brightness in a running app — opt in by wrapping your root widget in the new MarionetteDeviceConfigancestor_keys to tap, secondary_tap, double_tap, long_press, swipe, pinch_zoom, scroll_to and enter_text, and a repeatable --ancestor-keys to 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_to keeps scrolling first, so a scope inside a lazily built list worksancestor_keys to get_interactive_elements, and --ancestor-keys to get-interactive-elements, to list only one subtree — the same chain can then be passed to the matcher tools to act inside itidentifier to the matcher tools (--identifier in the CLI), and report each element's identifier in get_interactive_elements (#90)Server error instead of the detail the extension returned — this silently swallowed every validation message and setup instruction, including the get_logs log-collector onboarding helppress_key with enter not submitting the focused text field: it now performs the field's text input action, so onSubmitted runs, while a multiline field still gets a new line (#117)MarionetteBinding.ensureInitialized() silently hanging the app when another binding, such as the one SentryFlutter.init installs, was created first — it now throws an error that says to initialize MarionetteBinding first (#96)connect hanging 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, and hot_reload/hot_restart report failure in that state (#127)scroll_to on 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 routescroll_to missing a target that only comes into view on its final drag, at either end of a listscroll_to being 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 gesturesscroll_to on 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 gesturescroll_to reporting an attempt count instead of the cause when no scrollable could move at all: it now fails with no Scrollable could be scrolled to reveal ittap, double_tap, long_press, secondary_tap, swipe, pinch_zoom, scroll_to) silently doing nothing, and every element being reported visible: 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 inchore: bump mcp_dart to v2.1.0 by @jakubfijalkowski with @Copilot in #71
Full Changelog: v0.5.0...v0.6.0
ExtensionInputSchema/ExtensionParam DSLpress_key tool for dispatching hardware key events with modifiershot_restart tool for fully restarting the app from main()secondary_tap tool for right mouse button clicks on desktopswipe CLI command for element- and coordinate-based swipe/drag gesturesSemantics(label:) and Semantics(value:) in get_interactive_elementsmcp_dart to ^2.1.0 and drop the bespoke Copilot-compat stdio transportDockerfile for building marionette_mcp as a container imagefeat: extract text callback exposes element instead of widget by @thangmoxielabs in #61
element instead of widget by @thangmoxielabs in #61Full Changelog: v0.4.0...v0.5.0
Element instead of Widget to the extractText configuration callback, giving access to the full element context. Migration: change (widget) to (element) and use element.widget to access the widget.swipe/drag, long_press, double_tap, pinch_zoom, and press_back_button..fvmrc.Fix custom text extraction by @jakubfijalkowski in #26
logging by @jakubfijalkowski in #28marionette_cli package with multi-instance CLI supportcall_custom_extension tool for arbitrary VM service extensionsregisterMarionetteExtensionenter_textmarionette_flutter into marionette_logger and marionette_loggingScrollSimulator with reverse scrolling direction and configurable max scroll attemptsonChanged not being called on enter_textMarionetteExtensionErrorSee changelog on pub.dev
hot_reload tool response handlingSee changelog on pub.dev
See changelog on pub.dev
See changelog on pub.dev
initialize callMarionetteBinding.ensureInitialized()Release v0.2.1 with new README
Release v0.2.1 with new README
Update CHANGELOG and bump version to 0.2.0
Update CHANGELOG and bump version to 0.2.0
get_interactive_elementsget_interactive_elements returns only hittable elements nowscroll_to does not assume that the widget is in the treeText is a stopwidget nowRequire Flutter when building marionette_flutter
Require Flutter when building marionette_flutter
logging packageInitial 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 logging package
56
likes
150
points
48.3k
downloads
API reference
leancode.co
MCP server that lets AI agents (Claude, Copilot, Cursor) inspect and interact with running Flutter apps — tap, scroll, type, and screenshot.
Repository (GitHub)
View/report issues
#mcp #ai #claude #agent #copilot
Apache-2.0 ( license )
args , logging , mcp_dart , path , stack_trace , vm_service
Packages that depend on marionette_mcp
56
likes
150
points
48.3k
downloads
API reference
leancode.co
MCP server that lets AI agents (Claude, Copilot, Cursor) inspect and interact with running Flutter apps — tap, scroll, type, and screenshot.
Repository (GitHub)
View/report issues
#mcp #ai #claude #agent #copilot
Apache-2.0 ( license )
args , logging , mcp_dart , path , stack_trace , vm_service
Packages that depend on marionette_mcp
Back
Your coding agent can read these notes before it upgrades. Set up the MCP server →