Browser Use
Browser agents and stealth cloud browsers for AI: run web tasks, fill forms, extract data.
Drive live Flutter apps: snapshot the Semantics tree, tap, type, scroll and screenshot.
使っているAIアプリを選んで、設定をコピーしてください。
チェック 3/3 合格 · あなたのパソコンで動きます
まず:どの AI を使っていますか?
使っているアプリを選ぶと、下に手順が表示されます。
Claude はまだ FlutterSDK Dusk につなげません
提供元はまだ MCP Registry にインストール方法を載せていません
ChatGPT はまだ FlutterSDK Dusk につなげません
提供元はまだ MCP Registry にインストール方法を載せていません
B · ウェブ・ブラウザ の中で ChatGPT につなげる別のサーバー
同じカテゴリでよく使われているものから、キーなしでアドレスだけでつなげるものを選びました
Claude Code はまだ FlutterSDK Dusk につなげません
提供元はまだ MCP Registry にインストール方法を載せていません
Cursor はまだ FlutterSDK Dusk につなげません
提供元はまだ MCP Registry にインストール方法を載せていません
VS Code はまだ FlutterSDK Dusk につなげません
提供元はまだ MCP Registry にインストール方法を載せていません
パソコンで動くサーバーです。インストールすると、ツール一覧がAIアプリに表示されます。
誰でも見られる情報をチェックしており、コードは読んでいません。当てはまらない項目は数に入れていません。 · 2026年11月15日にチェック
レジストリ名は、リポジトリを所有するGitHubアカウント fluttersdk で確認済みです
コードの最終更新:今日
MITを使用
これはパソコンで動くため、インターネット上のエンドポイントはありません
パソコンで動き、代わりにローカルの設定を使います
パソコンで動くサーバーです。ツール一覧を読み取れるのは、インターネット上のエンドポイントがある場合だけです
質問、コツの共有、使えないことの報告ができます。「役に立った」の多い順です。
まだレビューはありません
レジストリでこのカテゴリにある有効なすべてのサーバーと比較しています。スターは、公開者がリポジトリの所有者である場合だけ数えます。
当てはまる基本チェック3項目のうち3項目に合格しました。コードは読んでいません。キーやトークンを追加する前に、サーバーがどんなアクセスを求めているかを確認し、必要な権限だけを持つキーを使ってください。
レジストリには必須のキーは載っていません。ただし、最初に使うときにサインインを求めるサーバーもあります。
あなたのパソコンで動きます。必要なときにAIアプリが起動し、データは作者のサーバーを通りません(サーバー自体がオンラインサービスを呼び出す場合を除きます)。
GitHubリポジトリの最終更新は今日、最新バージョン(0.0.13)がレジストリに届いたのは2 か月前です。
Claude Desktop、Claude Code、Cursor、VS CodeなどのMCP対応アプリで使えます。
同じカテゴリには:Browser Use, changedetection.io (official), Apify MCP Server, Actionbook, Flowershow
同じカテゴリでほかの作者のもの。コマンドは確認済み。公式を先に、次にスター順。
カードの見方:↓ 週あたりのダウンロードi★ GitHubスターi3つの柱:レビュー · チェック · 利用状況i更新=最新バージョンをレジストリに公開した日i
Browser agents and stealth cloud browsers for AI: run web tasks, fill forms, extract data.
Official changedetection.io MCP: web page change tracking, back-in-stock and price alerts.
Extract data from any website with thousands of scrapers, crawlers, and automations on Apify Store ⚡
Let your AI agent operate any website through a real, logged-in browser session.
Publish Markdown and HTML from your AI session as a live website. No account needed.
作者のリポジトリから書かれたとおりにコピーしたものです。PopNx MCPは内容を確認・推奨していません。HTML、画像、スクリプトは取り除いています。リンクはこのサイトの外へ移動します。
Tapir
Give your AI agent eyes and hands on a running Flutter app.
Snapshot the Semantics tree, tap, type, scroll, screenshot and profile the live app from one CLI and one MCP server, with no flutter_test harness and no test file between actions.
Documentation · pub.dev · Issues
| Fact | Value |
|---|---|
| Package | tapir |
| Install | dart pub add tapir, then dart run tapir tapir:install |
| Import | package:tapir/tapir.dart (TapirPlugin.install(), behind if (!kReleaseMode)) |
| Entry points | dart run tapir , ./bin/dowel , TapirPlugin.install(), TapirPlugin.enrichers, TapirDowelProvider (package:tapir/cli.dart), dart run tapir mcp:serve |
| Platforms | Any Flutter target that exposes a VM Service in a debug or profile build: Android, iOS, web, macOS, Windows, Linux; viewport and device emulation need Chrome with a CDP port; tapir_hot_reload_and_snap writes to the flutter run stdin FIFO, so it needs a POSIX host; on a Windows host mcp:install writes a dart run entry, never ./bin/dowel |
| Requires | Dart 3.13, Flutter 3.47; a plugin of dowel (^0.0.21) |
| Dependencies | dowel, image, meta, wind_kit_diagnostics_contracts, yaml, the Flutter SDK |
| License | MIT |
dart pub add tapir
dart run tapir tapir:install dart run tapir start --device=macos # dowel records the session every tapir:* command dials dart run tapir tapir:snap
tapir:install patches lib/main.dart (the import, WidgetsFlutterBinding.ensureInitialized() when missing, and TapirPlugin.install() inside a !kReleaseMode guard), then scaffolds the fast ./bin/dowel wrapper and registers tapir as a dowel plugin. Re-running it changes nothing. The installation guide also adds dowel as a direct dependency (dart pub add dowel). Wired by hand, main.dart looks like this:
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:tapir/tapir.dart';
Future main() async { WidgetsFlutterBinding.ensureInitialized(); if (!kReleaseMode) { TapirPlugin.install(); } runApp(const MyApp()); // MyApp is the host app's root widget. }
The guard is !kReleaseMode, not kDebugMode: debug and profile builds carry tapir (tapir:perf_run measures a profile build) and a release build tree-shakes it. Without the guard tapir ships in release, and anyone who reaches that app's VM Service can drive it. --dart-define=TAPIR_DISABLE=1 skips registration in a build that must not expose the extensions. The example/ app gives each verb a live target widget.
dart run tapir tapir:snap --interactiveOnly
| Token | Minted by | Lifetime |
|---|---|---|
e | tapir:snap | The same Semantics node keeps its token across snapshots, and a token outlives its widget. A ref whose element left the tree is relocated by label (reresolved on the response) only when the snapshot recorded a binding for it, the live tree has the same number of nodes with that label and the match sits on the route the ref was minted on; otherwise it fails as defunct and you re-snap |
q | tapir:find, tapir:observe | Re-resolved against the live tree on every action; survives rebuilds |
Narrow a read with --within= , --interactiveOnly and --grep= ; they compose. --includeEnrichers adds Wind state (the host calls Wind.installDebugResolver() from wind_kit, read through wind_kit_diagnostics_contracts) and Magic state (MagicTapirIntegration.install() from package:magic_devtools/tapir.dart, after Magic.init(); it exists only in a magic_devtools release built on tapir, and tapir:install warns and skips it otherwise; see Magic integration). A ref line ending in [offscreen] or [occluded] names why an action would fail before you try it.
dart run tapir tapir:tap --ref=e2 --snapshot=diff
dart run tapir tapir:fill --ref=e1 --text="ada@example.com" --json
Gestures (tap, hover, drag, scroll, dblclick, right_click, triple_click) and text verbs (type, clear, fill, press_key) dispatch real pointer and key events into the widget tree. tap, hover, drag, the click variants, type and fill first pass the gate (clear, scroll, press_key, select_option and set_checkbox skip it), in a fixed order, and a refusal names the reason an agent can branch on:
| Check | Refusal substring | Recovery |
|---|---|---|
| Defunct (preflight) | defunct (...) | Re-snap |
| Enabled | not enabled | Re-snap; the widget may enable later |
| Zero rect | zero rect | Re-snap or re-find |
| Off-viewport (scrolls into view first) | off-viewport | tapir:scroll into view, then retry |
| Stable across two frames | not stable | Wait for the animation; --no-checkStable |
| Receives events (hit test) | obscured by | Dismiss the overlay (tapir:reset_overlays); --no-checkReceivesEvents |
A green tick is dispatch, not effect. Add --json to print the whole response and read the effect block: effect.changed for tap and scroll, effect.verified and effect.value for type, fill and clear. When the hit test could not answer (routine on a web debug build) the response of a gated verb such as tap or type carries a checks block with receivesEvents: indeterminate instead of a silent pass; fill reports only its effect. tapir:run "tap --ref=e5" "snap --grep Counter" batches verbs into one round trip.
dart run tapir tapir:observe --roles=button,textbox # q<N> handles, re-resolved per action
dart run tapir tapir:wait --text="Welcome back" --timeoutMs=5000
| Verb | Returns |
|---|---|
tapir:wait | Waits for --text, --textGone or --expression |
tapir:wait_for_network_idle | Waits until in-flight HTTP requests stay at zero for --idleMs |
tapir:observe | A flat candidate list of interactive widgets with q handles: observe once, act many times (no model call inside tapir) |
tapir:console, tapir:exceptions | In-app debugPrint output and FlutterErrors, overflow included; --since= scopes errors to one action |
tapir:get_routes | The router's location and the top page (tapir:navigate and tapir:navigate_back change it) |
When the app is not producing frames (a hidden window or a backgrounded tab) tapir forces frames outside the web and reports framesForced: true; where it cannot, every response carries a warnings block rather than a stale answer that looks fresh. See frame production.
dart run tapir tapir:screenshot --output=shot.jpg
dart run tapir start --device=chrome --cdp-port=9333 dart run tapir tapir:device --preset=pixel-8
| Surface | Behaviour |
|---|---|
tapir:screenshot | JPEG (default) or PNG of the viewport, or of one widget with --ref (and a sub-rect of it with --rect) |
| Web screenshot | With --cdp-port, the CLI captures through CDP Page.captureScreenshot; the tapir_screenshot MCP tool stays in-isolate and can time out under CanvasKit, so prefer the CLI on web |
tapir:device | Presets iphone-x, iphone-13, iphone-15-pro, pixel-5, pixel-8, ipad-pro-12.9, desktop-1440, desktop-1920 (viewport, DPR, touch, user agent); the emulation ends with the command, the window size stays. tapir:resize --width --height overrides the viewport until exit, or longer with --hold |
tapir:hot_reload_and_snap | Hot reload, then snapshot, screenshot and recent exceptions in one round trip |
dart run tapir tapir:perf_begin --mode=attribution
dart run tapir tapir:tap --ref=e7 dart run tapir tapir:perf_end
| Verb | Does |
|---|---|
tapir:perf_begin, tapir:perf_end | Bracket one interaction; attribution ranks the widget builds that cost time next to Wind and Magic counters, timing reports frame timings you can quote. A session in which the engine rendered nothing is refused (refused: true, exit 1), never reported as zeros that read as fast |
tapir:perf_insight | The rows behind one insight of the last report |
tapir:perf_run, tapir:perf_compare, tapir:perf_campaign | Repeat a scenario from a clean start and write medians, judge one run against another, run a campaign of scenarios from cold starts |
tapir:perf_trace --out=trace.json | The last session as a Chrome Trace JSON for ui.perfetto.dev |
The tapir_* tools ride on the dowel MCP server, so the client config key is dowel. dart run tapir mcp:install writes the entry into .mcp.json: ./bin/dowel mcp:serve when the fast wrapper exists on a POSIX host, and dart run tapir mcp:serve otherwise (always on Windows, where ./bin/dowel is not used). Standard config for any client that reads .mcp.json:
{ "mcpServers": { "dowel": { "command": "./bin/dowel", "args": ["mcp:serve"], "cwd": "." } } }
| Client | Install |
|---|---|
| Claude Code | claude mcp add dowel -- ./bin/dowel mcp:serve, then /mcp reconnect dowel after a change |
| VS Code | code --add-mcp '{"name":"dowel","type":"stdio","command":"dart","args":["run","tapir","mcp:serve"]}' |
| Cursor | .cursor/mcp.json (project) or ~/.cursor/mcp.json (user) |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| Goose, Warp | Paste the standard config into Goose (Advanced settings, Extensions, Add custom extension) or Warp (Settings, AI, Manage MCP Servers) |
| Claude Desktop | claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\) |
| Codex | codex mcp add dowel ./bin/dowel mcp:serve |
| Without tapir | With tapir |
|---|---|
| You hot reload, screenshot, drag the PNG into the chat, paste widget source and ask why the button does nothing. | The agent calls tapir_snap, then tapir_tap on e7; the gate checks the button, the tap lands, a fresh snap confirms it. |
You add Future.delayed and re-run to tell a timing issue from a bug. | The gate refuses with a reason (not stable, obscured by, off-viewport) that names the cause. |
| Do | Because |
|---|---|
Install tapir only behind if (!kReleaseMode) | Anyone who reaches the VM Service of a build that carries tapir can drive the app |
| Start the app with dart run tapir start, not flutter run | Every tapir:* co