4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Dart and Flutter MCP server]をゆるーーく最近使って開発し始めましたよーっていうお話とtool追加してみよう

Posted at

はじめに

こんにちは。CAMPFIREでFlutterエンジニアをしているつるみです。

今年はなんといってもAIが怒涛の勢いで普及したの1年でしたね...
もう、Xをひらけば新しいAIの情報が飛び交っていてもう自分は全然ついて行けてませんでした。
あ、ちなみに弊社ではCursor, Devin, geminiなどを使用して開発業務をしています。

MCPいいよーとかみんな言ってるけど、どう使っていいのかさっぱりでした.....
(cursor使い始めた頃にMCP公式の天気予報のチュートリアル触ってみたくらい)

Dart and Flutter MCP server

そんなちんぷんかんぷんだった8月に Dart and Flutter MCP serverがリリースされました

概要を読んでみると

The Dart and Flutter MCP server exposes Dart and Flutter development tool actions to compatible AI-assistant clients. MCP (model context protocol) is a protocol that enables communication between development tools and AI assistants, allowing the assistants to understand the context of the code and perform actions on behalf of the developer.

The Dart and Flutter MCP server can work with any MCP client that supports standard I/O (stdio) as the transport medium. To access all the features of the Dart and Flutter MCP server, an MCP client must support Tools and Resources. For the best development experience with the Dart and Flutter MCP server, an MCP client should also support Roots.

If you are using a client that claims it supports roots but doesn't actually set them, pass --force-roots-fallback to enable tools for managing the roots.

The Dart and Flutter MCP server provides a growing list of tools that grant AI assistants deep insights into your project. Here is an overview of a few things it can do:

Analyze and fix errors in your project's code.
Resolve symbols to elements to ensure their existence and fetch documentation and signature information for them.
Introspect and interact with your running application.
Search the pub.dev site for the best package for a use case.
Manage package dependencies in your pubspec.yaml file.
Run tests and analyze the results.
Format code with the same formatter and config as dart format and the Dart analysis server.

<google 翻訳>
Dart および Flutter MCP サーバーは、互換性のある AI アシスタント クライアントに Dart および Flutter 開発ツールのアクションを公開します。
MCP (モデル コンテキスト プロトコル) は、開発ツールと AI アシスタント間の通信を可能にするプロトコルであり、アシスタントがコードのコンテキストを理解し、開発者に代わってアクションを実行できるようにします。 
Dart および Flutter MCP サーバーは、転送媒体として標準 I/O (stdio) をサポートする任意の MCP クライアントと連携できます。
Dart および Flutter MCP サーバーのすべての機能にアクセスするには、MCP クライアントがツールとリソースをサポートしている必要があります。
Dart および Flutter MCP サーバーで最高の開発エクスペリエンスを実現するには、MCP クライアントがルートもサポートしている必要があります。 
ルートをサポートしていると主張しているものの、実際にはルートを設定していない場合は、--force-roots-fallback を渡してルート管理ツールを有効にしてください。 
Dart および Flutter MCP サーバーは、AI アシスタントがプロジェクトに関する詳細な情報を取得できるようにするツールを随時追加しています。
以下に、このツールでできることの概要をいくつかご紹介します。
- プロジェクトのコード内のエラーを解析・修正する。
- シンボルを要素に解決して存在を確認し、それらのドキュメントと署名情報を取得する。
- 実行中のアプリケーションをイントロスペクトし、操作する。
- pub.dev サイトからユースケースに最適なパッケージを検索する。
- pubspec.yaml ファイルでパッケージの依存関係を管理する。
- テストを実行し、結果を分析する。
- dart フォーマットおよび Dart 分析サーバーと同じフォーマッタと設定でコードをフォーマットする。

ふむふむなるほど🧐🧐🧐🧐
それってAIにやってもらう意味あるのかな...別に自分でコマンド叩けばいいのでは??とその時思い、他のタスクあるし一旦置いておこうとなりました。

そして時は流れ...

11月 FlutterKaigi 2025

弊社では昨年からFlutterKaigiにしれっと参加させてもらってます。
(ほんとは参加レポートを書かないといけないのですが...今年の分はそろそろ書きます!!!絶対に!!4人も参加してるんだからそれくらいは書かないと...🫣🫣🫣)

今年のFlutterKaigiはAIを活用した発表がちらほら増えてきていました。
自分がその中でもDart and Flutter MCP serverを使ってみよーと思った発表がありました。

それがこちらの株式会社Layerx さかいさんのDart and Flutter MCP serverで実現するAI駆動E2Eテスト整備と自動操作です。

こちらの発表を見てエンジニアとして強すぎる...って思ってしまいました...w
Xでよく出てくるsubagentなどをフル活用しているし、すごーーとなりましたw

去年のFlutterKaigiでもアーキテクチャとテストカバレッジ100%にしてるよーなどの発表を聞いてから、ゆるーくレイヤー分けしているのをしっかりちゃんと分けてrepository層とusecase層のテストは100%にしてきました。
UI部分のテストもそろそろ書こうかなと思っていたので、気になっていましたし、ここまでAI活用できるんだと大変勉強になりました🙏

Dart and Flutter MCP serverを使ってみる

追加

次の日からとりあえず、普段Cursorで開発をしているので https://docs.flutter.dev/ai/mcp-server#cursor ←ここから追加してみました。
または、 ~/.cursor/mcp.jsonに以下を追加します

{
  "mcpServers": {
    "dart": {
      "command": "dart",
        "args": [
          "mcp-server",
          "--force-roots-fallback"
      ]
    }
  }
}

テストを実行

dart MCPでテストを実行して

このようなプロンプトを入れるとDart MCP内のrun_testsが実行されます。
run_testsのgithubの説明には

Run Dart or Flutter tests with an agent centric UX. ALWAYS use instead of dart test or flutter test shell commands.
エージェント中心の UX で Dart または Flutter テストを実行します。常に dart test または flutter test シェル コマンドの代わりに使用します。

と記述されています。

常に dart test または flutter test シェル コマンドの代わりに使用します。

なぜ常になのか、Cursorくんに聞いてみました。

主な理由
1. 構造化された出力
- シェルコマンド(dart test)→ 単なるテキスト出力
- MCPツール → 構造化されたデータ(JSON形式など)で結果を返す
AIエージェントがテスト結果を解析しやすくなります。

2. エラー情報の適切な取得
シェルコマンドでは出力をパースする必要がありますが、MCPツールは:
- 失敗したテスト名
- エラーメッセージ
- スタックトレース
などを構造化された形で返してくれるので、AIが次のアクション(修正など)を取りやすくなります。

3. 環境依存の排除
- シェルコマンドはOS/シェルの違いで動作が変わることがある
- MCPツールは抽象化されているため、環境差を気にしなくて良い
4. Dart Tooling Daemon(DTD)との統合
MCPツールはDart/Flutterの開発ツールと深く統合されており、より良いデバッグ体験を提供できます。

結論: AIエージェント(Cursor)がテスト結果を正確に理解し、次のアクション(バグ修正、リトライなど)を適切に判断できるようにするためです。

なるほどなるほど。
「失敗したら〇〇してね」や「成功したらcommitしてね」などができるからのようです。

自分が使う場面は、最近Graphqlライブラリをferryからgraphql_flutterに移行していて、プロンプトの最後にdart MCPでテストを実行してと追記して使用しています。

analyzeエラーの検出→修正

めちゃくちゃ大袈裟ですが、こういうコードが生成された場合に

dart mcpでanalyze エラーを修正して

などのプロンプトを渡すと
Dart MCPのanalyze_filesでエラーを検出→dart_fixでエラー修正→analyze_filesでエラーが修正されているか確認、
が実行され修正してくれます。

フォーマットはまた別のdart_formatがあります。
一気にエラー、フォーマットの修正を依頼する場合は、

dart mcpでanalyze エラーを修正して、formatも整理してください。

と渡すとよさそうでした!

build_runner欲しいかも...

テストなどやレイアウトエラーもチャットで聞いているとコマンドでやってもいいけど、なんとなくbuild_runnerできたらいいなー思ってきてしまい...
この記事書くついでに追加してみました!

まず、Dart and Flutter MCP serverのリポジトリをgit cloneします

git clone git@github.com:dart-lang/ai.git

次に、pkgs/dart_mcp_server/lib/src/mixins/配下にbuild_runner.dartを作成します。

// 必要なimportは省略

base mixin BuildRunnerSupport on ToolsSupport, LoggingSupport, RootsTrackingSupport
    implements ProcessManagerSupport, FileSystemSupport, SdkSupport {
  @override
  FutureOr<InitializeResult> initialize(InitializeRequest request) {
    registerTool(buildRunnerTool, _runBuildRunnerTool);
    return super.initialize(request);
  }

   // Implementation of the [buildRunnerTool].
  Future<CallToolResult> _runBuildRunnerTool(CallToolRequest request) async {
    final watch = request.arguments?['watch'] as bool? ?? false;
    return runCommandInRoots(
      request,
      arguments: [
        'pub',
        'run',
        'build_runner',
        watch ? 'watch' : 'build',
        '--delete-conflicting-outputs',
      ],
      commandDescription: 'dart pub run build_runner ${watch ? 'watch' : 'build'}',
      processManager: processManager,
      knownRoots: await roots,
      fileSystem: fileSystem,
      sdk: sdk,
    );
  }

  static final buildRunnerTool = Tool(
    name: 'build_runner',
    description:
    'Runs build_runner to generate code (e.g., freezed, json_serializable, riverpod_generator). '
    'Executes `dart pub run build_runner build --delete-conflicting-outputs`.',
    annotations: ToolAnnotations(
      title: 'Build runner',
      destructiveHint: true,
    ),
    inputSchema: Schema.object(
      properties: {ParameterNames.roots: rootsSchema()},
      additionalProperties: false,
    ),
  );

↑のコードを追加。

sever.dartに↓のコードを追加します。

final class DartMCPServer extends MCPServer
    with
        BuildRunnerSupport,

これでdart mcp serverの準備がととのいました。

次にCursorのmcp.jsonに追加していきます。

{
  "mcpServers": {
    "dart": {
      "command": "dart",
      "args": [
        "run",
        "path/ai/pkgs/dart_mcp_server/bin/main.dart",
        "--force-roots-fallback"
      ]
    }
  }
}

これが完了するとbuild_runnerが追加されます。
スクリーンショット 2025-12-23 15.41.36.png

試しにfreezedファイルを編集してみて動かしてみました。
スクリーンショット 2025-12-23 15.47.23.png
↑このように無事に実行されました。👏👏👏🎉🎉🎉

意外と、あっさり追加できましたねw
これから、業務で使ってみて欲しいコマンドとかあったらMCPサーバーに追加していきたいなと思います。

まとめ

ここまで読んでいただきありがとうございました。
この記事の最初の方にも書きましたが、本当にAIの普及が目まぐるしくてついていくのに必死です。そしてついて行けてないです...w。Cursorにも最近subagent,skillsが登場しましたが、いまいちcontextを意識しながらとか開発できていなし、これで合ってるのか分からず手探りで開発してます。

記事のどこかでも書いたと思うのですが、施策開発と並行してGraphQLのライブラリの移行作業をしています。
各Query,mutationを呼び出してるRepositoryの関数ごとに分けて、Cursorとdevinに移行を任せています。
Cursorでは、Planをまず作成させてからcloud agentにシンプル投げていましたが、先週くらいにsubagent使ってみよーと思いCursorにsubagent作ってみてと気軽に言ってみたら4つに分けて作ってくれました。

  1. Repository移行方針の特定
  2. graphql_flutter生成物(型・ファイル・戻り値)の正解を確定
  3. UseCase/Store層の型統一と波及箇所洗い出し
  4. テスト追従(mock/期待値/ビルドランナー要否/実行コマンド)

この4つのsubagentをこのように実行してみてます。

まず @1agent.md  [INPUT] からJSONを作ってください
次に、その @2agent.md, @3agent.md, @4agent.md  に渡して “並列” に実行してください。

制約:
- subagent  @2agent.md, @3agent.md, @4agent.md は INPUT 原文を参照せず、ExtractorのJSONのみを前提にすること
- 結果は subagent ごとに分けて出力

[INPUT]
<--------ここに移行先の型や、該当ページの情報を記述--------->
[/INPUT]

1のagentからjsonをもらったら↓のように並列で作業してくれます。

ここからまたPlanファイルを作ってもらうagentなどを追加したりして使ってみてます。
これでいい感じに出来てるか分からないですが...

このsubagentに次いで...skillsはどう使ったらいいだ...

CAMPFIREでは社内イベントとしてAIハッカソンを定期的に開催しています。
最終営業日の26日にあるので、そこでまたskills,subagentを作ってみようと思います!

来年もコツコツ自分の持ち場で頑張っていきます!ありがとうございました!ごっちゃんし!

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?