AIエージェント ツール連携3パターン|MCP・FC・API直接比較

AIエージェント ツール連携3パターン|MCP・FC・API直接比較

この記事の結論

Function Calling・MCP・API直接呼び出しの3パターンをどう使い分けるか。実際に動くコード例と共に、適切な場面・合わない場面・よくある失敗を解説する。判断フロー付き。

「MCP、Function Calling、API直接呼び出し——結局どれを使えばいい?」

AIエージェントの設計を始めると、ほぼ必ずこの問いにぶつかる。そして困ったことに、どれも「使えるケース」があり、どれも「使うべきでないケース」がある。

10社以上のAIエージェント導入を支援してきた経験から言うと、この判断を間違えると後から大きなリファクタリングが発生する。逆に最初に正しく選択できると、開発速度が劇的に上がる。

この記事では、3つのツール連携パターンを実際のコード例とともに比較し、状況別の使い分けを具体的に示す。

3つのパターンの概要

パターン 何を解決するか 主な採用場面 難易度
Function Calling LLMからAPI呼び出しを構造化する 小規模・単一プロバイダー
MCP ツール定義をプロバイダー横断で標準化 マルチモデル・スケール展開
API直接呼び出し AIを介さない確定的な処理 固定ワークフロー・高頻度処理 低〜中

パターン1: Function Calling(関数呼び出し)

何をするパターンか

LLMに「使えるツールの定義(JSON Schema)」を渡し、LLMが必要に応じてそのツールを呼び出す。OpenAIが普及させたアプローチで、AnthropicのTool Use、GoogleのFunction Declarationsもこの概念の実装だ。

最小実装コード

# OpenAI Function Calling 最小実装
# 動作環境: Python 3.11+, openai>=1.30.0
# pip install openai

from openai import OpenAI
import json

client = OpenAI()

# ツール定義(JSON Schema形式)
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "指定した都市の現在の天気を取得する",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "都市名(例: Tokyo)"}
                },
                "required": ["city"]
            }
        }
    }
]

# ツールの実際の処理(自前で実装)
def get_weather(city: str) -> str:
    # 実際はAPIを呼ぶ
    return f"{city}の天気: 晴れ、気温23°C"

# LLMにメッセージを送信
messages = [{"role": "user", "content": "東京の天気を教えて"}]
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
)

# LLMがツール呼び出しを判断した場合、実行して結果を返す
if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
    args = json.loads(tool_call.function.arguments)
    result = get_weather(**args)
    # 結果をLLMに戻す
    messages.append(response.choices[0].message)
    messages.append({
        "role": "tool",
        "tool_call_id": tool_call.id,
        "content": result
    })
    final_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
    )
    print(final_response.choices[0].message.content)

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

最終確認日: 2026-04-11

Function Callingが適切な場面

  • ツールが5個以下で固定されている
  • 単一のLLMプロバイダーしか使わない
  • プロトタイプや初期実装
  • チームがAI統合に不慣れで、最もシンプルな形から始めたい

Function Callingが合わない場面

  • 複数のLLMプロバイダーを使う(OpenAI→Claude切り替えなど)
  • ツールが10個を超える
  • 同じツールを複数のAIアプリケーションで共有したい

パターン2: MCP(Model Context Protocol)

何をするパターンか

ツールの定義と実行をMCPサーバーとして独立させる。AIアプリケーション(MCPクライアント)は統一されたプロトコルでサーバーに接続し、利用可能なツールを動的に発見して使う。プロバイダー間の差異がなくなり、「1つのサーバー → 複数のAIアプリ」が成立する。

MCPサーバー実装コード

# MCP サーバー実装(天気ツールをMCPサーバーとして公開)
# 動作環境: Python 3.11+, mcp>=1.0
# pip install mcp

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
import asyncio

server = Server("weather-service")

@server.list_tools()
async def list_tools():
    """利用可能なツールを定義(クライアントが動的に発見できる)"""
    return [
        Tool(
            name="get_weather",
            description="指定した都市の現在の天気を取得する",
            inputSchema={
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "都市名(例: Tokyo)"
                    }
                },
                "required": ["city"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    """ツールの実際の処理"""
    if name == "get_weather":
        city = arguments["city"]
        # 実際はAPIを呼ぶ
        return [TextContent(type="text", text=f"{city}の天気: 晴れ、気温23°C")]
    raise ValueError(f"未知のツール: {name}")

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            server.create_initialization_options()
        )

if __name__ == "__main__":
    asyncio.run(main())

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

このMCPサーバーは、Claude Desktop、Claude Code、OpenAI互換クライアントなど、MCP対応の全クライアントから同じように呼び出せる。

MCPの設定例(Claude Desktop向け)

// claude_desktop_config.json
{
  "mcpServers": {
    "weather-service": {
      "command": "python",
      "args": ["/path/to/weather_server.py"],
      "env": {
        "WEATHER_API_KEY": "your_api_key_here"
      }
    }
  }
}

最終確認日: 2026-04-11(MCP仕様 2026-03-26版)

MCPが適切な場面

  • 複数のAIアプリから同じツールを使いたい(共有ツールライブラリ)
  • 将来的にLLMプロバイダーを変える可能性がある
  • 社内ツールを組織全体でAIに繋ぎたい
  • 5,800本以上の既存サーバーを活用したい(開発コスト最小化)

MCPが合わない場面

  • サーバーセットアップのオーバーヘッドが大きすぎる極小プロジェクト
  • 高頻度処理(MCPのプロトコルオーバーヘッドが影響する場合)

パターン3: API直接呼び出し

何をするパターンか

AIを介さず、アプリケーションが直接APIを呼び出す。AIは「いつ、どのAPIを呼ぶか」を判断するが、実際の呼び出しはAIではなくアプリケーションコードが行う。

これはFunction CallingやMCPを否定するパターンではない。「AIの判断が不要な処理」はAPIを直接呼べばいい、というシンプルな考え方だ。

実装コード

# ハイブリッドパターン: LLMが判断、アプリが実行
# 動作環境: Python 3.11+, anthropic>=0.30.0
# pip install anthropic requests

import anthropic
import requests
import json

client = anthropic.Anthropic()

def execute_order(product_id: str, quantity: int, user_id: str) -> dict:
    """注文確定API(確定的処理 — LLMに実行させない)"""
    # 実際は内部APIを呼ぶ
    return {"order_id": f"ORD-{product_id}-001", "status": "confirmed"}

def get_product_info(product_id: str) -> dict:
    """商品情報取得(LLMが判断に使う情報取得)"""
    # 実際はAPIを呼ぶ
    return {"id": product_id, "name": "商品A", "price": 1980, "stock": 50}

# LLMには「推薦」だけをさせ、「実行」はアプリが担う
response = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=1024,
    tools=[{
        "name": "recommend_product",
        "description": "ユーザーのニーズに合った商品IDを推薦する",
        "input_schema": {
            "type": "object",
            "properties": {
                "product_id": {"type": "string"},
                "reason": {"type": "string"}
            },
            "required": ["product_id", "reason"]
        }
    }],
    messages=[{
        "role": "user",
        "content": "予算2000円以内で家庭用品を探しています"
    }]
)

# LLMの推薦を取得
if response.stop_reason == "tool_use":
    tool_use = next(b for b in response.content if b.type == "tool_use")
    recommendation = tool_use.input

    # 商品情報を直接API取得(AIを介さない)
    product = get_product_info(recommendation["product_id"])

    # 在庫チェックもAPIで直接確認
    if product["stock"] > 0 and product["price"] <= 2000:
        # 注文確定はAIに任せず、アプリが直接実行
        order = execute_order(
            product_id=recommendation["product_id"],
            quantity=1,
            user_id="user_123"
        )
        print(f"注文完了: {order}")

# 注意: 本番環境で使用する前に、必ずテスト環境で動作確認してください。

最終確認日: 2026-04-11

API直接呼び出しが適切な場面

  • 確定的な処理(決済、データ更新など)— AIに任せると不確実性が生まれる
  • 高頻度処理(プロトコルオーバーヘッドを避けたい)
  • AIが判断だけを担い、実行は既存システムに任せるアーキテクチャ

3パターンの使い分け判断フロー

AIがツールを使う場面

  └─ 複数のLLMプロバイダーを使うか、または社内共有ツールが必要?
       ├─ Yes → [MCP] サーバーを構築して標準化する
       └─ No
            └─ ツール数は5個以下で固定されているか?
                 ├─ Yes → [Function Calling] シンプルに実装する
                 └─ No → [MCP] 将来のスケールを考えMCPを選ぶ

ただし、確定的処理(決済・データ更新等)は必ずAPI直接呼び出しで。

よくある誤解と正しい理解

誤解1: MCPはFunction Callingの置き換えだ

✕ MCPがあればFunction Callingは不要
⭕ MCPはFunction Callingの概念を使っている。MCPサーバーが提供するツールも、内部的にはFunction Callingの仕組みで呼び出される

MCPはプロトコルの標準化レイヤーであり、Function Callingの代替ではなく、その上位概念だ。

誤解2: 全処理をAIに判断させるべきだ

✕ AIエージェントが全ての処理を判断・実行すべき
⭕ 確定的処理はAPIに任せ、AIは不確実性が価値を生む判断だけを担う

「AIがどこまで自律的に動くか」を意識的に設計することが、安全で予測可能なシステムを作る鍵だ。

誤解3: Function Callingは古い技術だから使うな

✕ MCPが標準になったのでFunction Callingは廃れた
⭕ 小規模プロジェクトや単一プロバイダー構成では、Function Callingがシンプルで正しい選択肢だ

MCPのセットアップコストを払う必要がない場面でMCPを選ぶのは、複雑さを増やすだけだ。

【要注意】設計でよくある失敗パターン

失敗1: 全処理をFunction Callingで実装し後からMCPに移行できない

❌ プロバイダー固有のFunction Calling構文を全コードに散布する
⭕ ツール実行ロジックを抽象化し、プロバイダー交換を可能にしておく

なぜ重要か: OpenAIのFunction CallingとAnthropicのTool Useは仕様が異なる。早期に抽象化しておかないと、プロバイダー変更時に全書き直しになる。

失敗2: MCPサーバーにビジネスロジックを詰め込む

❌ MCPサーバーの中でデータ変換・ルール適用・バリデーションを全部やる
⭕ MCPサーバーは薄いアダプター層として保ち、ビジネスロジックは既存サービスに委ねる

なぜ重要か: MCPサーバーが太くなると、テストが困難になり、保守性が下がる。MCPサーバーは「AIとサービスをつなぐ線」であり、「サービス本体」ではない。

失敗3: エラーハンドリングを後回しにする

❌ ツール呼び出しが失敗したときの処理を実装せずに本番デプロイする
⭕ タイムアウト、レート制限、APIエラーの全ケースを最初から設計する

なぜ重要か: AIエージェントがツール呼び出しで失敗したとき、エラー処理が不十分だとエージェントが無限ループに入ったり、誤った情報をユーザーに返したりする。

参考・出典

まとめ:今日から始める3つのアクション

  1. 今日: 現在のプロジェクトで使っているツール連携方法をリストアップし、「Function Calling」「MCP」「API直接呼び出し」のどれで実装しているかを分類する
  2. 今週中: 最もスケールが難しそうなツール統合を1つ選び、MCPサーバーに移行するプロトタイプを作る
  3. 今月中: チームのAIエージェント設計ガイドラインとして、3パターンの使い分けルールを文書化してCLAUDE.mdかWikiに追記する

AIエージェントのツール設計全体を学びたい方は、AIエージェント構築完全ガイドで体系的に解説しています。

あわせて読みたい:


著者: 佐藤傑(さとう・すぐる)
株式会社Uravation代表取締役。早稲田大学法学部在学中に生成AIの可能性に魅了され、X(旧Twitter)で活用法を発信(@SuguruKun_ai、フォロワー10万人超)。100社以上の企業向けAI研修・導入支援を展開。著書累計3万部突破。

Need help moving from reading to rollout?

この記事を読んで導入イメージが固まってきた方へ

Uravationでは、AIエージェントの要件整理、PoC設計、社内導入、研修まで一気通貫で支援しています。

この記事をシェア

X Facebook LINE

※ 本記事の情報は2026年4月時点のものです。サービスの料金・仕様は変更される可能性があります。最新情報は各サービスの公式サイトをご確認ください。

関連記事