はじめに
技術書典や技書博(技術書同人誌博覧会)の開催に合わせて商業誌「はじめてのNode-RED MCU Edition」の補足書を執筆しています。
この記事は「はじめてのNode-RED MCU Edition補足書 (2025年11月15日版)」からの抜粋で、Node-RED MCU EditionでMCPサーバーを動かす記事です。
LLMとMCPの関係
LLMは大規模言語モデル ( Large Language Model ) の略で、膨大なテキストデータから学習し、人間のように自然言語を生成・理解できるAIモデルのことです。
MCPはModel Context Protocolの略で、LLMを外部システムやツールとつなぐための共通プロトコルです。
LLMとMCPを組み合わせることで「会話AI」から行動できる「エージェント」へ進化します。
構成
Node-REDの標準ノードのみでMCPサーバーを動かします。PC(macOS)にMCPクライアント機能を持った
Claude DesktopをインストールしてMCPホストとします。
LLMはClaude(Sonnet 4.5)を使用します。無料プランで利用可能です。
MCPサーバはWi-Fi機能を持ったESP32(M5Stack ATOMS3)を使用します。
MCPクライアントとLLMおよびMCPサーバはネットワーク(HTTP)で接続します。
MCPのライフサイクル
3つのフェーズ(Initialization、Operation、Shutdown)が定義されています。
Initialization
MCPクライアントがMCPサーバーに接続する時の初期化フェーズです。
関数(リクエスト)は2つです。
| 関数 | 説明 |
|---|---|
| initialize | 初期化 |
| notifications/initialized | 初期化完了通知 |
MCPクライアントからのinitializeリクエストに対して、MCPサーバーはMCPクライアントにHTTP 200を応答します。(msg.idはリクエストに含まれるidの値を設定します)
{
"jsonrpc": "2.0",
"id": msg.id,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {},
"prompts": {},
"resources": {}
},
"serverInfo": {
"name": "hello-world-mcp-server",
"version": "1.0.0"
}
}
}
MCPクライアントからのnotification/initializedリクエストに対して、MCPサーバーはMCPクライアントに空のHTTP 204を応答します。
Operation
MCPクライアントとMCPサーバーがメッセージをやり取りするフェーズです。
関数(リクエスト)は7つですが、4つのみ実装します。(実質的にはtoolsのみ実装します)
| 関数 | 説明 | 実装 |
|---|---|---|
| prompts/list | 定型プロンプトのリストを取得 | ○(応答しない) |
| prompts/get | 指定した定型プロンプトを取得 | |
| resources/list | リソースのリストを取得 | ○(応答しない) |
| resources/read | 指定したリソースを取得 | |
| resources/subscribe | 指定したリソースをサブスクライブ | |
| tools/list | ツールのリストを取得 | ○(応答する) |
| tools/call | 指定したツールを実行 | ○(応答する) |
MCPクライアントからのtools/listリクエストに対して、MCPサーバーはMCPクライアントにHTTP 200を応答します。(msg.idはリクエストに含まれるidの値を設定します)
{
"jsonrpc": "2.0",
"id": msg.id,
"result": {
"tools": [
{
"name": "hello_world",
"description": "Returns a simple hello world message",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to greet (optional)"
}
}
}
}
]
}
}
MCPクライアントからのtools/callリクエストに対して、MCPサーバーはMCPクライアントにHTTP 200を応答します。(msg.idはリクエストに含まれるidの値、msg.nameはリクエストに含まれるnameパラメータの値を設定します)
{
"jsonrpc": "2.0",
"id": msg.id,
"result": {
"content": [
{
"type": "text",
"text": "Hello " + msg.name + ", This is a simple MCP server response."
}
]
}
}
MCPクライアントからのprompts/listリクエストとresources/listリクエストに対して、MCPサーバーはMCPクライアントにエラー応答(HTTP 200)を返すべきですが、MCPサーバーの処理が追いつかずMCPクライアントがタイムアウト(5秒)でエラーになるため、MCPサーバーは応答しない実装(タイムアウト後にMCPクライアントからMCPサーバーへnotifications/cancelledリクエストを送信)にしました。
Shutdown
MCPクライアントがMCPサーバーとの接続を切断するフェーズです。
関数は定義されておらず、HTTP接続を切断すれば完了です。
Node-REDフロー
標準ノード(「http in」「http response」「delay」「switch」「change」「function」「debug」ノード)を使用してフローを作成します。
参考にしたNode-REDフローでは「サブフロー」が使用されていますが、Node-RED MCUではサポートされていないため、通常のフローに置き換えました。
また、「change」ノードの中でJSONata表記が使用されていますが、これもNode-RED MCUではサポートされていないため、「Function」ノードに置き換えました。
動作確認の段階で、MCPクライアントからのリクエストに対してMCPサーバーの処理が追いつかず、MCPクライアントがタイムアウト(5秒)でエラーになる事象を確認したため、一部のリクエスト(前述のprompts/listとresources/list)に対して応答しない実装(「delay」ノードの挿入、未対応のMCPリクエストのフローを接続しない)にしています。
Node-REDフローのサンプルをGitHubに公開しています。
Claude Desktopの設定
MCPサーバーを設定します。
アカウントのメニューを開いて「設定」→「開発者」→「設定を編集」を選択します。
claude_desktop_config.jsonファイルをテキストエディタで開き、以下の内容を記載します。MCPサーバーのIPアドレスにはESP32(M5Stack ATOMS3)に付与されたIPアドレスを設定します。MCPサーバーとHTTPS(セキュア)ではなくHTTP(非セキュア)で接続する場合、”-y”と”--allow-http”を設定する必要があります。
{
"mcpServers": {
"hello-world-mcp-server": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://MCPサーバーのIPアドレス/mcp-server/mcp",
"--allow-http"
]
}
}
}
ファイルを保存したら、一旦Claude Desktopを終了し、再度起動します。追加したMCPサーバーが「running」と表示されていれば正常です。(異常の場合は「failed」と表示されます)
動作確認
新規チャットを開き、「検索とツール」からMCPサーバー(hello-world-mcp-server)を有効化(スライダーをON)します。
プロンプトで「hello worldを使ってください。名前はtestです。」と入力し、MCPサーバーのツールが使用されていれば正常です。






