はじめに
前編「MCPサーバーの最小構成を作ってみる(Node.js版) 」では、Model Context Protocol(MCP)プロトコルの仕様を軽く解説し、OpenAIやClaudeなどのAPIを持たなくてもMCPツールの開発及び検証の方法を紹介しました。
本編では、実際にAIサービス(Google Gemini)のAPIを使って、本物のAI Agentを開発してみます。
シリーズ記事
№ | 記事 | 内容 |
---|---|---|
1 | MCPサーバーの最小構成を作ってみる(Node.js版) | AIサービスのアカウントを持たなくてもMCPツールの開発ができます |
2 | 簡単なMCP利用可能なChatbotを作ってみる(Google Gemini版) | 本編 |
3 | MCPサーバーの最小構成を作ってみる(Python版) | Coming Soon |
4 | 簡単なMCP利用可能なChatbotを作ってみる(Azure OpenAI版) | Coming Soon |
5 | RAGをMCPサーバーとして利用し、簡単な映画推薦Chatbotを作ってみる(Azure OpenAI版) | Coming Soon |
6 | MCPを活用してAI Agentで定期タスクを実行できるように | 自分自身に指向するMCPサーバーを使って、定期タスクを実装する方法 |
実装
実行環境
- Node.js (v20以上)
Google Gemini APIキーの申請
下記のページにアクセスし、 「Google AI Studio で無料で取得」 をクリックして、案内に従えば無料に取得できます。
Google GeminiのAPIキーを取得したら、 環境変数 GEMINI_API_KEY
をセットアップします。
パッケージのインストール
npm i @google/genai @modelcontextprotocol/sdk dotenv
また、試したいMCPツールがあれば、事前にインストールすると、後ほどスムーズに実行できるので、 事前インストールをおすすめします。
Geminiチャットボットの実装
まずはMCPツールを持たない単純なAIチャットボットを作ります。使ったのはGemini SDKのマルチターンの会話(チャット)APIです。
import { GoogleGenAI } from '@google/genai';
import { createInterface } from "readline/promises";
import dotenv from "dotenv";
dotenv.config(); // .envファイルを読み込む
// クライアントを設定
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const chat = ai.chats.create({
model: "gemini-2.0-flash",
config: {
systemInstruction: "あなたはMCPを使って、いろんな操作を行うことができます。",
},
});
// ユーザー入力用のreadlineインターフェースを作成
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
// readlineインターフェースのプロンプトを設定
rl.setPrompt(`Waiting for chat input... \n> `);
rl.prompt();
rl.on("line", async (line) => {
const trimmedLine = line.trim();
// 入力が空の場合は再度プロンプトを表示
if (!trimmedLine) {
rl.prompt();
return;
}
try {
const response = await chat.sendMessage({
role: "user",
message: { type: "text", text: trimmedLine },
});
console.log("Gemini: ", response.text);
} catch (error) {
console.error("Error: ", error);
} finally {
rl.prompt();
}
});
Node.jsのReadlineを使って、非同期的にコマンドラインの入力を取得し、GeminiのチャットAPIで送信しています。
実行結果:
$ node gemini_demo.mjs
Waiting for chat input...
> こんにちは
Gemini: こんにちは!何かお手伝いできることはありますか?
Waiting for chat input...
>
MCPツールの活用
今回の記事は前回で作られた「Streamable HTTPを使ったMCPサーバー」 add_http.mjs
、及び公式のFilesystem MCP Serverを使って Streamable HTTP
と STDIO
二種類のClientをDemoします。
[注意]: Google Geminiは現在(2025-06-18)MCPサポートが試験運用であるため、ツールのみがサポートされ、リソースやプロンプトはサポートされないとのことです。
MCP Clientの初期化
尺を考慮して、ここは追加分のコードのみ展示します。フルバージョンのソースコードをみたい方は文末の Full Souce Code を参照してください。
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
// MCPサーバーの設定
const stdioTransport = new StdioClientTransport({
command: "npx",
args: ['-y', '@modelcontextprotocol/server-filesystem', './'],
});
const client1 = new Client(
{
name: "server-filesystem",
version: "1.0.0"
}
);
await client1.connect(stdioTransport, { timeout: 30000 });
// HTTP Transportの設定
const httpTransport = new StreamableHTTPClientTransport(
new URL("http://localhost:3000/mcp"),
{
sessionId: undefined,
requestInit: { headers: { } },
},
);
const client2 = new Client(
{
name: "demo-http-client",
version: "1.0.0"
}
);
await client2.connect(httpTransport);
Geminiにツールを提供する
ここも変更点だけ表示します。。フルバージョンのソースコードをみたい方は文末の Full Souce Code を参照してください。
- import { GoogleGenAI } from '@google/genai';
+ import { GoogleGenAI, mcpToTool } from '@google/genai';
...
// クライアントを設定
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const chat = ai.chats.create({
model: "gemini-2.0-flash",
config: {
systemInstruction: "あなたはMCPを使って、いろんな操作を行うことができます。",
+ tools: [ mcpToTool(client1), mcpToTool(client2) ],
},
});
...
見た通り、Gemini SDKは mcpToTool()
という便利メソッドを提供していて、標準のMCP SDKのClientをGeminiが利用できるツール形式に変換してくれます。変換したツールは、Geminiのサービスを初期化する際に、tools
フィールドに提供すれば利用できます。
実行結果:
まずは別のターミナルで node add_http.mjs
で自前のMCPサーバーを立ち上げます。
$ node gemini_demo.mjs
Secure MCP Filesystem Server running on stdio
Allowed directories: [
'PATH/TO/YOUR/DIR'
]
Waiting for chat input...
> こんにちは、現在使えるMCPツールの一覧を出してください。
Gemini: 現在使えるMCPツールは以下の通りです。
- read_file
- read_multiple_files
- write_file
- edit_file
- create_directory
- list_directory
- directory_tree
- move_file
- search_files
- get_file_info
- list_allowed_directories
- add_test
また、アクセス可能なディレクトリは `PATH/TO/YOUR/DIR` です。
Waiting for chat input...
> MCPツールadd_testは何ができます?
Gemini: MCPツール`add_test`は、与えられた2つの数値(aとb)を足し算し、さらにその結果に10を足した値を返します。
Waiting for chat input...
> このツールで12+20を計算して
Gemini: 12 + 20 の計算結果は 42 です。
Waiting for chat input...
> 上記結果を./result.csvに保存して
Gemini: 結果を ./result.csv に保存しました。
Waiting for chat input...
> ./result.csvの内容を読み取って
Gemini: ./result.csv の内容は "42" です。
Waiting for chat input...
>
Full Souce Code
gemini_demo.mjs
import { GoogleGenAI, mcpToTool } from '@google/genai';
import { createInterface } from "readline/promises";
import dotenv from "dotenv";
dotenv.config(); // .envファイルを読み込む
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
// MCPサーバーの設定
const stdioTransport = new StdioClientTransport({
command: "npx",
args: ['-y', '@modelcontextprotocol/server-filesystem', './'],
});
const client1 = new Client(
{
name: "server-filesystem",
version: "1.0.0"
}
);
await client1.connect(stdioTransport, { timeout: 30000 });
// HTTP Transportの設定
const httpTransport = new StreamableHTTPClientTransport(
new URL("http://localhost:3000/mcp"),
{
sessionId: undefined,
requestInit: { headers: {} },
},
);
const client2 = new Client(
{
name: "demo-http-client",
version: "1.0.0"
}
);
await client2.connect(httpTransport);
// クライアントを設定
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const chat = ai.chats.create({
model: "gemini-2.0-flash",
config: {
systemInstruction: "あなたはMCPを使って、いろんな操作を行うことができます。",
tools: [ mcpToTool(client1), mcpToTool(client2) ],
},
});
// ユーザー入力用のreadlineインターフェースを作成
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
// readlineインターフェースのプロンプトを設定
rl.setPrompt(`Waiting for chat input... \n> `);
rl.prompt();
rl.on("line", async (line) => {
const trimmedLine = line.trim();
// 入力が空の場合は再度プロンプトを表示
if (!trimmedLine) {
rl.prompt();
return;
}
// "exit"と入力された場合は終了
if (trimmedLine.toLowerCase() === 'exit') {
console.log("Exiting...");
// readlineインターフェースを閉じる
rl.close();
// クライアントを閉じる
console.log("Closing clients...");
await Promise.all([
client1.close(),
client2.close(),
]).catch(console.error);
process.exit(0);
}
try {
const response = await chat.sendMessage({
role: "user",
message: { type: "text", text: trimmedLine },
});
console.log("Gemini: ", response.text);
} catch (error) {
console.error("Error: ", error);
} finally {
rl.prompt();
}
});
余談: Geminiの読み方
天文学や西洋占星術に詳しい方だと、 Gemini は「ふたご座」を意味すると気付くでしょう。星座を表す時、Geminiの発音は「ジェミナイ」(英語発音: [ˈdʒɛmɨnaɪ])ですが、 Google Gemini語源は星座ではなく、アメリカが1960年代実行した有人宇宙計画「ジェミニ計画」ですので、故に読み方は「ジェミニ」と確定です。
まぁ、本家のビデオや宣伝資料もご丁寧に「Gemini(ジェミニ)」と書いていますね。