GeminiのGoogle検索グラウディングAPIでWeb検索MCPサーバーを作ってみる


## はじめに

MCPサーバーで検索といえば`Brave Search`がありますが、自分でも簡単に作れたらな～と思い、Gemini APIのグラウディング機能を利用してMCPサーバーを作りました。
実際はほぼChatGPT-o3に作ってもらいました。

↓下記リポジトリから使えます。

https://github.com/sayuyuyuyu/genimi-serach-tool

### MCP

MCPについてはこちらの記事がわかりやすいのでこちらを読んでください

https://qiita.com/sakasegawa/items/b091ad9931cea378099b

### Google検索によるグラウディング機能（Gemini API）

検索グラウディング（Grounding with Google Search）は、Gemini APIが回答を生成すると同時にバックエンドで Google検索を実行し、最新かつ検証可能な情報を抜粋して回答に結び付ける機能です。

有効にすると  

1. 内容の新鮮さ・正確さが向上
2. 回答中にインラインの出典リンク（grounding sources）が追加される  
3. 併せて検索サジェストも返り、元の検索結果ページにすぐ飛べる  

という三つのメリットが得られます。
実行にはGoogleのAPIキーがいります。料金形態は下記のとおりです。

>Gemini Developer API の有料階層では、1 日あたり 1,500 件の Google 検索によるグラウンディング クエリを無料で実行できます。それを超えるクエリについては、1,000 件あたり 35 ドルの標準料金が請求されます。

https://ai.google.dev/gemini-api/docs/grounding?hl=ja&lang=python

---

## 1. ゴール

* ローカル PC で **MCP サーバー**（`server.py`）を起動  
* クライアント（Cursor など）から `web_search` ツールを呼ぶ  
* 回答本文＋参照リンク（Google 検索グラウディング）が返ってくる

---

## 2. 環境

| ツール | バージョン |
|--------|-----------|
| Windows 11  | – |
| Python | 3.12 |
| `uv`   | 0.1.35+  |
| `google-genai` | 0.5.* |
| `mcp` Python SDK | 1.2.* |
| VS Code (任意) | 1.88+ |
| Cursor (任意)   | 0.35+ |

---

## 3. 事前準備

### 3.1 Google API キー取得（検索グラウディング特権付き）

1. [Google AI Studio › API keys](https://ai.google.dev/gemini-api/docs/api-key?hl=ja) にアクセス  
2. **Create API key** → **Programmability** を選択  
3. 「Enable Google Search grounding?」を **ON** にする  
4. 生成されたキーをメモ  

### 3.2 プロジェクト作成

```powershell
# uv が未インストールなら
curl -LsSf https://astral.sh/uv/install.sh | sh

uv init gemini_search_mcp
cd gemini_search_mcp
uv venv && .\.venv\Scripts\Activate.ps1   # Linux/Mac: source .venv/bin/activate
uv pip install -U google-genai mcp[cli] python-dotenv
````

`.env`

```env
GEMINI_API_KEY=AlXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

---

## 4. server.py

```python
from __future__ import annotations
import asyncio, os, textwrap
from typing import List

from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP
from google import genai
from google.genai import types

# ── 初期化 ───────────────────────────────
load_dotenv()
client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
MODEL_ID = "gemini-2.0-flash"  # Grounding 対応モデル

mcp = FastMCP("gemini-grounding-search")

# ── ツール定義 ──────────────────────────
@mcp.tool()
async def web_search(query: str, max_sources: int = 5) -> str:
    """
    Google 検索グラウディングで回答＋引用リンクを返す
    """
    tool = types.Tool(google_search=types.GoogleSearch())
    resp = await asyncio.to_thread(
        client.models.generate_content,
        model=MODEL_ID,
        contents=query,
        config=types.GenerateContentConfig(tools=[tool])
    )

    answer = resp.text
    chunks = resp.candidates[0].grounding_metadata.grounding_chunks
    links: List[str] = []
    for c in chunks[:max_sources]:
        web = getattr(c, "web", None)
        if web:
            links.append(f"- {web.title or '(no-title)'} : {web.uri}")

    return textwrap.dedent(f"""{answer}

    ▼ 参考リンク
    {os.linesep.join(links) if links else "(なし)"}
    """)

# ── 起動 ────────────────────────────────
if __name__ == "__main__":
    mcp.run("stdio")   # HTTP なら mcp.run("http", port=8801)
```

---

## 5. 動かす

CursorのMCPサーバー設定に、今回作成したMCPサーバーを追加します。
`.env`ファイルでAPIキーを読み込ませているのであれば、下記の`env`列は不要です。
仮想環境で立てているので、`command`には`.venv`内の`python.exe`を、`arg`には`server.py`の絶対パスを入れます。

Cursorの全体設定なら、`%USERPROFILE%\.cursor\mcp.json`に、
プロジェクト別の設定なら、`.\.cursor\mcp.json`に下記JSONを追加します。

```jsonc
{
  "mcpServers": {
    "gemini-grounding-search": {
      "command": "C:\\Work\\gemini-search-tool\\.venv\\Scripts\\python.exe",
      "args": ["C:\\Work\\gemini-search-tool\\server.py"],
      "env": { "GEMINI_API_KEY": "sk-XXXXXXXXXXXXXXXXXXXX" }
    }
  }
}
```

Cursorを再起動→MCP設定で**Enable**すればOKです。
緑ランプがつけば利用できるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535910/f40c4449-e32f-4c4c-99e5-09eaa732c184.png)

### 5.1 実行例その1

Agentに「今日の株価」を調べてもらいましょう。

`入力`
> @web_search 今日の株価

`出力`
> I'll search for information about today's stock prices.
> 2025年5月12日の株式市場状況:
> 日経平均: 37,644.26円(+0.38%)、3月27日以来の高値
> TOPIX: 2,742.08(+0.31%)
> 東証プライム: 値上がり1116銘柄、値下がり476銘柄
> 売買代金: 約4兆8542億円


結果は下記の通り、ちゃんと調べてくれました。

一応人力で確認しましたが、ちゃんと正しいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535910/399a89a6-92ee-4876-83cf-17eab8bd1aea.png)


実際にグラウディングされた情報は下記の通りでした。
参考リンクも5種提示していますね。


Parameters:
```json
{
  "query": "sayuyuyuyu Qiita アカウント 記事 技術カテゴリ"
}
```
Result
```
 2025年5月12日の今日の株式市場の状況は以下の通りです。

*   **日経平均株価**: 37,644.26円 (終値)で、前週末比140円93銭（0.38％）高。3月27日以来の高値となりました。
*   **東証株価指数（TOPIX)**: 2,742.08で、前週末比8.59ポイント（0.31％）高。
*   東証プライムの売買代金は概算で4兆8542億円、売買高は21億5238万株でした。
*   東証プライムの値上がり銘柄数は1116、値下がりは476、横ばいは42でした。

今日の株価上昇率ランキングも利用可能です。


▼ 参考リンク
- nomura.co.jp : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXFweXhP-Eta1na7UMl3d6WwJ_-Crlsjh9AggWuKtnrtMXxwFBV-P4iOvImXXYle1vDCL4aPtqX7OWuY1VSErr1YAi1qz6mqPGbnHwC7Tujc2IZkKDt_41ASo_AWrOmRSHNpdMYVXwfSsiOze1nxoyHmcb1uSBrV00xK2rmz_kTl8mTYQc7rPXgsr4qE
- sbisec.co.jp : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXGJjJvnxq61hN6Is75nIMovTJTdnGsXqsIHBBMrNTVEbnQZGYf1CM64QvVsiFBz55ZbjNTpUWLifOHjVBqarvuzlXyA7faxpjFd6y0deVP2yr9Cj5CLmPZ1HJF0kbUjVnKaa9nxkSjkJXhGwd_au69Xovf01ixBruhKu0w8ZJGXPLWul06mCliObmRJemU_IcBZJz6YeIrXlInDhHwDKb5wkdHvEmZCX0IXwEbdn5cIhpmBADOqdqZ6jTD6WZZvPqjDIM3bipgIfm0skMChdZKTsSilLUIL22a8UcU0CM6ZyPHmijPYRbO4LvLr7hK5Ro9teL4yQpMoIwbfYMxbU0lEGc4xvXREEu-OBeUTGY7isutsn2Ls2cNmcDXVrxXOdHsefqUshK9PeUEik8_udwdmVyxUElli
- kabutan.jp : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXGWWtG3511PruunaFxB5CYsRdROGneF4oF4ciThKt_7CZyiAgDLBSykGe8N_mHvaN-nG0ik__efx5B7Tcyi1Vnigdg08omGoVIGjTcSQ7mqFzOZEkCF0Tk_Y2PPnNYbaBYmpgMAX40edASdPp0=
- sbisec.co.jp : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXH2pIkGaCeV2Zet_sh1HAERvYiFtKDPSo4IudmNGLrauCx4CdmKDcNk8SFWJH1QyZhsqCw4xN_I7Hg2lPlSudiksUA5dzp54LaNBJyd6ias1vUTwOYXJmICTidMNbq77nalh0TzvVj8VkdCwVQu08DrRsAabdg-qhxYZGm3jU-4xfkR2Ia8JR1V6agYr746PEAb_7r3YZaAfgnw3O4e2y4u9Vep7WIguBtj5vtAa6RB8p7jzaaJNto_YFn3F20xgC8yX1qpGUJ_CWLx8G-Yu_DisCOLkBYcDBKj9pH-_Gm3R1yZiv1Wbb7P-DyR0FGyOW2uxx4ykSs7Ue3Qvns8gbXatPEl72UCR-JsMficT7ZS-txc2IDJwL7jGusxNzuV0ddMq0cKaanWv5odym-OzFmtRUE=
- kabutan.jp : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXERk1qimX4rvFZbyCWM3uNzRwLdC1JT3nVRCCvkmp1G-JIgv5EtruSg-pIhW00NTyVYF0L5Eo2UxMq6UoMhDSRx8fOeha21VbfSveXjFMM2CUCvEll9dt68E1qvtYRDZ6LtV4i0SIQ=
```

### 5.2 実行例その2

もう一例、僕のQiitaアカウントのことについても聞いてみます。

`入力`

> @web_search sayuyuyuyuというQiitaアカウントが投稿している記事の技術カテゴリを日本語で教えて

`出力`

> 検索を実行して、sayuyuyuyuさんのQiita記事の技術カテゴリを調べます。
> sayuyuyuyuさんのQiitaアカウントの技術カテゴリは、主に以下のものです：
>
> - Python
> - データ分析
> - Spotify API
> 
> この方はグミ好きの新人エンジニアで、Spotify APIを使った曲のデータ分析に関する記事を投稿しています。

あってますね。内容的にプロフィールページを見たのかと思いますが、検索結果を見てみましょう。

Parameters:
```json
{
  "query": "sayuyuyuyu Qiita アカウント 記事 技術カテゴリ"
}
```
Result:
```
Qiitaアカウント「sayuyuyu」さんの記事と技術カテゴリについて説明します。

「sayuyuyu」さんは、グミ好きの新人エンジニアです。

Qiitaで公開されている記事には、以下のようなものがあります。

*   **Spotify APIを使って曲のデータ分析をしてみる**
    *   この投稿では、Spotify APIを利用してプレイリストからデータを取得し、パラメータの相関分析が行われています。ただし、2025年4月の追記で、Spotify APIの仕様変更により、紹介されているソースコードが動作しなくなっている可能性があることに注意が必要です。

このことから、技術カテゴリとしては、Python、データ分析、Spotify APIなどが考えられます。


▼ 参考リンク
- qiita.com : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXFBjzTjbzEabb9tqZgnBvawuiPQJ5EBt9a5Q7lk6TFCBZAV7w4FjrldiaBlwUZOqYctIaG2E1AVYUVADQ7pYMNphttK7w_psQBWWx7hJtHaKFapjnw=
- qiita.com : https://vertexaisearch.cloud.google.com/grounding-api-redirect/AbF9wXGr3iltp7Cmpn9ZbGAIQb1EsbLxuGyQgtEote548EwujasGCLIMLmevZ5OKI3I3N3JkSIxbGinORuustznKMVQFQ03Upj3bYgq6OrLUggArWMaV2OR7dDVlq4x35hgAOdDAFHL38hXBEaw6B9ZvV1M=
```

参考リンクはTOPページとSpotifyの記事なので、参照元もちゃんとしていますね。

## おわりに

今回はほぼo3先輩に書いてもらいましたが、十数回の修正で完成したので、簡単なMCPサーバーはo3先輩に書いてもらうのが早いな～と実感しました。
MCPサーバーの利点は「使いまわしのしやすさ」にあると思うので、AITuberにつなげたりしたら面白そうですね。
GeminiのAPIも便利なものがドシドシ出ているので、要チェックですね。

---

### 参考リンク

* [Gemini API Docs – Search grounding](https://ai.google.dev/gemini-api/docs/grounding?hl=ja)
* [MCP (Model Context Protocol)](https://modelcontextprotocol.org/)
* [google-genai GitHub](https://github.com/google-gemini/google-genai-python)