inkpal_bridge 9.0.0 copy "inkpal_bridge: ^9.0.0" to clipboard
inkpal_bridge: ^9.0.0 copied to clipboard

Turn your running Flutter app into an MCP server. Claude Code, Cursor, Windsurf, Codex, Copilot can inspect, drive, hot-reload it. 79 tools over local HTTP. Zero deps.

inkpal_bridge #

The reliable execution path between your AI and your Flutter app.

pub package pub points GitHub stars

AI writes Flutter code. It can't run it. So it guesses — at the widget tree, at the state, at whether the change compiled. inkpal_bridge closes that loop.

The InkPal loop #

  AI writes  →  hot-reloads  →  drives the UI  →  verifies  →  repeats

Every step is one MCP tool call over a loopback HTTP server your app opens on port 8767. No external CLI, no daemon, no ADB round-trip.

Install #

# pubspec.yaml
dependencies:
  inkpal_bridge: ^9.0.0
// lib/main.dart
import 'package:inkpal_bridge/inkpal_bridge.dart';

void main() => inkpalRunApp(const MyApp());

Paste this into your editor's MCP config once:

{"mcpServers": {"inkpal": {"transport": "http",
  "url": "http://127.0.0.1:8767/mcp"}}}

Restart the editor. Done.

What's unique #

  • Verified execution. Every mutating call returns a verification envelope — did the screen change, did errors fire, did the route move. verify: 'lite' | 'off' on the fast paths.
  • Confidence + evidence. Five mutating tools (tap, scroll, enter_text, navigate_to_route, state_override) now return outcome.confidence (verified / observed / probable / unknown / failed) plus a structured evidence block, and refuse to fire when the caller's expect: {frame_stamp, route, app_identity, build_id} doesn't match.
  • Runtime identity. Every response carries _meta.runtime with session_id, bridge_id, build_id, hot_reload_generation, and 9.0's freshness (semantics_seq / route_seq / hot_reload_seq / frame_stamp) — agents catch stale reads without asking.
  • 79 tools. Inspection, interaction, wait/assert, state time-travel, HTTP memory, hot reload, recording → replay, runtime-health rollup, image cache — all in one Dart package.
  • Zero deps. Just flutter. No third-party runtime deps ever.

Android #

The bridge binds inside the running app. Android emulators need one adb forward per flutter run:

adb forward tcp:8767 tcp:8767

The bridge's welcome banner prints this command when it detects Android. iOS simulator, macOS, Linux, and Windows share loopback — no forward required.

Platforms #

Android, iOS, macOS, Linux, Windows. Flutter web is not currently supporteddart:io HttpServer is unavailable in the browser runtime. The bridge skips its HTTP server on web with a debugPrint and stays inert.

Bundled CLIs #

dart run inkpal_bridge:inkpal tap "Save"
dart run inkpal_bridge:inkpal health
dart run inkpal_bridge:inkpal screenshot --out shot.png
dart run inkpal_bridge:doctor        # nine-check diagnostic
dart run inkpal_bridge:connect       # discover bridge + print editor config

Full release history #

See CHANGELOG.md.


Advanced — routers, state adapters, hooks

go_router — pass your router; route tracking is automatic:

final router = GoRouter(routes: [...]);
inkpalRunApp(MyApp(router: router), router: router);

Other routers — pass an onNavigateToRoute callback:

inkpalRunApp(
  const MyApp(),
  onNavigateToRoute: (route) async => Get.toNamed(route),
);

Live app state — wire an InkPalStateAdapter so state_read, state_watch, state_override reach your Riverpod / Bloc / Provider / GetX / MobX store:

inkpalRunApp(
  const MyApp(),
  stateAdapter: InkPalStateAdapter(
    list: () async => [{'id': 'cart.count', 'kind': 'notifier'}],
    read: (id) async => {'value': cartNotifier.value},
    write: (id, v) async { cartNotifier.value = v as int; return {'success': true}; },
  ),
);

Custom widgets — teach the semantics walker to recognise them:

inkpalRunApp(
  const MyApp(),
  walkerHooks: InkPalWalkerHooks(
    isInteractiveWidget: (w) => w is BrandButton,
    extractTextFrom: (w) => w is BrandButton ? w.label : null,
  ),
);

Default verify mode — set once for every mutating tool:

inkpalRunApp(const MyApp(), defaultVerify: 'lite');

App identity — set once, echoed on every reply so cross-app orchestration can tell which bridge answered:

inkpalRunApp(const MyApp(), appIdentity: 'com.foo.mymapapp');

Emergency kill-switch — even in a debug build:

flutter run --dart-define=INKPAL_BRIDGE=off

MIT-licensed. Bug reports + PRs welcome at github.com/InkPalAI/inkpal_bridge.

5
likes
160
points
745
downloads

Documentation

API reference

Publisher

verified publisherinkpal.ai

Weekly Downloads

Turn your running Flutter app into an MCP server. Claude Code, Cursor, Windsurf, Codex, Copilot can inspect, drive, hot-reload it. 79 tools over local HTTP. Zero deps.

Homepage
Repository (GitHub)
View/report issues

Topics

#mcp #ai #claude #copilot #agent

License

MIT (license)

Dependencies

flutter

More

Packages that depend on inkpal_bridge