こんにちは!YOUTRUSTのアプリエンジニアの葉(YOUTRUST)です!
今回は、最近話題の MCP(Model Context Protocol) を使って、AI にコマンドを“安全に任せる”方法を試してみたので、シェアしたいと思います!
🚀なぜ MCP なのか
最近、AI を開発に使う中で、ちょっとしたノイズを感じることがありました。
同じ依頼でも毎回出力が微妙に違う(設定が抜けたり、フォーマットがずれる)。
人間との会話のように柔軟で便利なんですが、ちょっとした言い回しの違いで結果が変わったり、毎回の動作がブレたりするのが悩みでした。
「言葉」で伝える限界をどう補うかを考えたとき、
AI に実行を任せるためのルールをコードとして定義するのが一番早いと気づきました。
そこで方針をシンプルに:
① 公式の「Dart & Flutter MCP Server」を使う
② 足りない“社内コマンド”は自前MCPツール化して、安全・再現・構造化を担保する
この組み合わせで、プロンプトだけでは届かない “安全で再現性のある実行” が可能になります。
自分は普段 Flutter 開発が多いので Dart / Flutter MCP を使いましたが、実はほかにも Python や Node.js、Rust など、さまざまな公式 MCP サーバーがあります。
自分の環境に合うものを探してみるのもおすすめです!🔍
🧠MCP とは(超要約)
MCP(Model Context Protocol)は、LLMとツールをつなぐための標準プロトコルです。
サーバー側が「使ってよい Tools(機能)」「読める Resources」「定型 プロンプト」などを型付き(JSON Schema)で公開し、クライアント(Claude / Cursor / Gemini CLI…)がtools/list → tools/call で発見・実行できるようになります。
⚙️なぜ「プロンプト追記」だけでは足りないのか(コマンド限定の観点)
| 観点 | プロンプトに追記(CLAUDE.md/コマンド等) | MCP(型付きツール) |
|---|---|---|
| 指示 | 人が読む文章(解釈ゆれ) | subcommand/args をスキーマで固定 |
| 安全 | 文章の約束 | ホワイトリスト+バリデーション+タイムアウト |
| 出力 | 都度違うログ | 毎回 {exitCode, stdout, stderr} |
| 再実行 | 言い方・担当者依存 | 機械的に同じ(tools/call) |
| 再利用 | クライアント依存 | 複数クライアント横断で再利用 |
つまり、「再現性のない CLI 操作」をツールとして再定義する感じです。
🧩このように運用してみた
1. 公式 MCPを使う!
Flutter 開発での基本操作(analyze/test/format など)はすでに Dart and Flutter MCP server が全部やってくれます。
“AI にコマンドを任せる” なら、まずこれから始めるのが一番おすすめです。
ちなみに、自分の環境では ~/.cursor/mcp.json では反応せず、 youtrust-app/.cursor/mcp.json に置いたらうまく動きました。
❌ ~/.cursor/mcp.json ✅ youtrust-app/.cursor/mcp.json
動くとこんな感じになります👇

dart format をちゃんと叩いてくれました!🎉
![]()
2. 自前で MCP サーバーを作る!
🪄 1. まずは公式チュートリアルを動かす
公式の Build an MCP server チュートリアルは、Python + FastMCP で “天気API” を公開する最小構成です。
- uv(Astral製の高速パッケージマネージャ) で環境構築
- API 呼び出しを関数化(Helper)
- @mcp.tool() でツール定義
- mcp.run(transport='stdio') で起動
これで MCP の仕組みがサクッと掴めます。
👇 実際に動かすとこんな感じ。

🔧 2. 公式チュートリアルから“自分仕様”へ
YOUTRUST では make build_runner.youtrust.run をよく使うので、 これを MCP サーバー化してみました。
Claude Code にお願いして作ったのがこれ👇
# /// script # requires-python = ">=3.13" # dependencies = [ # "mcp[cli]>=1.16.0", # ] # /// import asyncio import json import subprocess import os from pathlib import Path from typing import Any, Optional from mcp.server.fastmcp import FastMCP # Initialize FastMCP server mcp = FastMCP("flutter_dev") # Global dictionary to track running Flutter processes running_processes: dict[str, subprocess.Popen] = {} async def run_command(cmd: list[str], timeout: int = 30, cwd: Optional[str] = None) -> dict[str, Any]: """Run a command and return the result as a dictionary.""" try: process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, cwd=cwd ) stdout, stderr = await asyncio.wait_for( process.communicate(), timeout=timeout ) return { "success": process.returncode == 0, "returncode": process.returncode, "stdout": stdout.decode('utf-8', errors='ignore'), "stderr": stderr.decode('utf-8', errors='ignore') } except asyncio.TimeoutError: return { "success": False, "error": f"Command timed out after {timeout} seconds" } except Exception as e: return { "success": False, "error": str(e) } @mcp.tool() async def run_build_runner( timeout: int = 300 ) -> str: """Run build_runner for code generation using make build_runner.youtrust.run. Args: timeout: Command timeout in seconds (default: 300) Returns JSON with command output. """ cmd = ["make", "build_runner.youtrust.run"] try: result = await run_command(cmd, timeout=timeout) except RuntimeError as e: return json.dumps({ "success": False, "error": str(e) }) return json.dumps({ "success": result["success"], "command": " ".join(cmd), "returncode": result.get("returncode"), "stdout": result["stdout"], "stderr": result["stderr"], "error": result.get("error") }, ensure_ascii=False, indent=2) def main(): """Initialize and run the MCP server.""" mcp.run(transport='stdio') if __name__ == "__main__": main()
起動用 alias(~/.zshrc)
alias flutter-dev="uv run weather/flutter_dev.py"
youtrust-app/.cursor/mcp.json に追加
{ "mcpServers": { "flutter-dev": { "command": "zsh", "args": [ "-ic", "flutter-dev" ] } } }
🚨実装時のハマりどころ
公式チュートリアルでは directory を MCP サーバー(スクリプト側)に設定していますが、
自分の環境ではそれだと make コマンドが動きませんでした。
make はプロジェクトディレクトリ内でしか動作しないため、 youtrust-app/.cursor/mcp.json に alias で設定したコマンドを走らせるようにしたら、 ちゃんと拾ってくれるようになりました ✅
これで、Cursor から MCP サーバーとして make build_runner.youtrust.run を安全に叩けるようになります 🎉
「mcpで make build して」って言うだけで動くの、ちょっと感動します。

💡おわり
今回は MCP(Model Context Protocol)について紹介しました。
今後は、社内のコマンドや情報をどんどん MCP 化していき、
安全・再現性・構造化 を実現していきたいと思います。
AI の力で “安全な自動化” を進めたい方は、ぜひ自分の環境でも試してみてください!
自分も今回が初挑戦なので、「ここ違うかも」「こっちの方が便利だよ」みたいな気づきがあったら、ぜひコメントで教えてもらえると嬉しいです!🙌