FlutterSDK Artisan について
FlutterSDK Artisanは、FlutterおよびDartプロジェクト向けのDart製CLIフレームワーク兼stdio MCPサーバーです。コマンド登録、スキャフォールディング、プラグイン導入、コード生成、実行中のFlutterアプリの制御をまとめています。
主な機能
- 01統合コマンドレジストリ
- 02プロジェクトとコマンドのスキャフォールディング
- 03宣言型プラグイン導入
- 04可逆で冪等なインストール
- 05ホットリロードとVM制御
- 06アプリ操作・状態確認用MCPツール
活用シーン
- 01FlutterまたはDartプロジェクトのCLI構築
- 02プラグインの導入と変更の取り消し
- 03エージェントから実行中のFlutterアプリを操作
- 04プロジェクトのコマンド生成と登録
MCP 対応
stdio JSON-RPCのMCPサーバーは、アプリのライフサイクルと状態確認のツールに加え、プラグイン提供のツールも公開します。`mcp:install`コマンドはMCPクライアント設定を書き込みます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Artisan
Flutter と Dart 向けの、組み合わせ可能な CLI フレームワークおよび stdio MCP サーバーです。
スキャフォールディング、コード生成、トランザクション対応のプラグインインストール、ホットリロードのオーケストレーション、REPL、AI エージェント向けツールインターフェースを 1 つのバイナリにまとめています。
Artisan を選ぶ理由
Dart の CLI は断片化しています。各パッケージが独自のインストール手順、独自のスキャフォールドスクリプト、独自に手編集するエントリーポイントを作っています。5 つのツールを採用したチームでは、bin/*.dart ラッパーが 5 つ、README のインストール手順が 5 つでき、マージミスによってビルドが気付かないうちに壊れる可能性も 5 倍になります。実行中のアプリを操作したい AI エージェントは、共通のツールインターフェースがないため、その場しのぎのシェルスクリプトに頼ることになります。
Artisan はこれを解決します。 1 つのバイナリにすべてのコマンドを登録し、1 つのプロトコルですべてのプラグインインストールを記述し、1 つの stdio MCP サーバーでスタック全体を AI エージェントに公開します。
# Before, the painful manual setup ritual
edit pubspec.yaml # add the plugin dependency
edit bin/<custom>.dart # wire the provider
edit lib/main.dart # register the config factory
edit android/app/src/AndroidManifest.xml # add the permission
edit ios/Runner/Info.plist # add the entry
write .env stub # remember which keys
restart the app and hope nothing collided
# After, the Artisan way
dart pub add fluttersdk_artisan
dart run fluttersdk_artisan install
dart run fluttersdk_artisan plugin:install <name>
php artisan を知っていれば、動詞の形はすでにおなじみです。実装は純粋な Dart 3.4+ で、フレームワークのコアに Flutter ランタイムへの依存はありません。
機能
| 機能 | 説明 | |
|---|---|---|
| 🎼 | コマンドレジストリ | ArtisanRegistry が、登録済みのすべての ArtisanServiceProvider からコマンドを収集し、起動時に重複を検出します |
| 🧰 | 22 個の組み込みコマンド | ライフサイクル、スキャフォールディング、プラグイン管理、MCP、イントロスペクション、コード生成を 1 つのバイナリで提供します |
| ✍️ | シグネチャ DSL | String get signature => 'cmd:name {arg} {--flag}'、Dart 3 のレコード形式パーサー。必要に応じて ArgParser にフォールバックします |
| 🤖 | MCP サーバー | dart_mcp を基盤とする Stdio JSON-RPC サーバーで、基盤機能とプラグインのツールを AI エージェントに公開します |
| 🌳 | Magic 非依存パス | install は通常の Flutter および Dart プロジェクト用の標準ラッパーを書き込み、フレームワークへの依存はありません |
| 🔌 | プラグインプロトコル | 宣言型マニフェスト install.yaml と、PluginInstaller の柔軟な DSL による代替手段を提供します |
| 🔄 | 冪等なインストール | 先読みアンカー付き正規表現の挿入と、名前による置換レジストリを採用し、インストールを再実行しても安全な no-op になります |
| ↩️ | 取り消し可能な操作 | 適用したすべての操作を .artisan/installed/<plugin>.json に記録し、plugin:uninstall が逆順に処理します |
| 🪞 | VM Service フック | tinker、reload、hot-restart が ext.* 拡張機能を介して実行中の Flutter VM を直接操作します |
| 🎯 | コンテキスト対応ジェネレーター | make:command はプラグインと利用側のどちらのコンテキストかを検出し、make:plugin は自動的に Magic モードへ切り替わります |
| 🧪 | テスト可能なプリミティブ | VirtualFs と InMemoryFs、InstallContext.test、ArtisanContext.bare、BufferedOutput によるキャプチャ |
クイックスタート
1. インストールとスキャフォールド
dart pub add fluttersdk_artisan
dart run fluttersdk_artisan install
install は bin/dispatcher.dart(runArtisan(...) を呼び出すコンシューマーのエントリーポイント)と、バレル(lib/app/_plugins.g.dart、lib/app/commands/_index.g.dart)を書き込みます。その後、make:fast-cli を自動で連続実行するため、すぐに bin/fsa を使えます。再実行しても冪等です。上書きするには --force を渡します。
スキャフォールド後、コンシューマーラッパーを使って組み込みコマンドを実行します。
dart run artisan list
dart run artisan doctor
dart run artisan start --device=chrome
2. プラグインをインストールする
dart pub add awesome_plugin
dart run fluttersdk_artisan plugin:install awesome_plugin
プラグインには、install.yaml マニフェスト(宣言型で、ManifestInstaller が走査します)を含める方法と、PluginInstaller を直接操作する ArtisanInstallCommand サブクラスを含める方法があります。どちらの場合も、レジストリは適用されたすべての操作を記録するため、後で plugin:uninstall を安全に実行して元に戻せます。
プラグインのコマンドは自動的に表示されます。fluttersdk_dusk をインストールすると、dart run artisan list に新しい dusk:* エントリーが独自の名前空間セクションに表示されます。
3. AI エージェント用に MCP サーバーを接続する
./bin/fsa mcp:install
# or, on Windows / when bin/fsa is absent:
# dart run fluttersdk_artisan mcp:install
mcp:install は .mcp.json の mcpServers.fluttersdk エントリーを書き込むか、更新します。インストール後、MCP クライアントを一度再接続してください(Claude Code の場合:/mcp reconnect fluttersdk)。サーバーは stdio JSON-RPC モードで起動し、10 個の基盤ツール(artisan_start、artisan_stop、artisan_status、artisan_logs、artisan_restart、artisan_reload、artisan_hot_restart、artisan_doctor、artisan_list、artisan_tinker)に加えて、プラグインが提供するツールを公開します。
詳しいセットアップ手順は、MCP セットアップガイドをお読みください。
コマンド
Artisan には、6 つの名前空間にわたる 22 個の組み込みコマンドがあります。各コマンドは、signature 文字列と handle() メソッドを備えた final class X extends ArtisanCommand です。
| 名前空間 | 数 | コマンド |
|---|---|---|
| ライフサイクル | 7 | start、stop、status、logs、restart、reload、hot-restart |
| スキャフォールディング | 4 | make:plugin、make:command、make:fast-cli、install |
| プラグイン管理 | 3 | plugin:install、plugin:uninstall、plugins:refresh |
| MCP | 3 | mcp:serve、mcp:install、mcp:uninstall |
| イントロスペクション | 4 | help、list、doctor、tinker |
| コード生成 | 1 | commands:refresh |
主な機能:
# Lifecycle
dart run artisan start --device=chrome # spawn flutter run, record the session under ~/.artisan/sessions/<project>/
dart run artisan reload # send r (hot reload) via FIFO bridge to detached process
dart run artisan hot-restart # send R (hot restart, drops Dart state)
# Scaffolding
dart run artisan make:plugin awesome # 7-file plugin skeleton, auto-upgrades to magic-mode when applicable
dart run artisan make:command Greet # context-aware: plugin vs consumer context, auto-registers in provider
dart run artisan make:fast-cli # compile artisan to native binary at bin/fsa (~50ms startup vs ~3s)
# Introspection
dart run artisan tinker # connected REPL against the running VM
dart run artisan tinker --eval='1 + 1' # one-shot evaluation flag for automation
dart run artisan doctor # preflight checks: flutter + dart on PATH, default port availability
コマンドの一覧と、各コマンドのフラグのリファレンスはコマンドカタログをご覧ください。
独自のコマンドを作成する
make:command は ArtisanCommand を継承する final class をスキャフォールドし、最も近いサービスプロバイダーに自動登録します。シグネチャ DSL は 1 つの文字列から引数とフラグを解析し、handle() メソッドは型付きの ArtisanContext を受け取ります。
final class GreetCommand extends ArtisanCommand {
@override
String get signature => 'greet {name} {--shout}';
@override
String get description => 'Greet a person by name.';
@override
Future<int> handle(ArtisanContext context) async {
final name = context.input.argument('name');
final shout = context.input.option('shout') == 'true';
final greeting = shout ? 'HELLO, ${name.toUpperCase()}!' : 'Hello, $name';
context.output.success(greeting);
return 0;
}
}
シグネチャ DSL で表現できないケース(位置指定の可変長引数、相互排他的なフラググループ)では、void configure(ArgParser parser) をオーバーライドし、context.input.results から直接読み取ります。シグネチャ DSL の文法については、シグネチャ DSL リファレンスをご覧ください。
プラグインプロトコル
Artisan プラグインは、ManifestInstaller が読み込む宣言型マニフェストである install.yaml で、インストール時に配置するファイルを宣言します。このマニフェストは、publish(コピーするファイル)、magic.provider と magic.configFactory と magic.routes(フレームワークの接続設定)、native.android(権限、metaData、gradle プラグイン、gradle 依存関係)、native.ios と native.macos(plist エントリ、pod エントリ)、native.web(head への挿入、meta タグ)、env(デフォルト値を含む環境変数の宣言)、prompts(対話形式のインストールプロンプト)、placeholders(プロンプトの回答からのトークン解決)、bootstrap_command(インストール後のヒント)をサポートしています。スキーマのリファレンスは、install.yaml スキーマを参照してください。
最小構成の install.yaml は次のようになります。
publish:
- from: stubs/config.dart
to: lib/config/awesome.dart
magic:
provider: package:awesome/awesome_provider.dart
configFactory: package:awesome/config.dart
native:
android:
permissions:
- android.permission.INTERNET
ios:
plistEntries:
NSCameraUsageDescription: "We need the camera to scan codes."
env:
AWESOME_API_KEY:
default: ""
comment: "API key for awesome.example.com"
bootstrap_command: "Run dart run artisan awesome:bootstrap after install."
YAML スキーマで表現できない実行時の分岐が必要なプラグインでは、ArtisanInstallCommand をサブクラス化して、PluginInstaller を直接操作します。DSL では、ファイル操作(writeFile、publishConfig、mergeJson)、ソースへの挿入操作(injectImport、injectBefore、injectAfter、injectProvider、injectConfigFactory、injectRoute)、ネイティブ操作(injectAndroidPermission、injectIosPlistEntry など)、環境変数操作(injectEnvVar)を利用できます。すべての操作は保留されてまとめて適用され、commit(dryRun:, force:) が実行されるまで書き込みは行われません。
final class AwesomeInstallCommand extends ArtisanInstallCommand {
@override
String get signature => 'awesome:install';
@override
Future<int> handle(ArtisanContext context) async {
final apiKey = await installer.ask('Enter the awesome API key:');
installer
..injectImport('lib/main.dart', 'package:awesome/awesome.dart')
..injectConfigFactory('Awesome.configFactory')
..injectEnvVar('AWESOME_API_KEY', defaultValue: apiKey)
..injectAndroidPermission('android.permission.INTERNET');
final result = await installer.commit(dryRun: false, force: false);
return result is Success ? 0 : 1;
}
}
DSL の詳細は、PluginInstaller DSL リファレンスを参照してください。
操作は冪等性を備えており(先読みアンカー付き正規表現で、対象のコードがすでに存在する場合はスキップします)、アトミックです(すべての書き込みは .tmp への書き込みとアトミックなリネームを経由するため、並行して読み取る処理に不完全な状態が見えることはありません)。また、可逆性も備えており、適用した各操作は改ざん検出用のコンテンツハッシュとともに .artisan/installed/<plugin>.json に記録され、アンインストール時に利用されます。
MCP サーバー
CLI コマンドを実行するバイナリは、stdio JSON-RPC 経由で Model Context Protocol ツールも提供します。別プロセスも追加パッケージも必要ありません。サーバーは公式の dart_mcp SDK 上に構築されており、2 つのツールレイヤーを提供します。
基盤ツール(常時有効な10個)。 artisan CLI の厳選されたサブセットを MCP ツールとして提供するため、AI エージェントはチャットから離れずに Flutter アプリを起動できます。ツールは artisan_start、artisan_stop、artisan_status、artisan_logs、artisan_restart、artisan_reload、artisan_hot_restart、artisan_doctor、artisan_list、artisan_tinker です。ディスパッチはレジストリ経由でプロセス内で実行されます。実行中の VM Service が必要なのは artisan_tinker のみです。各コマンドの inputSchema は、基盤となるコマンドの configure(ArgParser) とバイト単位で照合されるため、ワイヤーコントラクトが CLI の仕様から乖離することはありません。
プラグインツール。 ArtisanServiceProvider.mcpTools() のオーバーライドによって提供されます。ディスパッチは ext.* VM Service 拡張機能を経由します。公式の関連プラグインは、それぞれの MCP ツールカタログを専用のリファレンスページで管理しています。
| プラグイン | MCP ツールリファレンス |
|---|---|
fluttersdk_dusk | fluttersdk.com/dusk/mcp/tool-reference |
fluttersdk_telescope | fluttersdk.com/telescope/mcp/tool-reference |
3 層のフィルターパイプライン(.artisan/mcp.json ファイル、ARTISAN_MCP_* 環境変数、mcp:serve の CLI フラグ)を使うと、Cargo 形式の優先順位に従って、オペレーターがツールやパッケージを許可または拒否できます。すべてのレイヤーで拒否が優先されます。実例:
// .artisan/mcp.json
{
"packages": { "deny": ["fluttersdk_telescope"] }
}
# Env (process-scoped, overrides file)
export ARTISAN_MCP_PACKAGES_DENY=fluttersdk_telescope
# CLI (session-scoped, overrides env)
dart run fluttersdk_artisan mcp:serve --exclude-tool artisan_stop
結果:Telescope パッケージはファイルによって除外され、環境変数によっても拒否されます(和集合は冪等です)。さらに、このセッションでは CLI フラグによって artisan_stop が除外されます。
mcp:install がクライアント設定エントリーを書き込むと、MCP 対応の各エージェントは必要に応じてサーバーを起動できます。
// .mcp.json (managed by mcp:install)
{
"mcpServers": {
"fluttersdk": {
"command": "./bin/fsa",
"args": ["mcp:serve"],
"cwd": "."
}
}
}
bin/fsa が存在しない場合(または POSIX シムが適用されない Windows ホストの場合)、mcp:install は代わりに {"command": "dart", "args": ["run", ":dispatcher", "mcp:serve"]} を書き込みます。フォールバックのエントリーポイントを上書きするには --invocation=<executable> を渡します。この場合、mcp:install は {"command": "dart", "args": ["run", "<executable>", "mcp:serve"]} を書き込みます。これは、コンシューマーのエントリーポイントが汎用の :dispatcher ではなくプラグインラッパーである場合(たとえば、dart run fluttersdk_artisan mcp:install --invocation=fluttersdk_dusk)に正しい形式です。優先順位:ホストが POSIX で bin/fsa が存在する場合は bin/fsa が優先されます。それ以外の場合、--invocation が指定されていればそれが優先され、どちらにも該当しなければ :dispatcher が適用されます。
initialize 時にプロジェクトのセッションが記録されていない場合(Flutter アプリが実行されていない場合)、サーバーはオンライン状態を維持し、基盤ツール10個を利用可能にしたまま、プラグインツールを0個登録します。次に VM Service を必要とする tools/call が発生すると、サーバーはメモ化された実行中の future を介して遅延再接続します。これにより、MCP クライアントは Flutter アプリの自然な開発サイクルである起動と停止を、再接続せずに乗り切れます。
セットアップ手順は MCP セットアップガイド をご覧ください。ツールの全リファレンスは ツールリファレンス をご覧ください。
アーキテクチャ
Artisan は lib/src/ 配下でサブシステムを中心に構成されており、各ディレクトリが単一の関心事を担います。
lib/
├── artisan.dart # Single barrel, re-exports the full public API
├── fluttersdk_artisan.dart # Convention sibling, re-exports the same surface
└── src/
├── console/ # ArtisanApplication, ArtisanRegistry, CommandSignature DSL, ArtisanContext
├── commands/ # 21 built-in commands, one final class per file
├── installer/ # PluginInstaller DSL, ManifestInstaller, InstallTransaction, sealed InstallOperation
├── mcp/ # McpServer, McpToolDescriptor, McpFilterConfig (3-layer filter pipeline)
├── helpers/ # FileHelper, ConfigEditor, MainDartEditor, EnvEditor, PlistWriter, StringHelper
├── stubs/ # StubLoader, asset bundle plus filesystem resolution
├── state/ # StateFile, JSON persistence for start, stop, status, mcp:serve discovery
├── tinker/ # Connected REPL primitives over ext.tinker.evaluate
└── vm/ # VmServiceClient, wraps package:vm_service, DDS-aware, no isolate-id cache
起動時のフロー:
runArtisan(args)
↓
ArtisanApplication.create(providers, builtins)
↓
ArtisanRegistry.registerAll(providers + builtins) # collision-detected
↓
[CLI path] dispatch by signature OR [MCP path] collectMcpTools then serve stdio
↓
ArtisanCommand.handle(ArtisanContext)
すべての公開型は final class です。操作セットや結果セットが閉じている箇所では、Dart 3 の網羅性を活用したシールドディスパッチを行います(InstallOperation にはシールドサブクラスが28個、TransactionResult には4個あります)。新しい操作や結果バリアントを追加すると、すべてのディスパッチャーの更新が必要になり、変更が暗黙に取り残されることはありません。
AI エージェントの統合
Artisan を Claude Code、Cursor、GitHub Copilot などの AI コーディングアシスタントと一緒に使えます。MCP サーバーはエージェントにツールへの直接アクセスを提供します。シェルを起動したり、ログ出力をパターンマッチングしたりせずに、Flutter アプリの起動、Dusk 経由でのウィジェット操作、Telescope 経由での HTTP トラフィックの調査、Tinker 経由での Dart 式の評価ができます。
一般的なエージェントのセッションは次のようになります。
[agent] artisan_doctor // verify toolchain
[agent] artisan_start { device: chrome } // launch the app
[agent] <fluttersdk_dusk tool> // capture Semantics tree, drive interaction
[agent] <fluttersdk_telescope tool> // inspect HTTP, logs, exceptions
[agent] artisan_tinker { eval: "User.find(1)" } // poke the running VM
[agent] artisan_stop // tear down
現在のツールカタログについては、各プラグインの MCP ツールリファレンスを参照してください (fluttersdk_dusk、 fluttersdk_telescope)。
接続時に構造化されたプロジェクトコンテキストを読み込むエージェント向けの正式なエントリーポイントは、リポジトリのルートにある llms.txt です(https://fluttersdk.com/artisan/llms.txt でも公開されています)。エージェントが読み取れる形式で、コマンドの一覧、プラグインのプロトコル、MCP ツールカタログを掲載しています。
スキルファイルとエージェントごとのセットアップ手順については、fluttersdk/ai をご覧ください。
ドキュメント
ライブサンプルを含む完全なドキュメントは fluttersdk.com/artisan にあります。
| トピック | |
|---|---|
| はじめに | 概要、要件、最初のコマンド |
| インストール | dart pub add fluttersdk_artisan とコンシューマー用のひな形 |
| クイックスタート | 空のリポジトリから MCP サーバーを実行するまでの 3 ステップ |
| コマンド | 名前空間ごとに分類した 21 個の組み込みコマンド |
| シグネチャ DSL | 引数とフラグの宣言文法 |
| プラグインの作成 | プラグインを作成する 5 ステップの手順 |
| install.yaml スキーマ | すべてのセクション、キー、サンプル |
| PluginInstaller DSL | 手続き型の代替手段に関するリファレンス |
| MCP の概要 | 基盤レイヤーとプラグインのツールレイヤー、ソフトフェイルのライフサイクル |
| MCP のセットアップ | クライアントごとのインストール(Claude Code、Cursor、Continue) |
| MCP ツールリファレンス | すべてのツール、入力スキーマ、呼び出し例 |
貢献
git clone https://github.com/fluttersdk/artisan.git
cd artisan && dart pub get
dart test && dart analyze
変更対象ファイルの範囲では、基準として約 1070 件のテストがすべて成功しています。新しい動作には対応するテストを追加してください(レッド、グリーン、リファクタリング)。dart format lib/ test/ bin/ で差分が生じず、dart analyze が lib/、test/、bin/ のすべてで問題ゼロと報告する必要があります。
プルリクエストを作成する前に、次のコマンドも実行してください。
dart format lib/ test/ bin/ # zero diff
dart analyze # zero issues
dart pub publish --dry-run # validate the publish archive
公開用アーカイブは、圧縮後 500 KB 未満に収めてください。.pubignore は example/、example_magic/、build/、coverage/、およびエディター用のひな形を公開用アーカイブから除外します。公開対象に含めない新しいトップレベルディレクトリを追加する場合は、除外設定も追加してください。
ライセンス
MIT ライセンスです。詳細は LICENSE をご覧ください。
FlutterSDK が心を込めて開発しました
Artisan が時間の節約に役立ったら、スターを付けてください。ほかの人にも見つけてもらいやすくなります。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。