Claude Code + Gemini で コンテキストを効率化
はじめに
Claude Code(Sonnet 4.5)は標準で 200K トークンのコンテキストを持っています。大規模なコードベースの分析や、複数回の Web 検索を行うと、すぐにコンテキストが枯渇してしまいます。
また、Claude の知識カットオフは 2025 年 7 月のため、それ以降の最新フレームワーク情報や技術ドキュメントにアクセスできません。
直面していた課題
Claude Code 単体では、次のような制約がありました。
コンテキスト制限による問題として、200K トークンに近づくと自動圧縮が発生します。Claude Code チームによれば 155K トークン付近で自動圧縮を実行しているという情報もあります。
知識の鮮度については、2025 年 7 月以降の情報にアクセスできません。最新のライブラリやフレームワーク情報を取得するのが難しい状況でした。
Web 検索のコストも課題でした。Claude の WebSearch/WebFetch は便利ですが、コンテキストを大量に消費します。複数回の検索を繰り返すと、あっという間にコンテキストが肥大化してしまいます。
大規模なコードベース全体を一度に分析することもできません。大規模なリファクタリングや分析では、作業領域が不足してしまいます。
解決策
Gemini MCP サーバーを Claude Code に統合することで、Claude のコンテキストを節約しながら Gemini の強み(1M トークン、Google Search)を活用できるようになりました。
Claude Code (200K) → タスク管理、コード編集、ユーザー対話
↓ MCP 経由
Gemini API (1M) → Web 検索、大規模分析、最新情報取得
なぜ Gemini を MCP 化するのか
Gemini 専用のサブエージェントを作ることもできますが、MCP 化して共通ツールとして提供することにしました。こうすることで、すべてのサブエージェントから利用できるようになります。
Claude Code との統合では、シームレスな連携が実現します。Claude がタスクに応じて自動的に Gemini を呼び出してくれます。コンテキストは分離されており、Gemini の処理結果のみが Claude に返されます。統一されたワークフローで、単一のインターフェースで作業が完結します。
Gemini の強みは、1M トークンの大きなコンテキストです。大規模なコードベースやドキュメントを一度に処理できます。Google Search grounding により、リアルタイムの最新情報にアクセスできるのも魅力です。Gemini 2.5 Flash は低レイテンシで応答するため、高速に処理が完了します。
アーキテクチャ
処理フローは次のようになります。
- Claude がタスクに応じて Gemini を呼び出すか判断
- MCP 経由で必要な情報のみを Gemini に送信
- Gemini が 1M トークンのコンテキストで分析または検索を実行
- 結果を要約して Claude に返す(数百トークン程度)
- Claude が結果を元に作業を継続
セットアップ手順
Gemini を MCP サーバーとして Claude Code に統合する実装例を示します。OAuth2 認証を使用した MCP サーバーの参考実装です。
1. プロジェクト構造
gemini-mcp-server/
├── src/
│ ├── index.ts # MCP サーバー本体
│ ├── codeAssistClient.ts # Gemini API クライアント
│ ├── oauth.ts # OAuth2 認証
│ └── types.ts # 型定義
├── dist/ # ビルド出力
├── package.json
└── tsconfig.json
2. OAuth2 認証の実装
// src/oauth.ts
import { OAuth2Client } from 'google-auth-library';
import { homedir } from 'node:os';
import { join } from 'node:path';
import * as fs from 'node:fs/promises';
/**
* Load OAuth credentials from $HOME/.gemini/oauth_creds.json
*/
export async function loadCredentials(): Promise<SavedCredentials> {
const credsPath = join(homedir(), '.gemini', 'oauth_creds.json');
const credsText = await fs.readFile(credsPath, 'utf-8');
return JSON.parse(credsText);
}
/**
* Setup OAuth2 client with credentials
*/
export async function setupOAuth2Client(): Promise<OAuth2ClientSetup> {
const savedCreds = await loadCredentials();
// Gemini CLI のデフォルト OAuth 認証情報を使用
const oauth2Client = new OAuth2Client(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);
const credentials: Credentials = {
access_token: savedCreds.access_token,
refresh_token: savedCreds.refresh_token,
expiry_date: savedCreds.expiry_date,
token_type: savedCreds.token_type,
scope: savedCreds.scope,
};
oauth2Client.setCredentials(credentials);
// Set up token refresh handler
oauth2Client.on('tokens', async (tokens: Credentials) => {
const updatedCreds = {
...savedCreds,
access_token: tokens.access_token || savedCreds.access_token,
refresh_token: tokens.refresh_token || savedCreds.refresh_token,
expiry_date: tokens.expiry_date || savedCreds.expiry_date,
};
await saveCredentials(updatedCreds);
});
return { credentials, savedCreds };
}
3. Code Assist Client の実装
// src/codeAssistClient.ts
import { OAuth2Client } from 'google-auth-library';
import { getAccessToken, setupOAuth2Client } from './oauth.js';
const CODE_ASSIST_BASE_URL = 'https://cloudcode-pa.googleapis.com/v1internal';
export class CodeAssistClient implements ContentGenerator {
private oauth2Client: OAuth2Client | null = null;
private projectId: string | undefined;
public userTier: UserTierId | undefined;
async initialize(): Promise<void> {
const oauth2Client = new OAuth2Client();
const setup = await setupOAuth2Client();
oauth2Client.setCredentials(setup.credentials);
this.oauth2Client = oauth2Client;
// Load Code Assist configuration
const accessToken = await getAccessToken(oauth2Client);
const loadData = await this.loadCodeAssist(accessToken);
this.projectId = loadData.cloudaicompanionProject;
this.userTier = loadData.currentTier?.id as UserTierId;
}
async generateContent(
request: GenerateContentParameters,
userPromptId: string
): Promise<GenerateContentResponse> {
const accessToken = await this.getAccessToken();
const requestBody = {
model: request.model,
project: this.projectId,
user_prompt_id: userPromptId,
request: {
contents: request.contents,
tools: request.config?.tools,
generationConfig: request.config,
},
};
const response = await fetch(`${CODE_ASSIST_BASE_URL}:generateContent`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(requestBody),
});
const data = await response.json();
return data.response;
}
}
4. MCP サーバーの実装
// src/index.ts
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { createCodeAssistClient } from './codeAssistClient.js';
import { randomUUID } from 'node:crypto';
let client: ContentGenerator | null = null;
const server = new Server(
{ name: 'gemini-cli-mcp', version: '0.4.0' },
{ capabilities: { tools: {} } }
);
// ツールの実行
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'gemini_query': {
const { prompt, model = 'gemini-2.5-flash' } = args;
const response = await client.generateContent(
{ model, contents: prompt },
randomUUID()
);
return { content: [{ type: 'text', text: response.text || '' }] };
}
case 'gemini_search': {
const { query, model = 'gemini-2.5-flash' } = args;
const enhancedPrompt = `Search the web and provide the latest information about: ${query}`;
const response = await client.generateContent(
{
model,
contents: enhancedPrompt,
config: {
tools: [{ googleSearch: {} }],
},
},
randomUUID()
);
return { content: [{ type: 'text', text: response.text || '' }] };
}
}
});
// サーバー起動
async function main() {
client = await createCodeAssistClient();
const transport = new StdioServerTransport();
await server.connect(transport);
}
main();
5. ビルドとセットアップ
# 依存関係のインストール
npm install @modelcontextprotocol/sdk google-auth-library @google/genai
# TypeScript のビルド
npm run build
6. 初回認証
MCP サーバーを起動する前に、gemini コマンドで OAuth2 認証を完了しておく必要があります。
# Gemini CLI で認証(初回のみ)
gemini auth
# ブラウザが開いて Google アカウントでの認証を求められます
# 認証が完了すると ~/.gemini/oauth_creds.json に認証情報が保存されます
7. Claude Code への追加
# MCP サーバーを追加
claude mcp add gemini-cli-mcp -- node /path/to/your/gemini-mcp-server/dist/index.js
または、~/.claude/mcp.json に手動で追加できます。
{
"mcpServers": {
"gemini-cli-mcp": {
"command": "node",
"args": ["/path/to/your/gemini-mcp-server/dist/index.js"]
}
}
}
8. MCP サーバーの確認
設定が正しく追加されたことを確認します。
claude mcp list
9. Claude Code を再起動
設定を反映するため、Claude Code を再起動します。
10. 動作確認
Claude Code で以下のように質問してみます。
「SwiftUI の 2025 年の最新機能を調べて」
Claude が自動的に mcp__gemini-cli-mcp__gemini_search を呼び出し、最新情報を取得します。
利用可能なツール
実際に使えるツールは以下の通りです。
gemini_search は、Google Search grounding で最新情報を検索します。検索クエリを query パラメーターに指定し、model には gemini-2.5-flash(高速)または gemini-2.5-pro(高品質)を選択できます。
gemini_query は、一般的な質問や分析に使用します。プロンプトを prompt パラメーターに指定し、同様に model を選択できます。
gemini_analyze_file は、画像、PDF、ドキュメントを分析します。分析の指示を prompt、ファイルパスを filePath、モデルは gemini-2.5-pro(推奨)または gemini-2.5-flash を指定します。
gemini_analyze_codebase は、複数のディレクトリを横断してコードベースを分析します。分析の指示を prompt、ディレクトリパスの配列を directories に指定します。モデルは gemini-2.5-pro(推奨)または gemini-2.5-flash を選べます。
Gemini をどう使うか
最新情報の取得では、Claude の知識カットオフ(2025 年 7 月)以降の情報が必要な場合に、Google Search grounding を活用して最新のフレームワーク情報や技術ドキュメントを取得できます。
大規模なコードベース分析では、1M トークンのコンテキストを活用して、Claude のコンテキストを消費せずに大規模なコードベースを分析できます。ただし、MCP 経由では数 KB〜数百 KB 程度の処理が現実的です。
マルチモーダル処理では、画像や PDF ドキュメントの分析が必要な場合に、Gemini の multimodal 機能を活用できます。
まとめ
Gemini を MCP サーバーとして Claude Code に統合することで、Claude のコンテキストを節約しながら、Gemini の 1M トークンと Google Search grounding を活用できます。OAuth2 認証により、ブラウザベースの簡単なセットアップで、最新情報へのアクセスと大規模なコードベース分析が可能になります。