🔌

Koog応用編 - Model Context Protocol (MCP) で外部サービスと連携してみた

に公開

はじめに

前回の記事「Koog応用編 - イベント駆動とサブグラフでAIエージェントの動作を制御する」では、Koogのイベント駆動機能とサブグラフ機能について試してみました。

今回は第4回として、**Model Context Protocol (MCP)**を使って既存の外部サービスと連携する方法にフォーカスします。KoogのMCP統合機能により、既に公開されているMCPサーバーを簡単にエージェントに組み込めます。

なぜMCPが重要なのか?

第2回の「Koog実践編」では、カスタムツールを1つ1つ実装する方法を試してみました。しかし、世の中には既に多くの便利なツールやサービスが存在しています。これらを毎回ゼロから実装するのは非効率的です。

そこで登場するのがMCP(Model Context Protocol)です。MCPはAIエージェントと外部ツール・サービスを接続するための標準化されたプロトコルで、以下のような利点があります。

MCPの主な利点

  1. 標準化されたインターフェース

    • 統一されたツール定義(JSON Schema)
    • 一貫性のある入出力形式
  2. 再利用可能性

    • 公開されているMCPサーバーをそのまま利用可能
    • 自分で実装する必要がない
  3. エコシステム

    • GitHub、Google Maps、Slackなど、多くのMCPサーバーが既に公開されている
    • コミュニティで開発・メンテナンスされている

今回は、実用的なMCPサーバーの一例として、Chrome DevTools MCPを使って統合方法を試していきます。

今回作るもの

Phase 4では、Chrome DevTools MCPとの統合を実装してみます。

Chrome DevTools MCP統合

  • ブラウザ自動化(豊富なツール群)
  • スクリーンショット撮影
  • パフォーマンス分析
  • ネットワーク監視
  • JavaScript実行

プロジェクト構成

phase4/
├── config/
│   └── Phase4Config.kt                 # MCP設定
├── controller/
│   └── ChromeDevToolsMcpController.kt  # Chrome DevTools REST API
├── service/
│   └── ChromeDevToolsMcpService.kt     # Chrome DevTools MCP統合
└── dto/
    └── Phase4Dto.kt                    # リクエスト/レスポンスDTO

KoogでのMCP統合の基本

KoogでMCPサーバーと統合するには、主に3つのステップがあります。

// ステップ1: MCPサーバーのプロセスを起動
val mcpProcess = ProcessBuilder(
    "npx", "-y", "chrome-devtools-mcp@latest", "--headless"
).start()

// ステップ2: ToolRegistryの作成
val toolRegistry = McpToolRegistryProvider.fromTransport(
    transport = McpToolRegistryProvider.defaultStdioTransport(mcpProcess)
)

// ステップ3: AIAgentに統合
val agent = AIAgent(
    executor = simpleGoogleAIExecutor(googleApiKey),
    llmModel = GoogleModels.Gemini2_0Flash001,
    toolRegistry = toolRegistry,  // MCPツールを登録
    systemPrompt = "あなたはブラウザ自動化アシスタントです"
)

たったこれだけで、MCPサーバーが提供する全てのツールがエージェントから利用可能になります!

実装例: Chrome DevTools MCP統合

Chrome DevTools MCPは、ブラウザ自動化のための豊富なツールを提供します。

サービス層(ChromeDevToolsMcpService.kt)

@Service
class ChromeDevToolsMcpService(
    @Value("\${api.google-api-key}") private val googleApiKey: String,
    private val config: Phase4Config
) {
    private var mcpProcess: Process? = null
    private var toolRegistry: ToolRegistry? = null
    private var agent: AIAgent<String, String>? = null

    @PostConstruct
    fun init() {
        // ステップ1: MCPサーバーのプロセスを起動
        mcpProcess = ProcessBuilder(
            "npx", "-y", "chrome-devtools-mcp@latest", "--headless"
        ).start()

        Thread.sleep(3000)  // サーバー起動を待つ

        // ステップ2: ToolRegistryの作成
        toolRegistry = runBlocking {
            McpToolRegistryProvider.fromTransport(
                transport = McpToolRegistryProvider.defaultStdioTransport(mcpProcess!!)
            )
        }

        // ステップ3: AIAgentに統合
        agent = AIAgent(
            executor = simpleGoogleAIExecutor(googleApiKey),
            llmModel = GoogleModels.Gemini2_0Flash001,
            toolRegistry = toolRegistry!!,  // 多数のツールが利用可能に!
            systemPrompt = """
                You are a browser automation and debugging assistant.
                You can navigate pages, take screenshots, analyze performance,
                execute JavaScript, and more.
                Respond in Japanese when asked in Japanese.
            """.trimIndent()
        )
    }

    @PreDestroy
    fun cleanup() {
        mcpProcess?.destroyForcibly()
    }

    fun executeTask(task: String): String = runBlocking {
        agent!!.run(task)
    }

    fun getAvailableTools(): List<String> {
        return toolRegistry?.tools?.map { it.name } ?: emptyList()
    }
}

Chrome DevToolsで利用可能なツール

Chrome DevTools MCPは以下のような豊富なツールを提供します。

カテゴリ 主なツール
入力自動化 click, fill, fill_form, drag, hover, upload_file, handle_dialog
ナビゲーション navigate_page, new_page, close_page, list_pages, select_page, wait_for
エミュレーション emulate_cpu, emulate_network, resize_page
パフォーマンス performance_analyze_insight, performance_start_trace, performance_stop_trace
ネットワーク get_network_request, list_network_requests
デバッグ evaluate_script, list_console_messages, take_screenshot, take_snapshot

環境設定

application.yaml

phase4:
  llm-model: ${PHASE4_LLM_MODEL:gemini-2.0-flash-001}
  temperature: ${PHASE4_TEMPERATURE:0.7}
  chrome-devtools:
    headless: ${PHASE4_CHROME_HEADLESS:true}
    startup-timeout: ${PHASE4_CHROME_STARTUP_TIMEOUT:3000}

api:
  google-api-key: ${GOOGLE_API_KEY:}

.envファイル

# Google AI APIキー(必須)
GOOGLE_API_KEY=your_google_api_key_here

# Phase 4設定(オプション)
PHASE4_LLM_MODEL=gemini-2.0-flash-001
PHASE4_TEMPERATURE=0.7
PHASE4_CHROME_HEADLESS=true
PHASE4_CHROME_STARTUP_TIMEOUT=3000

動作確認

Docker Composeでアプリケーションを起動します。

task up
# または
docker compose up

ステータス確認

curl http://localhost:8080/phase4/chrome-devtools/status | jq .

実行結果

{
  "ready": true,
  "processAlive": true,
  "toolsCount": 26,
  "availableTools": [
    "list_console_messages",
    "emulate_cpu",
    "emulate_network",
    "click",
    "drag",
    "fill",
    "fill_form",
    "hover",
    "upload_file",
    "get_network_request",
    "list_network_requests",
    "close_page",
    "handle_dialog",
    "list_pages",
    "navigate_page",
    "navigate_page_history",
    "new_page",
    "resize_page",
    "select_page",
    "performance_analyze_insight",
    "performance_start_trace",
    "performance_stop_trace",
    "take_screenshot",
    "evaluate_script",
    "take_snapshot",
    "wait_for"
  ]
}

多数のツールが利用可能になっています!

実用例1: ページタイトルの取得

curl -X POST http://localhost:8080/phase4/chrome-devtools/execute \
  -H "Content-Type: application/json" \
  -d '{"task": "example.comにアクセスして、ページのタイトル(document.title)を教えてください"}' | jq .

実行結果

{
  "task": "example.comにアクセスして、ページのタイトル(document.title)を教えてください",
  "result": "ページのタイトルは \"Example Domain\" です。"
}

エージェントが自動的に:

  1. navigate_pageツールでページにアクセス
  2. evaluate_scriptツールでJavaScript(document.title)を実行
  3. 結果を日本語で返答

ログで確認

INFO  ai.koog.agents.core.agent.AIAgent - Executing tools: [navigate_page]
INFO  ai.koog.agents.core.agent.AIAgent - Executing tools: [evaluate_script]

MCPツール(navigate_page, evaluate_script)が実際に呼び出されていることがログから確認できます。

実用例2: リンクURLの取得

curl -X POST http://localhost:8080/phase4/chrome-devtools/execute \
  -H "Content-Type: application/json" \
  -d '{"task": "https://example.comにアクセスして、ページに表示されているすべてのリンク(aタグ)のURLを教えてください"}' | jq .

実行結果

{
  "task": "https://example.comにアクセスして、ページに表示されているすべてのリンク(aタグ)のURLを教えてください",
  "result": "https://example.com にアクセスしました。ページのすべての a タグの URL を取得するために JavaScript を実行しました。結果は `[ 'https://www.iana.org/domains/example' ]` です。"
}

エージェントが自動的に:

  1. navigate_pageツールでページにアクセス
  2. evaluate_scriptツールでJavaScriptを実行してリンクURLを抽出

ログで確認

INFO  ai.koog.agents.core.agent.AIAgent - Executing tools: [navigate_page]
INFO  ai.koog.agents.core.agent.AIAgent - Executing tools: [evaluate_script]

複雑な処理も自然言語で指示するだけで実行できます

MCPとカスタムツールの使い分け

第2回のカスタムツールと今回のMCPは、それぞれ異なる場面で活用できます。

アプローチ 適用場面 メリット デメリット
MCPサーバー 既存のMCPサーバーが利用可能な場合 ・実装不要
・コミュニティでメンテナンス
・標準化されたインターフェース
・MCPサーバーの制約を受ける
・カスタマイズが難しい
カスタムツール 独自のビジネスロジックが必要な場合 ・完全なコントロール
・ビジネスロジックに最適化
・柔軟なカスタマイズ
・実装コストが高い
・自前でメンテナンス

推奨アプローチ

  1. 既存のMCPサーバーがある場合は、まずMCPを試す
  2. カスタマイズが必要な場合は、カスタムツールを実装
  3. 両方を組み合わせて使うことも可能

まとめ

今回は、KoogのMCP統合機能を使って、Chrome DevTools MCPと連携する方法を試してみました。

重要なポイント

  1. MCPの3ステップ統合

    • プロセス起動 → ToolRegistry作成 → AIAgent統合
  2. 標準化のメリット

    • 既存のMCPサーバーをすぐに利用可能
    • 実装コストの削減
  3. 実用的な統合例

    • Chrome DevTools MCP: 豊富なブラウザ自動化ツール
    • ページナビゲーション、JavaScript実行、スクリーンショットなど
  4. Spring Bootとの統合

    • @PostConstructでMCPサーバー起動
    • @PreDestroyでクリーンアップ
    • REST APIとして公開

MCPを活用することで、エージェントの機能を効率的に拡張できます。既存のMCPエコシステムを活用しながら、必要に応じてカスタムツールも組み合わせることで、実用的なAIエージェントアプリケーションを構築できます。

サンプルコード

今回の実装コードは以下のリポジトリで公開しています。

参考資料

Discussion