Google公式MCPが出た日、僕らはまだ自社版MCPを実装していた
IT技術
こやまんこんにちは、GWはいかがお過ごしでしょうか? "こやまん" です。
今回は個人ではなく、グループとしての記事となります。
Google公式MCPが出た日、僕らはまだ自社版MCPを実装していた
実は、作っている途中でGoogleが公式のCalendar MCPツールをリリースしました。タイミングが絶妙すぎて、メンバー全員でちょっと笑いました。
ライトコードには、プロジェクトを横断してメンバーが集まり、社内の困りごとを技術で解決してみようというグループワークの取り組みがあります。今回はその一環として、「Google CalendarをClaudeから操作するMCPサーバー」を作っていました。社員同士のスケジュール調整をLLMに任せたい、という素朴な動機から始まったテーマです。
Cloud Runへのデプロイ、サービスアカウントのドメイン全体の委任(DWD)、Claude Desktopからの動作確認まで一通り終わり、あとは社内に展開するだけ、という段階で公式版がリリースされました。
タイミングは残念でしたが、それでも最後まで作り切って良かったと思っています。
理由は2つあります。作ってみて初めて見えたものがあったこと、そして「もうMCPサーバーは自分で書かなくていい」という空気の中にも、確実に残る領域があると気づけたことです。両方とも、手を動かしたから言える話だと思っています。
学習目的のグループワークとして始まったテーマでしたが、結果的に「自分たちでMCPサーバーを書く意味とは何か」を考える機会になりました。今回はその過程で見えたことを書いていきます。
MCPサーバーは下火、らしい
ここ最近、MCPサーバーを自前で作る話題は明らかに減ってきています。体感ベースですが、SNSや勉強会で「MCPサーバー作りました」系の発信は2025年前半をピークに落ち着いた印象があります。
理由はいくつか思い当たります。
ひとつは、主要SaaSの公式対応が進んだことです。Slack、GitHub、Notion、そして今回のGoogle Calendarのように、よく使われる連携先は公式または準公式のMCPツールが揃ってきました。「とりあえずSaaS APIをラップしたMCPを書く」という最初の山場は、もう公式が引き受けてくれる時代になりつつあります。
もうひとつは、LLMクライアント側の進化です。Claude DesktopもClaude Codeも、MCP以外の経路で外部連携できる道が広がっています。ネイティブ統合、ブラウザ拡張、CLI直叩き。MCPは「LLMに外部ツールを使わせる唯一の道」ではなくなりました。
そして地味に効いているのが、初期MCP設計が引きずる課題です。当初のMCPはローカル実行のstdioトランスポートが中心で、リモート配布・認証・監査といったエンタープライズ要件は後付けで進化してきました。Streamable HTTPでだいぶ改善されましたが、本番運用するならOAuth、IPフィルタ、ログ収集を自分で組む必要が今もあります。
これらが重なって、「MCPサーバー自作」のコスパは確実に下がっています。今回作ったものも、まさにGoogle公式版に置き換わる類のものでした。
——ですが、最後まで動かしたからこそ持ち帰れたものがありました。順に書いていきます。
作ったもの
社内で複数人の予定を合わせるとき、こんなやり取りが発生しがちです。
「今週ちょっとMTGしたいんですけど、空いてる日ありますか?」
「水曜の午後なら空いてますよ」
「あ、でももう一人も入れたくて……Aさんはどうですか?」
Googleカレンダーで空き時間を確認しつつ、Slackで都合を聞き、回答を待ち、またカレンダーと照らし合わせる。この作業、慣れてはいるけど地味にストレスです。
LLMがカレンダーを直接見てくれれば、「田中さんと佐藤さんの来週の共通空き時間を教えて」の一言で終わる話なのでは?というわけで作ってみました。
実装したツールは2つです。
| search_users | 名前やメアドのキーワードでGoogle Workspaceのユーザーを検索します。 |
| get_free_slots | メアドのリストと時間範囲を渡すと、共通の空き時間スロットを返します。 |
ユーザー: 田中さんと佐藤さんの来週の空き時間を教えて
Claude: (search_users("田中") を実行)
(search_users("佐藤") を実行)
田中さん tanaka@example.com、佐藤さん sato@example.com ですね。
(get_free_slots([tanaka@..., sato@...], 来週) を実行)
来週の共通空き時間:
- 月曜 14:00〜16:00
- 水曜 10:00〜12:00
- 金曜 15:00〜17:00
中身はFastMCPで書いて、Cloud RunにStreamable HTTPで立てました。認証はサービスアカウントのDomain-Wide Delegation(DWD)。クライアント認証は「VPN固定IP + APIキー」のアプリ層方式です。Free/Busy APIで予定の中身は読みません。
ここまでは「ふつうの実装」です。ふつうの実装にこそ、後から振り返ると意味のある選択が混じっていました。
公式ツールには載らない、3つの設計判断
作っている時は気づきませんでしたが、公式版のリリースノートと並べてみると、自分たちの実装には汎用ツールでは選ばれないであろう設計判断が3つ含まれていました。
判断1: Free/Busyだけ使う
Google Calendar APIには予定の詳細を取得するエンドポイントもあります。タイトル、参加者、説明文、すべて取れます。しかし今回はFree/Busy APIだけを使いました。
スケジュール調整に予定の中身は要りません。「いつ埋まっているか」だけで十分です。社員のカレンダー内容をLLMに読ませない、という意思決定がコードとして表現されています。
公式ツールはおそらく「機能を増やす方向」に進みます。ユーザーのユースケースの幅を広げるのが正解だからです。一方、社内向けに作るツールは「何を読まないか」を決められます。これは小さいですが本質的な違いだと思います。
判断2: VPN IP + APIキーのアプリ層認証
Cloud Runの標準認証はIAMベースですが、Claude DesktopからIDトークンを毎回取りに行くのは現実的ではありません。そこでCloud Run自体は`allUsers`で公開しつつ、アプリ層のミドルウェアで二重チェックする構成にしました。
- 社内VPNの固定IPからのアクセスのみ通す(CIDRマッチ)
- `X-API-Key`ヘッダーがSecret Manager由来の値と一致するもののみ通す
1class AuthMiddleware(BaseHTTPMiddleware):
2 async def dispatch(self, request, call_next):
3 forwarded_for = request.headers.get("X-Forwarded-For", "")
4 client_ip = forwarded_for.split(",")[-1].strip()
5 if not _is_allowed_ip(client_ip, self.allowed_networks):
6 return Response("Forbidden", status_code=403)
7
8 api_key = request.headers.get("X-API-Key", "")
9 if api_key != self.mcp_api_key:
10 return Response("Unauthorized", status_code=401)
11
12 return await call_next(request)これは「自社のネットワーク境界」を前提にした設計です。SaaS型の汎用MCPはこの設計を取れません。誰でも繋げる必要があるからです。社内向けだからこそ、ネットワーク境界そのものをセキュリティ層として活用できる、という発想です。
判断3: DWDで全社員を一括カバーする
社員一人ひとりがOAuthで認証する代わりに、サービスアカウントのDWDで「ドメイン内のユーザーに成り代わってAPIを叩く」設定を採用しました。
DWDは強い権限です。SA鍵が漏れれば全社員のカレンダーにアクセスできてしまいます。それでもこれを選んだのは、社内向けのツールとしてユーザー側の認証を不要にしたかったからです。鍵管理さえ厳格にやれば、ユーザー体験は劇的にシンプルになります。
公式ツールはユーザー個別のOAuthが基本になるはずです。それが汎用解として正しいからです。「全社で1つの認証境界に揃える」という判断は、自社の運用ポリシーを知っている人間にしか下せないものだと思います。
ハマったポイント、再分類
実装中に詰まった点を書きます。ただし単なる失敗談としてではなく、「これはクライアント側の進化で消える課題か、それとも残る課題か」という観点で分類してみたいと思います。
Domain-Wide Delegationの設定 → 残る課題
Google Cloud側でSAを作るだけでなく、Workspace管理者側に「このSAのClient IDで、このスコープを許可してほしい」と依頼する必要があります。社内の誰に何を頼むか、という話で、技術的というより組織的な作業です。
これはMCPがどれだけ進化しても消えません。組織の権限境界を越える作業は、人間の調整が必ず発生します。むしろこの種の手間がある領域は、自前で構築する判断と相性がよいとも言えます。
Cloud RunでのSA鍵の渡し方 → 消える課題
ローカルではJSONファイルパスで渡していましたが、Cloud Runにファイルはありません。最終的にSecret Managerに保存して環境変数経由で注入する形に落ち着きました。
1# auth.py(抜粋)
2key_json = os.environ.get("GOOGLE_SERVICE_ACCOUNT_KEY_JSON")
3if key_json:
4 info = json.loads(key_json)
5 return service_account.Credentials.from_service_account_info(
6 info, scopes=scopes,
7 ).with_subject(admin_email)
8# それ以外はファイルパスから読み込みこれはクライアントとMCPフレームワーク側が成熟すれば消える類の課題です。FastMCPを含む各種フレームワークがクラウド前提のSecret注入をテンプレ化していけば、こんな分岐は書かなくてよくなります。デプロイ時の認証情報受け渡しは、標準化が進む途中の領域だと感じています。
IAM認証を諦めた件 → 消える(消えてほしい)課題
Cloud Run標準のIAM認証ではなくアプリ層認証に逃げたのは、Claude Desktopから毎回IDトークンを取りに行く仕組みを組むのが重かったからです。
これはMCPクライアント側がOAuth/IAM連携の標準サポートを進めてくれれば消えます。実際、リモートMCPでの認証ハンドリングは標準化議論が活発になっている領域です。今のうちに自前で組んでおいた経験は、標準化された時に「何が抽象化されたか」が分かる解像度になります。
残り続ける領域 = 自前MCPの存在意義
ここまで書いてきて、「自前MCPサーバーを作るべき領域」がだいぶ絞れてきた気がします。
作らなくていい領域:
- 主要SaaSの汎用的な操作(カレンダー、メール、チャット、Issue管理など)
- 個人ユーザーの認証で完結するもの
- 公式ツールが既にある、または近い将来出そうなもの
今でも作る価値がある領域:
- 社内固有のロジック(営業時間、最小単位、独自ルール)が必要なもの
- データ最小化やプライバシー観点で「何を読まないか」を決めたいもの
- ネットワーク境界や組織の認証境界に紐付いた制御をしたいもの
- 社内SIEMへのログ送信など、監査要件を組み込みたいもの
- 社内システム(基幹DB、独自API、レガシーツール)との接続
要するに、「汎用化されるとむしろ困る部分」が自前MCPの守備範囲として残ります。公式ツールが充実するほど、この差分が逆にくっきり見える構図だと思います。
まとめ: 作るべきMCPと、待つべきMCP
タイミング悪く公式ツールに先を越された今回の経験で、自分たちの中の判断基準が変わりました。
新しくMCPサーバーを書こうとする時、まず問うべきはこの2つだと思います。
1. これは、近いうちに公式または準公式が出そうな領域か? 出そうなら、待った方がいいです。出ない/出ても自社要件に合わないことが見えているなら、作る価値があります。
2. この実装に、自社固有の判断が含まれるか? 「営業時間」「読まないデータ」「ネットワーク境界」「認証ポリシー」のような、汎用ツールでは選べない判断が含まれるなら、自前で作る合理性があります。逆にこれが含まれないなら、公式ツールを待つかラップする方が早いです。
今回のCalendar MCPは、振り返ると「1の判断は外したが、2の意味では正解だった」テーマでした。Google公式版が出ても、Free/Busyだけ使う設計、VPN境界に閉じた認証、DWDによる全社カバー、これらは置き換わりません。
そして何より、学習を目的としたグループワークだったからこそ、最後まで作り切ったことに価値がありました。途中でやめていたら、「公式が出たから無駄になった」で終わっていたと思います。動くものを作って、運用設計まで考えて、公式版のリリースを見て、それでも残る価値を見つけ出す。この一連の経験そのものが、次にMCPを書くべきかどうかを判断する解像度になりました。
MCPサーバーが下火と言われる時代に、それでも自分の手で書く意味があるとすれば、それは「公式ツールでは表現できない自社の判断を、コードという形で残すこと」なのだと思います。Google公式版が出た瞬間に置き換えられるMCPは、そもそも自前で書くべきではなかった。逆に、公式版が出ても置き換えられない部分を持っているMCPは、書く価値がある。
その線引きの感覚は、たぶん作ってみないと身につきません。グループワークで一通り走り切ったからこそ、たどり着けた感覚だったと思います。
参考
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!カジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ






