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: {
// Local tool (Stdio)
wikipedia: {
command: 'npx',
args: ['-y', 'wikipedia-mcp'],
},
// Maps & Navigation (Remote/HTTP)
googleMaps: {
url: new URL(process.env.GOOGLE_MAPS_MCP_URL!),
requestInit: {
headers: {
Authorization: `Bearer ${process.env.GOOGLE_MAPS_API_KEY}`,
},
},
},
// Weather Service Integration
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コードや天気サービス連携を書きませんでした。


ユーザーごとの認証

ここで犯しやすいセキュリティ上の過ちがあります:認証情報をハードコードすることです。

環境変数に1つのGoogle Maps APIキーを入れて終わりにした場合、すべてのユーザーが同じクォータとレート制限を共有します。もっと重要なことに、保存された場所やお気に入りのルートなど、ユーザーの設定を保存するサービスを使っている場合、誰もが同じデータを見るようになります。デモとしては問題ありません。本番環境ではリスクとなります。

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

async function handleUserRequest(userPrompt: string, userCredentials: UserCreds) {
// Create a client for THIS specific user
const userMcp = new MCPClient({
servers: {
googleMaps: {
url: new URL(process.env.GOOGLE_MAPS_MCP_URL!),
requestInit: {
headers: {
// User's specific API key or token
Authorization: `Bearer ${userCredentials.mapsApiKey}`,
'X-User-ID': userCredentials.userId,
},
},
},
},
});
const agent = mastra.getAgent('navigationDirectionsAgent');
// Inject tools at runtime
const response = await agent.generate(userPrompt, {
toolsets: await userMcp.getToolsets(),
});
return response;
}

各ユーザーは各自の分離されたツールセットを取得し、それぞれのAPIクォータと設定を持ちます。ユーザーAの保存場所は非公開のまま、ユーザーBのルート履歴は別々に保たれます。マルチテナントSaaSエージェントは、実際にはこうして動作しています。


複合ツールの構築

複数のMCPツールを1つの操作に組み合わせたい場合があります。リアルタイムの交通状況と沿線の天気予報を考慮したルートを計画したい場合など。

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

export const smartRouteTool = createTool({
id: 'smart-route-planner',
description: 'Plans optimal route considering traffic and weather conditions',
execute: async ({ context, mastra }) => {
// Get the raw tools
const tools = await mcpClient.getTools();
// 1. Get base route from Google Maps
const routeData = await tools.googleMaps_getDirections.execute({
context: {
origin: context.origin,
destination: context.destination
}
});
// 2. Check weather along the route
const weatherData = await tools.weather_getForecast.execute({
context: { coordinates: routeData.waypoints }
});
// 3. Return enhanced route with weather warnings
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. ワークフローとメモリ