はじめに
こんにちは。
Web系エンジニアを目指して学習している学生です。
今回は、Dify と Notion MCP を使って、研究室の議事録AIチャットボットを作ろうとしたときのメモです。
研究室では、ミーティングの内容や担当タスクを後から確認したくなることがあります。
例えば、
- 前回のミーティングで何を決めたか
- 誰にどのタスクが割り当てられたか
- 次回までに何をすればよいか
といった内容です。
これらを Notion に議事録として残しておき、Dify のチャットボットから質問できるようにすれば便利そうだと思いました。
今回は、Dify の MCP 連携を使って、Notion の議事録を検索できるAIチャットボットを作ろうとしました。
ただし、実際にやってみると、単に Dify と Notion をつなぐだけでは終わりませんでした。
この記事では、
- なぜ作ろうと思ったか
- どのような構成にしたか
- 実際にやったこと
- つまずいたところ
- MCP方式とナレッジ方式の違いについて考えたこと
をまとめます。
なお、この記事で使っている議事録データや質問例は、検証用にAIで作成したモックデータです。
実在の研究室の議事録や個人情報をそのまま使っているわけではありません。
また、今回のコードはAIに生成してもらったものをベースにしています。
ただし、生成されたコードをそのまま使うだけではうまくいかず、Dify側の挙動やNotion検索の仕様に合わせて修正が必要でした。
作ろうとしたもの
作ろうとしたものは、研究室の議事録AIチャットボットです。
やりたいことは、以下のような流れです。
Notionに議事録を保存する
↓
Difyのチャットボットに質問する
↓
DifyがMCPサーバー経由でNotionを検索する
↓
議事録の内容をもとに回答する
想定していた質問は、例えば以下のようなものです。
2025年11月6日のミーティングで、佐藤さんに割り当てられたタスクは何?
この質問に出てくる日付、名前、タスク内容は、検証用のモックデータです。
人間であれば、Notionの議事録を開いて、該当する日付や担当者を見れば確認できます。
これをAIチャットボットに任せられれば、議事録を毎回探しに行かなくても済むと考えました。
全体構成
今回の構成は、ざっくり以下のような形です。
ユーザー
↓
Dify チャットボット
↓
MCPサーバー(Render / Express)
↓
Notion API
↓
Notion 議事録DB
DifyからNotionへ直接アクセスするのではなく、間にMCPサーバーを置きました。
今回は自分だけでなく、研究室内の別の人にも使ってもらう想定だったため、自分のPC上でだけ動くローカル構成にはしませんでした。
自分のPCでサーバーを動かす構成にすると、自分のPCが起動していて、かつサーバーが動いている間しか使えません。
そのため、RenderにMCPサーバーをデプロイし、Difyから外部アクセスできる形にしました。
DifyのMCP連携では、HTTP/SSE形式のエンドポイントを指定する必要があったため、Expressで簡単なSSEエンドポイントを用意しました。
SSEについては、自分もまだ深く理解できているわけではありません。
この記事では、DifyとMCPサーバーをつなぐための通信口くらいの理解で進めています。
やったこと
1. Notion Integrationを作成する
まず、Notion側でIntegrationを作成しました。
これは、外部アプリケーションからNotion APIを使うための設定です。
今回は、研究室内で使う想定のツールなので、公開アプリのようなOAuthではなく、内部連携用のIntegrationを作成しました。
作成したIntegrationに対して、Notionの議事録DBへアクセスする権限を付与します。
ここで注意が必要なのは、Integrationを作成しただけでは対象のDBを読めないことです。
Notionの議事録DB側で、作成したコネクトを追加する必要があります。
この設定を忘れると、APIキー自体は正しくても、Notion側のデータを取得できません。
2. MCPサーバーを用意する
次に、DifyとNotion APIの間に置くMCPサーバーを用意しました。
今回は、AIに生成してもらったコードをベースに、Node.js / Expressで簡単なサーバーを作りました。
このサーバーでは、主に以下のような処理を行います。
Difyからの接続を受ける
DifyからJSON-RPC形式のリクエストを受ける
Notion APIに検索リクエストを投げる
検索結果をDifyへ返す
当初はMCP SDKを使う構成も考えました。
ただ、依存関係やSDKのバージョン差分で詰まりやすかったため、最初はExpressで手書きする最小構成にしました。
今回の目的は、MCP仕様をきれいに実装することよりも、まずDifyからNotionを検索できるところまで動かすことでした。
まずはローカルで、thunder clientから /message にJSON-RPC形式のリクエストを投げて確認しました。
3. Renderにデプロイする
作成したMCPサーバーは、Renderにデプロイしました。
Render側では、Notion APIキーを環境変数として設定しました。
GitHubにAPIキーを直接置くのは危険なので、.env やRenderの環境変数で管理します。
デプロイ後、Renderから発行されたURLに /sse を付けて、Dify側に登録しました。
例としては、以下のような形です。
https://example.onrender.com/sse
4. DifyにMCPサーバーを登録する
Dify側では、MCPサーバーとしてRenderのURLを登録しました。
ここでDifyがMCPサーバーに接続できれば、チャットボットの中でNotion検索用のツールを使えるようになります。
今回は、まず search_notion のような検索用ツールを用意し、DifyからNotion内のページや議事録を検索できるようにしました。
つまずいたところ
1. Notion Integrationを作っただけではDBを読めない
最初に気をつける必要があったのは、Notion Integrationの権限です。
NotionのIntegrationを作成してAPIキーを取得しても、それだけでは対象のページやDBにはアクセスできません。
対象の議事録DBに対して、作成したコネクトを追加する必要があります。
これはNotion APIを使うときにかなり重要なポイントだと感じました。
自分の感覚では、APIキーを作った時点でワークスペース内のデータにアクセスできるように思ってしまいました。
しかし、実際にはページやDBごとにアクセス許可を与える必要があります。
2. Difyの承認エラーが出た
DifyにMCPサーバーを登録しようとしたとき、承認エラーが出ました。
最初はDify側の設定ミスかと思いましたが、原因はMCPサーバー側にありました。
DifyはMCPサーバーに接続するとき、最初に initialize という初期化リクエストを送ります。
しかし、当初のサーバーでは tools/list や tools/call しか処理しておらず、initialize に対応していませんでした。
そのため、Difyから見ると、MCPサーバーとして初期化できない状態になっていました。
最終的には、以下のようなメソッドに対応することで進めるようになりました。
initialize
notifications/initialized
ping
ここで、MCPは単にツールを呼び出せればよいわけではなく、最初の接続時のやり取りも必要なのだと理解しました。
3. SDK版と手書き版で迷った
MCPサーバーを作る方法として、MCP SDKを使う方法もあります。
SDKを使えば、MCPの仕様に沿った実装をしやすいはずです。
一方で、今回の自分の環境では、SDKやNotion SDKまわりの依存関係で詰まりました。
また、AIに生成してもらったコードも、SDKのバージョン差分に影響されてそのままでは動かない部分がありました。
そのため、今回はいったんExpressとfetchを使った手書きの構成にしました。
Difyが /sse に接続し、/message にJSON-RPCを送り、サーバー側でNotion APIを呼び出して結果を返す、という最小構成です。
長期的にはSDKを使う方がよい場面もあると思います。
しかし、今回はまず動かして仕組みを理解することを優先しました。
4. search_notion だけでは議事録の中身まで読めない
接続ができたあと、実際にDifyから質問してみました。
質問した内容は以下です。
2025年11月6日のミーティングで、佐藤さんに割り当てられたタスクは何?
この質問と回答対象のデータは、検証用にAIで作成したモックです。
Dify上ではNotion検索ツール自体は使われていました。
しかし、最初は期待した回答が返ってきませんでした。
2025年11月6日のミーティングで佐藤さんに割り当てられたタスクについてNotionを検索しましたが、一致する情報は見つかりませんでした。
この時点で、DifyとNotion MCPをつなぐこと自体はできていました。
しかし、議事録AIチャットボットとしては、まだ不十分でした。
原因の一つは、search_notion がNotion内を検索するだけで、ページ本文やDBの中身を十分に読めていなかったことです。
つまり、AIは「それっぽいページを探す」ことはできても、そのページの中にあるタスク情報を正確に読み取るところまではできていませんでした。
そのため、検索用のツールだけでなく、ページ本文やDBの中身を読むためのツールも必要だと分かりました。
例えば、以下のような使い分けです。
search_notion:
関連しそうなページやDBを探す
read_notion_page:
見つけたページの中身を読む
read_notion_database:
DBの行や列を読む
AIに外部ツールを持たせる場合、単に検索ツールを渡すだけでは不十分なことがあります。
「探す」と「読む」は別の処理として設計した方がよいと感じました。
5. AIが検索キーワードを細かくしすぎた
もう一つの原因は、AIがNotion検索に渡すキーワードでした。
Difyの実行ログを見ると、AIは以下のような検索をしていました。
2025年11月6日 ミーティング タスク 佐藤
人間であれば、まず「議事録」や「2025年11月6日」などで大きく検索し、見つかったページを開いて中身を確認します。
しかし、AIは質問文に含まれる単語をそのまま全部検索キーワードとして使っていました。
その結果、Notion検索では該当ページが見つかりにくくなっていました。
この経験から、AIにツールを使わせる場合は、プロンプトでツールの使い方を具体的に指示する必要があると分かりました。
例えば、以下のような指示です。
Notionを検索するときは、検索キーワードを1〜2語程度にしてください。
まず「議事録」や日付などで関連ページを探し、見つかったページの本文やDBを読んでから回答してください。
AIにツールを渡せば勝手にうまく使ってくれると思っていましたが、実際にはツールの使い方も設計する必要がありました。
6. 議事録の書き方も重要だった
今回の質問は、以下のような条件を含んでいました。
日付: 2025年11月6日
担当者: 佐藤さん
知りたいこと: 割り当てられたタスク
このような質問に答えさせたい場合、Notion側の議事録もAIが読み取りやすい形にしておく必要があります。
例えば、以下のような曖昧な書き方だと、AIにも検索にも厳しいです。
佐藤さんは来週までに例の件をお願いします。
人間なら文脈で分かるかもしれません。
しかし、AIに検索・抽出させるなら、以下のように構造化した方がよさそうです。
担当者: 佐藤
タスク: 実験結果をまとめた資料を作成する
期限: 2025-11-13
関連ミーティング日: 2025-11-06
この例も、検証用のモックです。
また、議事録DBとタスクDBを分ける構成も有効そうだと感じました。
議事録DB:
会議全体の内容を記録する
タスクDB:
担当者、期限、ステータス、関連ミーティング日を管理する
今回のように「誰が何を担当したか」を聞きたい場合、タスクを構造化して保存した方が、AIにも扱いやすそうです。
MCP方式を使って感じたこと
今回使ったMCP方式は、AIに外部ツールを使わせるエージェント方式に近いと感じました。
DifyのAIが、必要に応じてNotion検索ツールを呼び出し、その結果をもとに回答します。
この方式のよいところは、Notionの最新情報を取りに行けることです。
Notion側で議事録やタスクが更新されていれば、MCPサーバー経由でその時点のデータを取得できます。
一方で、実際に使ってみると、以下のような難しさもありました。
AIがどの検索キーワードを使うか
検索結果からどのページを読むか
ページ本文やDBのプロパティをどう取得するか
取得した情報からどう回答するか
つまり、MCPでNotionにつながったからといって、AIが勝手によしなに議事録を読んでくれるわけではありませんでした。
ツール設計とプロンプト設計がかなり重要です。
ナレッジ方式の方が向いていたかもしれない
今回の目的は、研究室の議事録を読み込んで質問に答えることでした。
この用途だけで考えると、Difyのナレッジ機能を使った方が向いていた可能性があります。
ナレッジ方式では、事前に資料やテキストをDifyに読み込ませておき、質問時に関連する内容を検索して回答します。
NotebookLMのように、資料を読み込ませて質問する体験に近いです。
一方、MCP方式は、Notionの最新情報をリアルタイムに取りに行けるのが強みです。
そのため、自分の中では以下のような使い分けがよさそうだと感じました。
Difyナレッジ方式:
議事録本文を読み込ませて、自然に質問回答したい場合に向いている
MCP方式:
Notionの最新DBを取得したい場合や、将来的にNotionへ書き込みたい場合に向いている
今回のように「議事録を読ませて質問に答えさせたい」だけなら、まずはナレッジ方式で作る方がシンプルだったかもしれません。
ただし、MCP方式を試したことで、AIに外部ツールを使わせるときの難しさを学べました。
今回学んだこと
今回の構築で学んだことは、主に以下です。
1. DifyとNotionをつなぐだけでは完成しない
DifyからNotionを検索できるようになっても、それだけでは議事録AIとしては不十分でした。
実際には、
- どのページを検索するか
- ページ本文をどう読むか
- DBのプロパティをどう扱うか
- AIにどうツールを使わせるか
まで考える必要があります。
2. AIに渡すツールは設計が必要
AIに search_notion のようなツールを渡しても、AIが必ずうまく使ってくれるわけではありません。
検索キーワードが細かすぎたり、検索だけで本文を読めなかったりすると、期待した回答になりません。
ツールの説明文や、Dify側のプロンプトも含めて調整する必要がありました。
3. 議事録の書き方もAI向けに整える必要がある
AIに議事録を読ませるなら、議事録側もある程度構造化した方がよさそうです。
特にタスク管理では、
- 日付
- 担当者
- タスク内容
- 期限
- ステータス
を明確にしておくと、後からAIが拾いやすくなります。
4. MCP方式とナレッジ方式は用途が違う
今回の構築を通して、MCP方式とナレッジ方式は別物だと感じました。
MCP方式は、AIが外部ツールを使って最新データを取りに行く方式です。
ナレッジ方式は、事前に読み込ませた資料をもとに質問回答する方式です。
どちらが上というより、用途に応じて使い分ける必要がありそうです。
5. 便利さと情報管理はセットで考える必要がある
DifyやMCPを使うと、AIが外部ツールを使って情報を取得できるようになります。
ただし、研究室や業務のデータを扱う場合は、便利さだけでなく、情報管理も同時に考える必要があります。
特に、未公開の研究内容、個人情報、特許に関わる可能性のあるアイデアなどは、安易に外部AIへ渡さないように注意が必要だと感じました。
次回やりたいこと
次は、Difyのナレッジ機能を使って、NotebookLMのような議事録AIを作ってみたいです。
今回のMCP方式では、Notionの最新情報にアクセスできる一方で、議事録本文に対する自然な質問応答では少し大がかりだ感じました。
そのため、次回は以下を試したいです。
Difyのナレッジ機能に議事録を読み込ませる
NotebookLMのように議事録へ自然に質問できる形にする
MCP方式とナレッジ方式の使い勝手を比較する
議事録QAはナレッジ、最新タスク取得や更新はMCP、という使い分けを検討する
MCP方式を試したことで、エージェント的に外部ツールを使わせる難しさが分かりました。
次は、よりシンプルに議事録QAを作る方法として、ナレッジ方式を試してみたいです。
まとめ
今回は、Dify × Notion MCPで研究室の議事録AIチャットボットを作ろうとしました。
DifyとNotionを接続するところまでは進められましたが、実際にモックデータに対して「2025年11月6日のミーティングで、佐藤さんに割り当てられたタスクは何?」と質問すると、期待通りには答えられませんでした。
原因としては、
- Notion検索だけではページ本文やDBの中身まで十分に読めない
- AIが検索キーワードを細かくしすぎる
- 議事録やタスク情報の構造化が不足している
- ツール設計とプロンプト調整が必要
といった点がありました。
今回の経験から、MCPは外部ツールを使うAIエージェントを作る上で面白い仕組みだと感じました。
一方で、議事録を読み込ませて質問に答える用途では、Difyのナレッジ機能の方が向いている場面もありそうです。
次回は、Difyのナレッジ機能を使って、NotebookLMのような議事録QAチャットボットを作ってみたいと思います。



