DanLevy.net

あなたのAIエージェントはこれがないと役に立たない

MCPがAIにおけるUSB-Cである理由。

AIエージェントを構築した。おそらく悪くないものだ。プロンプトは洗練され、モデルは高速で、応答も自然に感じる。

しかし、誰かがSalesforceの顧客レコードを確認してほしいと頼む。あるいは最新のJiraチケットを取得してほしい、あるいは社内ドキュメントを検索してほしいと言う。

そして、その美しいエージェントは……何もできない。

これが、すべてのAIプラットフォームがいずれ直面する統合問題だ。エージェントには「手」が必要だ。実際のビジネスシステムを覗き込む「目」が必要だ。それらがなければ、高価なチャットボットを動かしているに過ぎない。

従来の解決策は?接続したいサービスごとにカスタムAPIラッパーを書くこと。ドキュメントを読み、認証を処理し、レート制限に対処し、来月エンドポイントが変更されないことを祈る。そして次のサービスでも同じことを繰り返す。また次のサービスでも。

Model Context Protocolは、この計算を根本的に変える。


MCPが実際に解決する問題

USB-C以前のUSBを思い出してほしい。Mini-USB、Micro-USB、Apple独自のコネクタ、そして特定のデバイスでしか使えないケーブルが引き出しに溢れていた。USB-Cは単に新しいコネクタを追加したのではない——どんなケーブルでもどんなデバイスでも使える標準を確立したのだ。

MCPはAIツール統合においてまったく同じことをしている。

Salesforce、HubSpot、GitHub、その他のサービスにエージェントを接続するためのカスタムコードを書く代わりに、プロトコルを一度実装する(またはプレビルドのサーバーをダウンロードする)だけで、MCP互換のどのエージェントでも即座に通信できるようになる。

プロトコルが通信レイヤーを処理する。あなたはツールが何をし、どんなデータが必要かを定義するだけだ。


複数の統合をセットアップする

MastraはMCPClientを通じてネイティブなMCPサポートを提供している。ローカルツール(子プロセスとして実行)とリモートサービス(独自のインフラで実行)の両方に接続できる。

Google Mapsによるルーティング、天気サービス、ローカルのWikipedia検索に接続する本番環境に近い構成例を示す:

src/mastra/mcp/index.ts
import { MCPClient } from '@mastra/mcp';
export const mcpClient = new MCPClient({
servers: {
// ローカルツール(Stdio)
wikipedia: {
command: 'npx',
args: ['-y', 'wikipedia-mcp'],
},
// 地図&ナビゲーション(リモート/HTTP)
googleMaps: {
url: new URL(process.env.GOOGLE_MAPS_MCP_URL!),
requestInit: {
headers: {
Authorization: `Bearer ${process.env.GOOGLE_MAPS_API_KEY}`,
},
},
},
// 天気サービス統合
weather: {
url: new URL('https://mcp.weatherapi.dev/v1'),
requestInit: {
headers: {
'X-API-Key': process.env.WEATHER_API_KEY!,
},
},
},
},
});

クライアントは接続ライフサイクルを管理し、ローカルツールのプロセススパンニングを処理し、リモートサーバーへのHTTP接続を維持する。ソケットやstdioを直接触る必要はない。


ツールをエージェントに接続する

MCPクライアントの設定が完了すれば、これらのツールをエージェントに渡すのは簡単だ:

src/mastra/agents/navigation-agent.ts
import { Agent } from '@mastra/core/agent';
import { openai } from '@ai-sdk/openai';
import { mcpClient } from '../mcp';
export const navigationDirectionsAgent = new Agent({
id: 'navigation-directions-agent',
name: 'Navigation & Directions Assistant',
instructions: `You are a helpful navigation assistant that provides route planning and travel advice.
- Always confirm the start and destination locations
- Use Google Maps tools to find optimal routes
- Check weather conditions along the route
- Provide estimated travel times and suggest alternatives if weather is poor
- Include relevant details like traffic, road conditions, and points of interest
- Keep responses clear and actionable`,
model: openai('gpt-5'),
tools: await mcpClient.getTools(), // <--- これが魔法の行
});

ユーザーが「サンフランシスコからレイクタホへの最適なルートは?天気は大丈夫?」と聞いたとする。

エージェントは利用可能なツール定義を読み取り、Google Mapsのルーティングと天気予報ツールにアクセスできることを認識し、正しいパラメータでそれらを実行し、最適なルートと沿線の現在の天気状況を返答する。

Google Maps APIコードも天気サービス統合も一行も書いていない。


ユーザーごとの認証

ここでやりがちなセキュリティ上の間違いがある。認証情報のハードコーディングだ。

環境変数に一つのGoogle Maps APIキーを入れて終わりにすると、すべてのユーザーが同じクォータとレート制限を共有することになる。さらに重要なのは、ユーザー設定(保存した場所やお気に入りルートなど)を保存するサービスを使っている場合、全員が同じデータを見ることになるということだ。これはデモでは問題ない。しかし本番環境では責任問題になる。

Mastraはユーザー固有の認証情報でMCPクライアントを動的に作成することでこれを処理する:

async function handleUserRequest(userPrompt: string, userCredentials: UserCreds) {
// この特定ユーザー向けのクライアントを作成
const userMcp = new MCPClient({
servers: {
googleMaps: {
url: new URL(process.env.GOOGLE_MAPS_MCP_URL!),
requestInit: {
headers: {
// ユーザー固有のAPIキーまたはトークン
Authorization: `Bearer ${userCredentials.mapsApiKey}`,
'X-User-ID': userCredentials.userId,
},
},
},
},
});
const agent = mastra.getAgent('navigationDirectionsAgent');
// 実行時にツールを注入
const response = await agent.generate(userPrompt, {
toolsets: await userMcp.getToolsets(),
});
return response;
}

各ユーザーは自分専用のAPIクォータと設定を持つ独立したツールセットを得る。ユーザーAの保存した場所はプライベートのままで、ユーザーBのルート履歴は分離されている。これがマルチテナントSaaSエージェントの実際の動き方だ。


複合ツールの構築

複数のMCPツールを一つの操作に組み合わせたい場合がある。例えば、リアルタイムの交通情報と沿線の天気状況の両方を考慮したルートを計画したい場合。

MCPツールをカスタムツール定義でラップできる:

export const smartRouteTool = createTool({
id: 'smart-route-planner',
description: 'Plans optimal route considering traffic and weather conditions',
execute: async ({ context, mastra }) => {
// 生のツールを取得
const tools = await mcpClient.getTools();
// 1. Google Mapsから基本ルートを取得
const routeData = await tools.googleMaps_getDirections.execute({
context: {
origin: context.origin,
destination: context.destination
}
});
// 2. ルート沿いの天気を確認
const weatherData = await tools.weather_getForecast.execute({
context: { coordinates: routeData.waypoints }
});
// 3. 天気警告付きの拡張ルートを返す
return {
...routeData,
weatherAlerts: weatherData.alerts,
recommendation: weatherData.severe ? 'Consider delaying trip' : 'Safe to travel'
};
},
});

これにより、MCPプロトコルの力を活用しながら、ツール間の相互作用をきめ細かく制御できる。


これが向かう先

AIエージェントが通信する必要があるすべてのサービスに対してカスタムAPIクライアントを書くことは、決して持続可能ではなかった。スケールが悪く、頻繁に壊れ、プラットフォームを特定の実装に縛り付ける。

MCPはすべての統合課題を解決するわけではない——認証は依然として複雑で、レート制限は依然として重要であり、すべてのサービスがMCPサーバーを持っているわけではない。しかし、エージェントプラットフォームの構築を大幅に楽にする基盤を確立している。

外部サービスとやり取りする必要があるAIシステムを設計しているなら、MCPを理解しておく価値はあるだろう。

リソース

シリーズを読む

  1. LLMルーティング
  2. セキュリティ&ガードレール
  3. MCP&ツール統合(この記事)
  4. ワークフロー&メモリ