はじめに
こんにちは!株式会社SOARIGでエンジニアをしているあおいです。
前回、社内向けにMCP Gatewayを構築した話を書きました。今回はその続きで、Gatewayに最初に繋いだMCPサーバー——社内wiki検索——の中身の話をしていきます。
「MCPサーバーを1本作る」と言ったときに実際に何をやっているのか。そして、作る過程でいちばん悩んだ「権限をどう通すか」について書きます。
先に結論だけ書いておくと、繋ぐこと自体はほとんど手間がかかりませんでした。難しかったのは権限のほうです。
対象読者
- 社内のドキュメントをAIから検索できるようにしたい方
- MCPサーバーを作るときの認証・権限設計で悩んでいる方
- 社内でAIを使わせたいが、「見えてはいけないものが見えてしまう」のが不安な方
- Google Workspaceを業務基盤にしている方
- 「社内にwikiはあるが、誰も見ていない」状態に心当たりのある方
記事の構成
- なぜ1本目が社内wikiだったのか
- どう組んだか
- 権限をどう通したか
- 2週間使ってみてどうだったか
- この構成が成立する条件
1. なぜ1本目が社内wikiだったのか
Gatewayという玄関口を建てても、その先に繋ぐものがなければただの箱です。では、まず何を繋ぐか。
候補はいくつかありました。GitHub、Slack、各種業務システム。その中で社内wikiを最初に選んだのには、3つの理由があります。
① 非エンジニアが最初に得をする
そもそもGatewayを作った動機の半分は「AI格差の解消」でした。エンジニアだけが得をするものを1本目に繋いだら本末転倒です。全社員に関係があって、誰でも今日から使えるもの。その条件で考えると、社内wikiは自然な選択でした。
② 「探しても見つからない」の総本山だった
うちの社内wikiは、Google Sitesでずいぶん前から運用されていました。制度のこと、申請の手順、過去の経緯。書いてはあるんです。 書いてはあるんですが、どこに書いてあるかが分からない。結局「総務に聞く」に戻ってしまう。
これは、wikiを作った人が悪いわけでも、探す人が悪いわけでもないと思っています。情報が増えれば増えるほど、階層のどこに置くかという問題は必ず発生します。検索窓はあるけれど、書いてある言葉と探すときの言葉が一致しないと引っかからない。
「情報が無い」ではなく「情報はあるのに辿り着けない」。この状態は、AIがいちばん得意とするところです。
③ 権限設計がいちばん素直だった
全社に公開しているwikiなので、まず動かすには最も見通しが良かった。逆に言うと、人事や経理まわりのデータを最初に選ばなかったのは、ここに理由があります。権限をどう通すかを固めないまま機密データに手を出すのは順番が違う、と判断しました(この話は3章で詳しく書きます)。
2. どう組んだか
やったことは、大きく3ステップです。
ステップ1:Google SitesをVertex AI Searchに取り込む
ここは、拍子抜けするほど簡単でした。
Vertex AI Searchには、Google Sitesを検索対象として取り込む機能が標準で用意されています。つまり、自前でクローラを書いたり、ドキュメントを適切なサイズに分割したり、エンベディングモデルを選定してベクトルDBに投入したり——といった作業を、一切していません。
「社内ドキュメントをAIで検索できるようにする」というと、たいていこの部分が山場として語られます。実際、チャンクの切り方やエンベディングの選び方についての記事は世の中にたくさんあります。
でも、すでにGoogle Workspaceの中に情報資産がある会社であれば、その工程はまるごとGoogle側が引き受けてくれます。ここに工数をかける必要はありませんでした。
ステップ2:MCPサーバーでラップする
次に、Vertex AI Searchの検索機能を、AIから呼べる形(MCPサーバー)に包みます。やっていることは「検索クエリを受け取って、Vertex AI Searchを叩いて、結果を返す」だけの薄いサーバーです。
ここで一つ、設計の判断をしています。返り値に何を含めるかです。
ドキュメントの本文を丸ごと返すこともできますが、返しているのはヒットしたページへのリンクと、該当箇所の抜粋だけにしました。Vertex AI Searchが返してくる形にそのまま乗った、というのが正直なところではあるのですが、結果的にこの判断が後々効いてきます。
理由は2つあります。1つは、リンクを返すことで、利用者が必ず一次情報(wikiそのもの)に戻ってこられること。AIの回答だけで完結してしまうと、その回答が古い情報に基づいていた場合に検証できません。もう1つは、ログに本文が残らないこと。これは後述します。
ステップ3:ContextForgeに登録する
最後に、作ったMCPサーバーをGateway(ContextForge)に登録します。
登録するのは1回だけです。それだけで、非エンジニアがGoogle Chatから使う場合も、エンジニアがAntigravity CLIやClaude Codeから叩く場合も、同じように社内wikiを検索できるようになります。入り口が違っても、監査とセキュリティ管理はGateway側で一元的に完結します。
前回の記事で「Gatewayに一つ登録するだけで全社員のAIから使えるようになる」と書きましたが、それを実際にやったのがこの部分です。
……と、ここまでは大きく詰まるところはありませんでした。難しかったのは、次の話です。
3. 権限をどう通したか
そもそも、権限には二段階ある
まず、前提の整理からさせてください。
「社内wikiをAIから検索できるようにする」と言ったとき、決めなければいけないことは、実は2つあります。
- そもそも、その人は「社内wiki検索」という機能を使ってよいのか
- 使ってよいとして、その人にはwikiの中のどこまでが見えるのか
Gatewayを「会社の玄関口」にたとえるなら、1つ目は入館証の話です。そもそも建物に入っていい人かどうか。2つ目は部屋の鍵の話です。入館できたとして、その人はどの部屋を開けられるのか。入館証を持っていても、役員室には入れない。
当たり前の話に聞こえると思います。でも、AI経由になった途端、この2つ目がすっぽり抜け落ちることがあります。
素直に作ると、AIにマスターキーを渡すことになる
なぜ抜け落ちるのか。
AIから社内ドキュメントを検索する仕組みを素直に作ると、MCPサーバーはサービスアカウント(人ではなくシステムのために発行するアカウント)を使ってVertex AI Searchを検索することになります。これでも動きます。動きますが、この構成は「サーバーが全社ドキュメントの読み取り権限を常に持っている」ことを意味します。
先ほどのたとえで言えば、AIに全部屋のマスターキーを渡している状態です。入館証さえ確認できれば、あとは誰が何を聞いても同じ答えが返ってくる。
そうすると、こういうことが起きます。
- 誰が使っても同じ検索結果が返る。本来その人には見えないはずの文書も返ってしまう
- 「AI経由なら見えてしまう」という抜け道ができる
- Gatewayが攻撃を受けたときの被害が最大化する
- AI用の権限台帳をもう一つ作り、既存の権限と二重に運用する羽目になる
最後の項目が、地味にいちばんきついと思っています。人が入社・異動・退職するたびに、棚卸しを2箇所でやることになる。運用が回らなくなるのはたいていこういう部分です。
誰が何を確認するかを分けた
そこで今回は、先ほどの2つを別々の仕組みで確認することにしました。
- 入館証の確認 → ContextForge(Gateway)が担当する
- 部屋の鍵の確認 → Googleにそのまま任せる
これを実現するために、扱うトークン(本人確認のための電子的な証明書のようなもの)を2種類に分けています。
① ContextForge用のトークン=入館証
そのユーザーがGatewayを使ってよいのか、登録されているMCPサーバーのうちどれに触れてよいのか。これはContextForge側で管理しています。「そもそも社内wiki検索という機能を呼べる人か」を判定する層です。
② Vertex AI Search検索用のOAuthトークン=部屋の鍵
入り口であるGoogle Chatで、利用者本人にGoogleアカウントでの認証をしてもらいます。そこで取得したトークンをヘッダーに載せ、Gatewayを経由してMCPサーバーまで受け渡します。MCPサーバーは、サービスアカウントではなくこのトークンを使ってVertex AI Searchを検索します。
このトークンに与えている権限の範囲は、Vertex AI Searchで検索することだけに絞っています。それ以外のことは何もできません。仮にこのトークンが漏れたとしても、できるのは検索だけです。
社内wiki検索:入館証はGatewayが確認し、部屋の鍵はGoogleに任せる
何が嬉しいのか
ユーザー本人のトークンで検索するということは、どのドキュメントが見えるかの判定を、Google側の共有設定がそのまま行うということです。部屋の鍵をこちらで作り直すのではなく、もともとGoogleが持っている鍵をそのまま使う。
Aさんが検索すればAさんに見える範囲から、Bさんが検索すればBさんに見える範囲から返ってきます。同じ質問をしても、人によって結果が変わる。それが正しい状態です。
言い換えると、私たちが作ったシステムは「誰に何を見せてよいか」の情報を一切持っていません。持たないようにした、というより、持つ必要がなくなりました。
ここから、いくつか良いことが生まれます。
- 権限台帳が増えない。 管理するのはGoogle Workspace側の権限だけ。AI用に別の権限管理を作らなくていい
- 共有設定を変えれば、AI経由の見え方も自動で変わる。 wikiの共有範囲を絞れば、AIから引ける範囲も同時に絞られます。同期作業は不要です
- 退職者のアカウントを止めれば、AI経由のアクセスも同時に止まる。 ここが二重管理だと、片方の止め忘れが必ず起きます
- Gateway自体が権限を持たない。 Gatewayはユーザーのトークンを運んでいるだけなので、仮にGatewayが攻撃されても、そこから全社ドキュメントが抜けるという構造になりません
「AIを導入すると、管理するものが増える」——これは導入をためらう理由としてかなり大きいと思っていて、そこを増やさずに済んだのは想像以上に効きました。
ログに何を残しているか
トークンを扱う以上、ログの設計もセットで考える必要があります。
パススルーしているトークンは、ログには一切残していません。 監査ログに記録しているのは「誰が・いつ・どのツールを呼んだか」という操作の記録と、結果として返ってきたドキュメントのIDまでです。検索キーワードそのものも保持していません。
監査のためにログは取りたい。でも、社員が何を検索したかという中身までは残したくない。この2つは両立できます。操作の記録(誰が・いつ・何を使ったか)と、その中身(何と入力したか)は分けて考えられるからです。
前章で「返り値をリンクと抜粋だけにした」と書きましたが、本文を返さない設計にしていると、この線引きが自然に守られます。返していないものは、そもそもログに残りようがありません。
4. 2週間使ってみてどうだったか
社内にリリースしてから2週間で、AI経由の社内wiki検索は70件でした。うちの規模を考えると、想定よりだいぶ引かれているな、というのが正直な感想です。
変化として実感しているのは、3つあります。
① 「探しても見つからないから総務に聞く」が減った
これが狙いそのものだったので、当然といえば当然なのですが。今までは、探す→見つからない→諦めて人に聞く、という流れでした。それが、AIに聞けば一発でリンクが返ってくるようになりました。
② 総務側の負荷が下がった
①の裏返しです。総務に回っていた「あれってどこに書いてありましたっけ」系の問い合わせが、その分減りました。聞かれる側の時間は、可視化されにくいコストです。
③ wikiそのものが育つ循環が生まれた
個人的にいちばん面白かったのがこれです。
今までは、wikiが古びていくのを止められませんでした。誰も更新しないし、更新されないから誰も見なくなる。よくある話だと思います。
それがAI経由になったことで、「どこに情報が無かったか」が見えるようになりました。検索されたのに良い結果を返せなかった、というのは、そのままwikiの穴です。そこで、届いた質問のうちwikiに答えが無かったものは、wikiに追記する。この運用に変わりました。
「RAGの精度は元のドキュメントの質に依存する」というのはよく言われる話です。それはその通りなのですが、実際に運用してみると、逆方向にも力が働くというのは発見でした。AIから引かれるようになると、ドキュメントを整備する動機が生まれます。
5. この型は、どこまで使い回せるのか
ここまで読んで、「うちはGoogle Workspaceじゃないから関係ないな」と思われた方がいるかもしれません。最後に、その話を書いておきます。
効いていたのは「Googleだったこと」ではない
今回うまくいった一番の理由は、前章に書いたとおり、部屋の鍵の管理を自分たちでしなくて済んだことです。権限台帳が増えず、共有設定を変えればAI経由の見え方も変わり、アカウントを止めればアクセスも止まる。
自分たちで権限管理を作らなくて済むなら、それがいちばん安全です。 作ったものは必ず運用しなければならず、運用は必ずどこかで抜けるからです。
ここで大事なのは、これがGoogle固有の性質ではない、ということです。効いていたのは「相手がGoogleだったこと」ではなく、繋ぎ先が利用者ごとの権限を判定してくれる仕組みを持っていたことでした。
分かれ目は、繋ぎ先がユーザー単位の認可を出せるかどうか
そう考えると、境界線はGoogleの内か外かではなく、こうなります。
① 利用者ごとの認可を提供しているサービス
OAuthに対応していて、「このトークンはこの人のもの」として権限を判定してくれるサービス。SlackやGitHubをはじめ、多くのSaaSがこれに当たります。この場合、今回と同じ型がそのまま乗るはずです。入り口で利用者本人に認証してもらい、そのトークンをGateway経由で渡し、見える範囲の判定は相手のサービスに任せる。私たちは鍵を持たない。
公式やOSSのMCPサーバーが提供されているサービスなら、なおさら話が早くなります。サーバーを一から作る必要すらなく、Gatewayに登録して、認証だけ今回の型で通せばいい。
② 利用者ごとの認可を持たないシステム
システム単位の認証しかない、あるいは社内で独自に作られたシステム。この場合は、鍵を預けられる相手がいません。入館証の側——つまりGateway(ContextForge)で「誰がどのMCPサーバーを使えるか」——を設計して対応することになります。
これはシステムの限界というより、権限設計の手間がどちら側で発生するかの違いです。①なら相手が持ってくれる。②なら自分たちで組む。繋ぎ先を選ぶときは、機能だけでなくここを見ています。
1本目で型はできた。次はそれを確かめる
正直に書くと、②に該当するケースはまだ通していません。①についても、今回検証できたのはGoogle(Vertex AI Search)の1件だけです。
ただ、社内wiki検索という1本目を通したことで、「入館証はGatewayが確認し、部屋の鍵は繋ぎ先に預ける」という型そのものは形になりました。ここから先は、この型が本当に他のサービスでも通るのかを、1本ずつ確かめていく作業になります。
次に繋ぐものでそれを試して、また書きます。