MastraでMCPを用いたTeamsチャットボットを作成する
背景
前回の記事で、Microsoft365 Agents Toolkit
で作成したボットでFunctionCallingを実装しました。今回は、MCPとエージェントフレームワーク利用をテーマに、Mastraを用いてシンプルなTeamsのAIチャットボットの開発を行ったのでまとめました。
対象読者
- TeamsでAIボットを作成したい方
- Typescript 初心者~中級者
環境
項目 | バージョン |
---|---|
OS | Windows11 Pro |
ランタイム | Node.js v22.14.0, Typescript 5.5.4 |
主要ライブラリ | @mastra/core==0.10.4, @mastra/mcp==0.10.3, @ai-sdk==1.3.23 |
使用モデル | GPT-4.1-mini |
Mastraとは
Mastraは、オープンソースのTypescript製のエージェントフレームワークです。Vercel AI SDK
を採用していることで、様々なLLMプロバイダやモデルの機能や構造に依存することなく統一したインタフェースで開発することができます。
他にも、@mastra/mcp-docs-server
といった開発ドキュメントへアクセスできるMCPサーバを提供しており、近年のCursor
やClaude Code
を活用したVibeCodingブームの流れを汲んでいることも人気の理由の1つだと思われます。[1]
事前準備
- BasicCustomEngineAgent新規作成
以下の記事を参考にBasicCustomEngineAgent
を新規作成します。
- Mastraのインストール
Mastra関係のモジュールとVercel AI SDK
をインストールします。
npm i @mastra/core @mastra/mcp @ai-sdk/azure
手順
1. MCPクライアントの作成
agents.ts
と同じ階層にmcp.ts
を作成しました。
ここでは、MCPサーバとの接続情報を定義しています。
import { MCPClient } from "@mastra/mcp";
export const mcp = new MCPClient({
servers:{
get_knowledge: {
url: new URL("http://localhost:8000/mcp"),
}
}
})
2. エージェントの構築
エージェントの構築と、MCPを用いたツールの取得を行います。
今回は、AzureOpenAIのGPT4.1-mini
を使用します。その他の対応プロバイダはこちらを参照してください。
import { Agent } from "@mastra/core/agent"
import { createAzure } from "@ai-sdk/azure"
import { mcp } from "./mcp";
// Azure OpenAIの設定
const azure = createAzure({
apiKey: config.azureOpenAIKey,
resourceName: config.azureOpenAIResourceName,
})
// ツールのリストを取得する関数
const getToolList = async () => {
const tools = await mcp.getTools();
return tools
}
// エージェントの定義
const ragAgent = new Agent({
name: "ナレッジ検索エージェント",
instructions: systemPrompt,
model: azure('gpt-4.1-mini'),
tools: getToolList
});
次に、Agentの処理経過をログ出力する仕組みを実装します。
MastraクラスにLoggerを追加する事で、ターミナル上にログが出力されるようになります。
出力できるレベルとしてDEBUG
、INFO
、WARN
、ERROR
が設定できます。
// ログ出力の設定
const logger = new ConsoleLogger({
name: "Mastra",
level: "debug"
});
// Mastraのインスタンスを作成
const mastra = new Mastra({
agents: { ragAgent },
logger: logger
})
agentApp.activity(ActivityTypes.Message, async (context: TurnContext) => {
const mainAgent = mastra.getAgent("ragAgent");
const userMessage = context.activity.text;
const result = await mainAgent.generate(userMessage)
await context.sendActivity(result.text);
})
また、agent.ts
の全体のコードは以下になります。
コード全体
import { ActivityTypes } from "@microsoft/agents-activity";
import { AgentApplication, MemoryStorage, TurnContext, CardFactory } from "@microsoft/agents-hosting";
import config from "./config";
import { Mastra } from "@mastra/core"
import { createAzure } from "@ai-sdk/azure"
import { Agent } from "@mastra/core/agent"
import { mcp } from "./mcp";
import { ConsoleLogger } from "@mastra/core/logger";
const azure = createAzure({
apiKey: config.azureOpenAIKey,
resourceName: config.azureOpenAIResourceName,
})
const systemPrompt = "あなたはTeamsで動くQ&Aエージェントです。\
以下のルールに従って回答してください。\
- Markdown形式で出力してください。\
- 必要なら会社のDBから情報を検索してそれを基に回答してください。DBから参照する場合は'参照: [http://localhost:8000/{pg_id}](http://localhost:8000/{pg_id})'という形で最後に示してください。\
- DBから検索した結果を用いる際は、その情報が質問内容とマッチしているかどうか考えてから回答してください。\
- 必要に応じてリストや番号付きリスト、表で表してください。表を作る場合は表の前に必ず改行を入れてください。\
- 重要な箇所は太字で強調してください。";
const storage = new MemoryStorage();
export const agentApp = new AgentApplication({
storage,
});
// ツールのリストを取得する関数
const getToolList = async () => {
const tools = await mcp.getTools();
return tools
}
// エージェントの定義
const ragAgent = new Agent({
name: "ナレッジ検索エージェント",
instructions: systemPrompt,
model: azure('gpt-4.1-mini'),
tools: getToolList
});
// ログ出力の設定
const logger = new ConsoleLogger({
name: "Mastra",
level: "debug"
});
// Mastraのインスタンスを作成
const mastra = new Mastra({
agents: { ragAgent },
logger: logger
})
agentApp.activity(ActivityTypes.Message, async (context: TurnContext) => {
const mainAgent = mastra.getAgent("ragAgent");
const userMessage = context.activity.text;
const result = await mainAgent.generate(userMessage)
await context.sendActivity(result.text);
});
結果&まとめ
MCPを用いた場合でもいい感じに出力されました!
今回は、エージェントフレームワークであるMastra
を用いてTeamsチャットボットの開発を行いました。
Typescript製のエージェントフレームワークの選択肢はPythonと比較して少ないものの、OpenAIのAgents SDK
やLangchainのlangchain-js
等、まだまだ比較検討しないといけないフレームワークが多く、選定が難しいです(そもそもフレームワークを使わない選択肢もある)。
Discussion