mcp (0.2.0)

Published 2026-10-02 06:26:59 +00:00 by Platform

Installation

dart pub add mcp:0.2.0 --hosted-url=

About this package

Embed an MCP server in a Flutter app's debug builds: see and drive every element, take screenshots, read logs and add your own tools. One gateway controls every running app.

mcp

Lets an AI agent see and drive a running Flutter app, like Playwright does for a browser. Debug builds only: in profile and release builds, and on the web, start() does nothing.

Every running app registers itself in one shared file. One gateway, registered once in your MCP client, serves all of them, so there is nothing to configure per app or per port.

Add it to an app

dependencies:
  mcp: ^0.2.0
import 'package:mcp/mcp.dart';

final mcp = Mcp(
  name: 'My App',
  version: '1.0.0',
  state: () => {'user': session.userName},
  tools: [
    McpTool(
      name: 'set_theme',
      description: 'Switch between the light and dark theme.',
      properties: {'dark': {'type': 'boolean'}},
      requiredArguments: ['dark'],
      handler: (arguments) async {
        themeNotifier.value = arguments['dark'] == true ? ThemeMode.dark : ThemeMode.light;
        return McpResult.text('ok');
      },
    ),
  ],
);

Future<void> main() async {
  await mcp.start();
  runApp(const MyApp());
}

Optional: add McpNavigatorObserver() to navigatorObservers so state lists the open pages, and call McpLog.add(line) from your own logger to feed the log tool (debugPrint is captured already).

Optional: wrap the app in McpViewport so window can imitate monitors this screen can't show: other display scales, text sizes and resolutions larger than the screen. It passes the child straight through outside debug builds.

MaterialApp(
  builder: (context, child) => McpViewport(child: child!),
)

Register the gateway once

build.bat
claude mcp add --scope user flutter -- <path to this repo>\MCP.exe

build.bat also writes MCP, a Linux x64 build (Dart cross-compiles it from Windows).

Or run it from source: claude mcp add --scope user flutter -- dart run mcp:gateway.

Flags: --name (the server name clients see, default flutter) and --registry (path of the registry file).

Built-in tools

Tool What it does
state App name, version, open pages and whatever your state callback returns
snapshot Every on-screen element as text: role, name, value, states, actions, position, and a ref
click Tap by ref, by text (exact or partial, case blind, nth for repeats) or by widget key
type Set the text of a field
scroll Scroll the first or a chosen scrollable up, down, left or right
adjust Step a slider up or down
long_press Long-press an element or a position
hover Move the mouse over an element or a position and leave it there (tooltips, hover states)
drag Drag from an element or position to another one, or by dx/dy
press_key Press a key or shortcut on the focused element, for example enter, shift+tab, ctrl+s
window Show the app as on another monitor: monitor ("2560x1440") and scale, or width/height, plus textScale; reset undoes it
wait_for Wait until some text or key is on screen
screenshot PNG of the window, including embedded web views
log Recent log lines

long_press, hover and drag also take x and y, the logical position snapshot prints after @.

window resizes the real window when the size fits this screen at its own scale and text size (Windows). Anything else needs McpViewport: the app then lays out at the imitated size, scale and text size, shrunk to fit the window, and screenshot returns the imitated monitor's pixels.

With more than one app running, pass instance (an id, a pid, a platform or part of the app name). The instances tool lists them.

How it works

The snapshot and the actions use the app's semantics tree, so anything a screen reader can reach is reachable, and a widget you add later is covered with no extra code. Give icon-only buttons a tooltip or Semantics label so they get a name; a widget with only a ValueKey can still be clicked with key.

Each app serves loopback HTTP on a random port with a random bearer token, refuses browser origins and foreign hosts, and keeps itself in %USERPROFILE%\.mcp\instances.json (~/.local/state/Mcp/instances.json elsewhere; MCP_REGISTRY overrides it) with a 5 second heartbeat. The Windows registry stays out of %LOCALAPPDATA% because MSIX hosts such as the Claude desktop app give the processes they start a private copy of AppData, so a gateway started there would never see the apps. Entries not refreshed for 20 seconds are dropped. Apps started by flutter test do not register.

Details
Pub
2026-10-02 06:26:59 +00:00
324
28 KiB
Assets (1)
0.2.0.tar.gz 28 KiB
Versions (4) View all
0.2.0 2026-10-02
0.1.2 2026-10-02
0.1.1 2026-10-01
0.1.0 2026-10-01