AI向けナレッジの作り方 後編 MCPでつなぐ自分と会社のAIコンテキスト
GitHubに置いたAI向けナレッジを、MCPサーバーでどのAIクライアントからも参照できるようにします。さらに会社で共有すべき情報を分離し、経営方針を社内へ届ける新しい経路になった実践を紹介します。
前回まで
前回は、AIの回答が一般論で終わるのは自分の情報を渡していないからだと考え、GitHubリポジトリにMarkdownでナレッジを蓄積する方法を紹介しました。経歴のようなプロフィールではなく、多くの場面の判断に使える基準を、AIが読む前提で過不足なく書くのがポイントでした。ナレッジ1件は1つのMarkdownファイルで、本稿でもこれを記事と呼びます。
今回は、これをどの環境のAIからも参照できるようにするMCPサーバーと、個人のナレッジを会社へ展開した話です。
ナレッジをPCの外へ
GitHubリポジトリに置いたナレッジは、PCの上で使う分には困りません。コーディングエージェントならローカルにcloneしたファイルをそのまま読めます。困るのはモバイル環境です。iPhoneのChatGPTに相談するとき、リポジトリのナレッジを参照させる手段がありません。
そこでMCP(Model Context Protocol)を使います。MCPはAIに外部のデータやツールを接続するための標準プロトコルで、ChatGPT、Claude、OpenCodeなどが対応しています。
- ChatGPT:デベロッパーモードとMCPアプリ
- Claude:リモートMCPを使用したカスタムコネクタの開始方法
- OpenCode:MCPサーバー
MCPサーバーはローカルで動かすこともできますが、iPhoneから使えるのは、ネットワーク越しに接続するリモート方式だけです。ナレッジを配信するリモートMCPサーバーを作れば、この問題を解決できます。
標準プロトコルであることも決め手でした。1つ作れば、ChatGPTとClaudeのどちらからも同じサーバーに接続できます。前回、メモリ機能を使わず自分で管理するMarkdownを選んだのと同じように、今回も特定のサービスに依存しない構成を選びました。
Cloudflare Workersで最小構成
構成は次のとおりです。
全体の構成
GitHubリポジトリ(ナレッジの本体)
│ pushをトリガーに自動ビルド・デプロイ
▼
MCPサーバー(Cloudflare Workers + Cloudflare Access)
│
▼
ChatGPT / Claude / コーディングエージェント
サーバー構成のポイント
サーバーはCloudflare Workersで動かしています。特徴は、データベースを持たない小さな構成にしたことです。ビルド時にMarkdownをすべて読み込み、静的なデータとしてコードにバンドルします。リポジトリへのpushをトリガーにビルドとデプロイが自動で走るため、記事を書いてpushすれば配信内容も追従します。ナレッジの本体はあくまでGitHubリポジトリにあり、サーバーはそれを/mcpというパスで配信するだけです。
認証はCloudflare Accessに任せました。個人のナレッジには判断基準や非公開の情報が含まれるため、誰でも読める状態にはできません。ChatGPTを含むクライアントでは、OAuthの対応を求められます。自前で実装するのは避けたいところです。
補足:Cloudflare Accessの導入
Cloudflare Accessの仕組みと設定手順は、CodeGridの次の記事で解説しています。
AccessをMCPサーバーの手前に置けば、認証と接続の制御をAccess側に任せられます。許可したアカウントだけが接続できるので、サーバー本体に認証コードを書く必要はありません。
workers.devのURLとプレビューURLも無効にしました。外部からアクセスできるのは、Cloudflare Accessで守ったカスタムドメインだけです。
ただ、これで全部終わるわけではありません。クライアントによって接続手順も使える機能も違うため、サーバーを作ったあとに、それぞれに合わせた設定が必要になります。
公開するツール
読み取り用に公開するツールは3つだけです。現在は、これにナレッジ候補を登録する書き込み用のツールを加えています。
| ツール | 役割 |
|---|---|
list_docs |
記事の一覧(パスとタイトル)を返す |
get_doc |
指定した記事の本文を返す |
grep_docs |
全記事をキーワードで検索する |
propose_knowledge_candidate |
新しいナレッジ候補をGitHub Issueへ登録する |
全記事をまとめて読ませる設計にしなかったのは、トークン消費を抑えるためです。AIはまず一覧や検索で当たりをつけ、必要な記事だけを取得します。前回の「過不足なく」という方針を、配信の仕組みでも守っている形です。
一方で、新しいナレッジ候補の登録は、Issueを登録するか書き換える処理です。AIが内容を勝手に決めてしまわないよう、登録する内容を先に示し、筆者が確認してから書き込みを実行させます。
もう一つ気をつけたのが、ツールのdescriptionとannotationsです。AIは説明文を読んで、どのツールをいつ使うか決めます。たとえばlist_docsには、「まず一覧を取得し、必要な記事だけget_docで取得する。全文を一度に取らないこと」と書いてあります。
annotationsには、そのツールが読み取り専用なのか、外部への書き込みを行うのかといった情報を設定します。実際の動作に合わせておけば、接続したAIツールが許可を求めてきたときにも、その操作をどう扱うか判断しやすくなります。
MCPサーバーの実装
サーバーの中身を知りたい人向けに、コードを少し載せます。実装はMCPの公式SDK(@modelcontextprotocol/server)と、CloudflareのagentsパッケージにあるcreateMcpHandlerの組み合わせです。Workerの中身は、ツールを登録してハンドラーに渡すだけです。
src/index.ts
import { createMcpHandler } from "agents/mcp/server";
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";
import { DOCS, getDoc } from "./knowledge.generated";
function buildServer(): McpServer {
const server = new McpServer({ name: "kyosuke-knowledge", version: "0.1.0" });
server.registerTool(
"get_doc",
{
description: "指定したパスのナレッジ記事の本文を返す。パスは list_docs が返す値を使う。",
inputSchema: z.object({
path: z.string().describe("記事のパス。例: dev/tech-stack.md"),
}),
annotations: { readOnlyHint: true, openWorldHint: false },
},
async ({ path }) => {
const doc = getDoc(path);
if (!doc) {
return { content: [{ type: "text", text: `not found: ${path}` }], isError: true };
}
return { content: [{ type: "text", text: doc.content }] };
},
);
return server;
}
export default {
fetch(request, env, ctx) {
return createMcpHandler(buildServer, { route: "/mcp" })(request, env, ctx);
},
} satisfies ExportedHandler<Env>;
読みやすさのために、ほかのツールの登録と型の注釈は省いています。importしているknowledge.generated.tsは、デプロイ前に走らせるスクリプトの出力です。リポジトリのMarkdownを読み、パスとタイトルと本文を持つDOCSという配列に書き出します。記事48ファイルで230KBほどなので、Workersのサイズ上限には余裕をもって収まります。外部への問い合わせはなく、この配列を引くだけで応答できます。
会社で共有できる部分を切り出す
個人のナレッジを運用しているうちに、会社に関する記事が増えてきました。会社の基本情報、経営理念、案件を選ぶ基準。これらは筆者個人というより、ピクセルグリッドという組織の判断基準です。個人のリポジトリに閉じ込めておくのはもったいないと考え、共有すべき記事をcompany-contextという別リポジトリへ分離しました。個人側に残したのは、会社へ載せない情報だけです。同じ構成のMCPサーバーを別に立て、社内の誰でも自分のAIツールから接続できるようにしています。
この分離も、最初からすべての置き場所を決めていたわけではありません。まずは個人のナレッジとして一緒に管理しました。実際に使う中で、個人の判断基準なのか、会社として持つべき情報なのか、誰に共有してよいのかを見極めたのです。ナレッジを1つの場所から始めると、書いてある内容だけでなく、利用者や更新責任の違いも見つけやすくなります。
分離にあたって決めたのが、掲載可否の基準です。「社外に公開して安全か」ではなく、「社内全員のAIツールから見えてよいか」で判断します。認証を会社のGoogle Workspaceでのシングルサインオンにしたため、会社ドメインのアカウントを持つメンバーだけが接続できます。社外公開が前提なら載せられない情報も、この境界の内側なら共有できるわけです。
補足:社内で使うAIのプラン
社内で使うAIは、会社が契約しているChatGPT BusinessとClaude Teamです。どちらも、入力したデータを既定ではモデルの学習に使わないプランです。会社のナレッジをAIから引く運用は、この前提の上に成り立っています。個人向けのプランではデータの扱いが違うため、社内の情報を通す前に確認が必要です。
この基準は、AI自身の振る舞いにも表れました。社員の呼び名の対応表を個人リポジトリから移す作業中、AIが手を止めて確認してきたのです。
表の大部分は、スタッフのGitHubやXのアカウントなど、会社サイトで公開済みの内容です。しかし、ビジネスネームに旧姓を使うメンバーもいて、本名との対応まで載っていました。こうした情報は労務管理での名寄せに役立つ一方、全社員のAIツールから引ける場所に置くべきか判断が分かれる、という指摘でした。労務を扱う担当者だけが知っていれば足ります。
掲載の基準をリポジトリのルールとして書いておいたことで、記事を移す作業そのものの判断にも使われたことになります。
既存のナレッジベースにつなぐだけではだめなのか
ナレッジを整備していたとき、社内から「既存のナレッジがあるのだから、それに接続するだけではだめなのか」と聞かれました。
もっともな疑問です。ピクセルグリッドが社内Wikiとして使っているesaには有益なナレッジが蓄積されています。多くの会社で使われるNotionと同じように、esaもMCPサーバーを提供しています。接続の手間だけを見れば、専用のリポジトリを作るよりずっと少なく済みます。
それでも分けたのは、社内ドキュメントが人間向けに書かれているからです。経緯の説明や当時の議論、読みやすさのための文脈は、人間の理解には役立ちますが、AIにとってはノイズです。議事録のような文書も大量にあるため、判断に必要な情報を集めるだけでかなりのトークンを使います。書かれた時期もばらばらで、現行の方針と古い方針が混在しています。
AIを対象としたコンテキストでは、判断に必要な前提や制約、例外を、いま正しいこととして書きます。「引き受ける仕事の範囲」を人間向けとAI向けの両方へ書いたことがあるので、そちらを例にします。
引き受ける仕事の範囲を決めたとき、esaへ「サーバーは持たず、データは設計する」という記事を出しました。フロントエンド専門という説明が実態とずれてきた経緯、社内から出た「DBの設計はやらないのか」という声、AIがあるならWordPressもやればいいという逆向きの意見。どう考えて線を引いたのかを、順を追って書いています。
ナレッジのほうは「アプリケーションは作るが、実行基盤は運用しない」という記事です。冒頭には要約と、前回紹介した「内容を最後に確認した年月」を入れました。扱う範囲を箇条書きで並べ、DBはマネージドサービスから選ぶ、コンテナ基盤は標準構成にしない、と現在の結論だけを置きました。末尾の「AIへの解釈メモ」では、構成の提案ではCloudflareを第一候補にする、認証は既製のサービスを前提にする、と振る舞いまで指定しています。一覧にない技術も、名前ではなく維持責任で判定するよう書いてあります。
また、筆者が目指しているのは会社の判断を代行できることです。そのための基準や、指定がないときのデフォルトは、社内ナレッジだけでは足りません。既存のナレッジベースは活用しつつ、AIが使う前提は別に整えました。手間はかかりますが、その分だけAIを経由した情報伝達が正確になります。
経営方針が伝わる新しい経路
会社のリポジトリに入れたのは、会社概要のような情報だけではありません。経営理念、どんな案件を選ぶのか、セキュリティをどう扱うのかまで、意思決定のよりどころになる考え方を中心に置いています。
会社用のナレッジを作ってみて、方針を社内に伝える手段にもなると気づきました。方針は、決めるよりも伝え続けるほうが難しいものです。ドキュメントにまとめても読まれず、口頭で伝えても、その場限りで終わってしまいます。経営者やマネージャーなら、一度はこうした苦労を経験しているのではないでしょうか。
今期の戦略を書いた記事も置いています。1年ごとだけでなく、期のなかでもこまめに見直します。いまの環境をどう見ているか、その認識のもとで何に取り組むか、クライアントワークとCodeGridのどちらに重心を置くかを並べています。組織と体制をどう変えていくかも入れました。収益や目標の数字は載せていません。数字が前提になる判断は代表に聞いてほしいと書き添えました。
AI経由の伝わり方は少し違います。社員がわざわざ読みに行かなくても、日々の業務相談への回答に方針が織り込まれるのです。たとえば「このAPIキーはどこに保存すべきか」とAIに聞けば、会社のセキュリティ方針に沿った保存先が返ってきます。「このサービスを導入すべきか」という相談なら、社員数や事業内容を踏まえて「この規模の会社には過剰では」という判断が返ります。
こうした記事は、発表直後は目を通してもらえても、その後何度も読まれるわけではありません。MCPを用意すれば、必要な場面でAIが自動で参照できます。外部環境や経営の判断で方針が急に変わっても、AIが読むナレッジはpushした時点で切り替わります。
判断基準はコピーできない
まねできるのは、仕組みだけです。リポジトリの構成もMCPサーバーの実装も、そっくり同じにするのは簡単です。取り入れられそうだと思ったら、ぜひやってみてください。
中身のナレッジは公開していませんが、たとえ筆者のものをコピーしても役に立ちません。そこに書いてあるのは筆者の判断基準であり、あなたの判断とは違うからです。
モデルそのものは、誰もが同じものを使えます。ナレッジを渡していないAIにできるのは、誰でもできる仕事です。自分の判断基準を渡してはじめて、自分の代わりが務まるAIになります。
だからこそ、自分のナレッジは自分で貯めるしかありません。AIに何度も同じ説明をしていること、AIの提案に「そうじゃない」と感じた理由。それを候補として残し、確認してから1つずつMarkdownにしていく地道な作業が、自分の判断をAIに任せるための資産になります。
まとめ
前後編を通して、AI向けナレッジの整備について紹介しました。ナレッジには、AIが読むことを前提に、知識だけでなく、判断に必要な基準も書きます。この基準が、AIの回答に大きく影響します。
MCPサーバーで配信すれば、環境が変わっても同じナレッジを参照できます。会社全体で使えば、会社の方針をAIが日々の相談への回答に反映できます。
MCPはナレッジを届ける経路にすぎません。決めるべきなのは、何を正しい前提として残すか、古くなったらどう見直すか、どの範囲の人に共有するかです。仕組みを作るだけでなく、中身を育てる運用まで用意してはじめて、ナレッジは日々の判断に役立ちます。
AIの回答に違和感があったり、事実と違う内容が混ざっていたりしたら、モデルの性能を疑う前に、必要なコンテキストを渡せているかを見直しましょう。AIを賢くする最初の一歩は、より大きなモデルに乗り換えることではなく、自分について正しく伝えることです。