1
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?

FastMCPとGemini 2.0による関数呼び出し連携 〜Googleコラボで実践〜

Posted at

はじめに

image.png

本記事では、Google Gemini 2.0のFunction Calling機能とModel Context Protocol(MCP)を連携し、Open-Meteo APIを使った天気予報機能の構築方法を紹介します。

image.png

MCPは、生成AIと外部ツールをつなぐ標準プロトコルとして注目されており、この記事ではMarktechPostの解説記事を参考に、Google Colabでの検証結果を備忘録としてまとめました。

Google ColabでMCPクライアントの実装を試みたものの実装制約で動作せず、調査中に上記記事を見つけて試した備忘録です。

技術的背景

Model Context Protocol (MCP)とは

Model Context Protocol (MCP)は、生成AIモデルと外部ツール・APIを統合するための標準プロトコルです。MCPを利用することで、AIモデルは自身の知識だけでなく、外部の情報源やサービスにアクセスして、より正確で最新の情報に基づいた応答を生成できるようになります。

FastMCPの役割

FastMCPは、Pythonで書かれたMCPサーバーとクライアントを簡単に構築するためのライブラリです。Pythonの関数をMCPツールとして公開し、インプロセスでMCPサーバーをホスティングすることができます。

実装と解説

環境準備

必要なライブラリをインストールし、APIキーを設定します。

!pip install -q google-genai mcp fastmcp httpx nest_asyncio

from getpass import getpass
import os
import nest_asyncio

api_key = getpass("Enter your GEMINI_API_KEY: ")
os.environ["GEMINI_API_KEY"] = api_key
nest_asyncio.apply()

MCPサーバーとツールの定義

FastMCPを使って、天気予報ツールを提供するMCPサーバーを作成します。

from fastmcp import FastMCP
import httpx

mcp_server = FastMCP("weather")

@mcp_server.tool()
def get_weather(latitude: float, longitude: float) -> str:
    """3日間の最低/最高気温予報をOpen-Meteoから取得します。"""
    url = (
        f"https://api.open-meteo.com/v1/forecast"
        f"?latitude={latitude}&longitude={longitude}"
        "&daily=temperature_2m_min,temperature_2m_max&timezone=UTC"
    )
    resp = httpx.get(url, timeout=10)
    daily = resp.json()["daily"]
    return "\n".join(
        f"{date}: low {mn}°C, high {mx}°C"
        for date, mn, mx in zip(
            daily["time"],
            daily["temperature_2m_min"],
            daily["temperature_2m_max"],
        )
    )

@mcp_server.tool()
def get_alerts(state: str) -> str:
    """米国州の天気アラート(ダミー)を返します。"""
    return f"No active weather alerts for {state.upper()}."

Geminiクライアントと統合

Geminiクライアントを初期化し、関数宣言を定義します。

import asyncio
from google import genai
from google.genai import types
from fastmcp import Client as MCPClient
from fastmcp.client.transports import FastMCPTransport

# Geminiクライアントとトランスポートの初期化
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
MODEL = "gemini-2.0-flash"
transport = FastMCPTransport(mcp_server)

# 関数宣言の定義
function_declarations = [
    {
        "name": "get_weather",
        "description": "指定された座標の3日間の最低/最高気温予報を返します。",
        "parameters": {
            "type": "object",
            "properties": {
                "latitude": {
                    "type": "number",
                    "description": "対象位置の緯度。"
                },
                "longitude": {
                    "type": "number",
                    "description": "対象位置の経度。"
                }
            },
            "required": ["latitude", "longitude"]
        }
    },
    {
        "name": "get_alerts",
        "description": "指定された米国州のアクティブな天気アラートを返します。",
        "parameters": {
            "type": "object",
            "properties": {
                "state": {
                    "type": "string",
                    "description": "米国州の2文字コード(例: 'CA')。"
                }
            },
            "required": ["state"]
        }
    }
]

tool_defs = types.Tool(function_declarations=function_declarations)

実行関数の定義

Geminiと連携して実行する関数を定義します。

async def run_gemini(lat: float, lon: float):
    async with MCPClient(transport) as mcp_client:
        # Geminiへのプロンプト
        prompt = f"Give me a 3-day weather forecast for latitude={lat}, longitude={lon}."
        
        # Geminiへのリクエスト
        response = client.models.generate_content(
            model=MODEL,
            contents=[prompt],
            config=types.GenerateContentConfig(
                temperature=0,
                tools=[tool_defs]
            )
        )

        # 関数呼び出しの取得
        call = response.candidates[0].content.parts[0].function_call
        if not call:
            print("関数呼び出しなし; Geminiの応答:", response.text)
            return

        print("🔧 Geminiの関数呼び出し:", call.name, call.args)

        # MCP経由で関数を実行
        result = await mcp_client.call_tool(call.name, call.args)
        print("\n📋 実行結果:\n", result)

# サンフランシスコの座標で実行
asyncio.get_event_loop().run_until_complete(run_gemini(37.7749, -122.4194))

実行結果と考察

サンフランシスコの座標を指定して実行した結果:

🔧 Geminiの呼び出し要求: get_weather {'latitude': 37.7749, 'longitude': -122.4194}

📋 ツールの結果:
 [TextContent(type='text', text='2025-05-06: low 10.7°C, high 27.2°C\n2025-05-07: low 9.8°C, high 15.7°C\n2025-05-08: low 11.2°C, high 19.7°C\n2025-05-09: low 10.3°C, high 22.9°C\n2025-05-10: low 10.3°C, high 19.3°C\n2025-05-11: low 11.4°C, high 16.6°C\n2025-05-12: low 10.5°C, high 17.3°C', annotations=None)]

image.png

連携の仕組みと流れ

この実装における連携の流れは以下の通りです:

  1. ユーザーの自然言語入力 → Gemini
  2. Gemini → 関数呼び出し情報(名前とパラメータ)
  3. MCP Client → MCP Server → 実際の関数実行
  4. 関数実行結果 → ユーザー

この流れで重要なのは以下の3つの要素です:

  1. 関数仕様の定義: Geminiに提供するJSON Schemaで関数を明確に定義
  2. MCPサーバーとツール: 実際に実行される関数の実装
  3. 連携部分: GeminiからMCPへの橋渡し(FastMCPTransportとMCPClient)

まとめ

gemini-mcp-code-clean (1).png

FastMCPとGemini 2.0の関数呼び出し連携をGoogle Colabで試してみました。これをベースに、他の外部システムとの連携も実装して試してみると、MCPの理解がさらに深まると思います。

参考資料

免責事項

  • 本記事の作成にあたり、文章および図解の一部に生成AIを活用しています。最終的な編集および内容の確認は筆者が責任を持って行っています。
1
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
1
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?