mcp-gtags-server について
mcp-gtags-serverは、GNU Globalのインデックスを使ったC/C++コードナビゲーションをMCP経由でコーディングエージェントに提供します。大規模なコードベースやビルドが難しいコードベースを対象に、広範なテキスト検索の代わりにシンボルや参照、呼び出し元、呼び出し経路を検索できます。
主な機能
- 01インデックスによる定義と参照の検索
- 02呼び出し元、呼び出し先、呼び出し経路の検索
- 03関数本体の取得
- 04カーネルマクロとエクスポートの解決
- 05インデックスの自動作成と更新
- 06複数リポジトリのプロジェクトルート選択
活用シーン
- 01大規模なC/C++ツリーでシンボルを検索
- 02関数を変更する前に呼び出し元を追跡
- 03大きなファイルを読まずに関数本体を確認
- 04参照検索をプロジェクト内のパスに限定
MCP 対応
8種類のコードナビゲーションツールと、影響分析およびコード説明用のプロンプトをMCPクライアントに公開します。stdioまたは共有ローカルHTTPサーバーとして実行できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx mcp-gtags-serverGTAGS_MCP_ROOTOptional pinned project root. Usually unnecessary: the server uses the client's workspace roots or auto-detects the repo from its working directory.GTAGS_MCP_AUTO_SETUPSet to 0 to disable the automatic user-space install of the gtags/ctags toolchain on first use.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
8掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| limit | integer | いいえ | |
| format | enum | いいえ | json | text |
| offset | integer | いいえ | |
| symbol | string | はい | |
| project_root | any | いいえ | |
| active_config | any | いいえ | |
| case_insensitive | boolean | いいえ |
詳細
mcp-gtags-server
AI エージェントに grep させるのはやめましょう。インデックスを使わせましょう。
mcp-name: io.github.harshithsunku/mcp-gtags-server
# If you don't have uv yet (one-time, no sudo):
curl -LsSf https://astral.sh/uv/install.sh | sh
{ "mcpServers": { "gtags": { "command": "uvx", "args": ["mcp-gtags-server"] } } }
ユーザーレベルの設定を一度追加するだけで、sudo も事前インストールも不要です。初回使用時にツールチェーン全体がユーザースペースにインストールされ、開いたリポジトリはすべて自動的に対応します。
📖 ドキュメント全文 — 各クライアントへのインストール方法、ツールリファレンス、出力形式、カーネル機能、設定、トラブルシューティングを掲載しています。
Claude Code、Cursor、Codexなど、あらゆるAIコーディングエージェントが「この関数はどこで定義されているのか?」という問いに、同じ方法で答えています。ツリー全体を grep するのです。 100万行規模の C/C++ コードベースでは、質問のたびに全体をスキャンすることになり、出力は洪水のようになります。すべてのコメント、文字列リテラル、無関係な一致が、そのままモデルのコンテキストウィンドウに流れ込みます。
mcp-gtags-server は、GNU Global (gtags) を活用したインデックス検索に置き換えます。これは、カーネル開発者やシステム開発者が何十年も信頼してきた同じタグエンジンであり、Model Context Protocol を介してエージェントに公開されます。LSP ベースのツールでは対応できないコードベース向けに構築されています。カーネル規模の C/C++、現在ビルドできないツリー、sudo 権限を使えないマシンに対応します。
- クエリごとに約100倍高速 — コードベースの規模を問わず、数秒ではなく数ミリ秒で検索します
- ノイズを大幅に削減 — 7,873行もの一致結果ではなく、定義を取得します
- カーネルの構造を理解 —
.configによるフィルタリング付きの#ifdefガードスタック、他のタグ付けツールでは解決できないマクロ生成シンボル(sys_read→ 対応するSYSCALL_DEFINE3の箇所)、さらに ctags を使ってEXPORT_SYMBOLの箇所から復元するパーサーが見落とした定義にも対応します - インデックス管理は不要 — 最初のクエリでインデックスを構築し、以降の各クエリで自動更新します
- CI で正確性を測定 — バージョンを固定したカーネルを対象に、8つのツールすべてを網羅する64ケースのゴールデン評価を実施。再現率100%、precision@1 100%です(docs/capability.md)
- MCP が動作するあらゆる環境で利用可能 — Claude Code、Claude Desktop、Cursor、その他あらゆる MCP クライアントに対応します
数値(おもちゃではなく、実際の Linux カーネル)
Linux カーネルの完全なチェックアウトで測定 — C/C++ ファイル 65,163 個、3,710 万行 — ページキャッシュがウォームな状態:
| エージェントが尋ねる質問 | grep -rn | gtags(このサーバー) | 消費されるコンテキスト |
|---|---|---|---|
tcp_v4_rcv はどこで定義されていますか? | 1.40 秒 | 0.01 秒 | 8 行 → 1 行 |
kmalloc はどこで定義されていますか? | 1.62 秒 | 0.01 秒 | 7,873 行 → 5 行 |
kmalloc を参照しているのはどこですか? | 1.62 秒 | 0.10 秒 | ノイズの多い 7,873 行 → 実際の箇所 2,744 件(またはファイル別のランキング付き要約) |
tcp_v4_rcv の実装を表示してください | 3,500 行のファイルを読む | get_symbol_body | 関数の正確な 271 行 |
ext4_mark_inode_dirty を呼び出しているのはどこですか? | 生の一致行 245 行 | find_callers | 重複排除された呼び出し元関数 62 件と件数 |
sys_read は実際にはどこで定義されていますか? | 回答なし — 名前がマクロ生成される | 0.03 秒 | fs/read_write.c SYSCALL_DEFINE3(read, ...)、resolved_via フラグ付き |
mutex_lock はどこで定義されていますか? | ノイズの多い一致行 24,774 行 | 0.2 秒 | kernel/locking/mutex.c:314 — gtags のパーサーがここで処理に失敗するため、EXPORT_SYMBOL と ctags を使って特定 |
ksys_read は rw_verify_area に到達しますか? | grep と読み込みを N 回繰り返す | 0.6 秒 | 最短の呼び出しチェーンと、各呼び出し箇所のファイル名・行番号 |
fs/ext4 内のすべての mutex_lock 呼び出しは? | ツリー全体の一致行 22,905 行 | 0.01 秒 | find_references(path_prefix="fs/ext4"):実際の箇所 18 件 |
一度だけ行うインデックス構築:カーネル全体で 66 秒。編集後の増分更新:1 秒未満です。scripts/benchmark.sh を使って、ご自身でも再現できます:
./scripts/benchmark.sh /path/to/linux tcp_v4_rcv kmalloc ext4_readdir
速度も魅力ですが、本当の利点は精度です。ノイズの多い 7,873 行ではなく、正確な 5 行を受け取るエージェントは、実際の推論にコンテキストウィンドウを使えます。
回答は推測ではなく、実測値です。CI では、プッシュのたびに、固定されたカーネル v6.16 を対象に64 ケースのゴールデン評価を実行しています。現在、定義、マクロ解決、エクスポートの復元、参照、呼び出し元、呼び出し先、定義本体、#ifdef ガード、到達可能性にわたり、全 8 ツールで**再現率 100%、precision@1 100%**を達成しています。詳しい手法、数値、正直な制限事項はdocs/capability.mdに記載しています。
クイックスタート(60 秒)
オプション A — 設定項目を 1 つ追加(推奨)
サーバーをユーザーレベルで一度だけ追加すれば完了です。インストーラーも、事前にインストールした gtags も、リポジトリごとの設定も必要ありません。前提条件はuvだけです(または、インストールも自動で行うオプション B をご利用ください)。
# Claude Code (once per device, all repos):
claude mcp add --scope user gtags -- uvx mcp-gtags-server
// Cursor (~/.cursor/mcp.json), or any MCP client's global settings:
{
"mcpServers": {
"gtags": { "command": "uvx", "args": ["mcp-gtags-server"] }
}
}
または、このページ上部にあるCursor ワンクリックインストールバッジをクリックしてください。
最初のツール呼び出し時に、サーバーが残りのすべてを自動でセットアップします。GNU Global(ビルド済みのユーザー空間バイナリ — コンパイラーも sudo も不要)、universal-ctags、Pygments をすべて ~/.gtags-mcp にインストールします。この初回インストール中(ほとんどのプラットフォームで数秒間)は、ツール呼び出しが失敗する代わりに、"toolchain is being installed — retry shortly" ステータスを返します。--no-auto-setup または GTAGS_MCP_AUTO_SETUP=0 で無効にできます。
ビルド済み Linux バイナリは、glibc ≥ 2.28 のあらゆるディストリビューション(RHEL/Rocky 8 以降、Ubuntu 18.10 以降、Debian 10 以降)で動作します。古いホストの場合、またはダウンロードしたバイナリのインストール後実行チェックに失敗した場合は、自動セットアップが代わりに GNU Global をソースからコンパイルします。必要なのは make と C コンパイラーだけです。
オプション B — プラグインをインストールする(サーバー+スキル+スラッシュコマンド)
このプラグインには、このサーバー、エージェントにどのツールがどの質問に答えるかを伝える**「C/C++ コードナビゲーション」スキル**、および 2 つのスラッシュコマンド
(/gtags:impact、/gtags:explain)が含まれています。インストールすると MCP サーバーが登録されるため、編集する設定ファイルはありません。
| クライアント | インストール |
|---|---|
| Claude Code | /plugin marketplace add harshithsunku/mcp-gtags-server を実行し、続けて /plugin install mcp-gtags-server@mcp-gtags-server を実行します |
| Codex | codex plugin marketplace add harshithsunku/mcp-gtags-server を実行し、続けて ChatGPT デスクトップアプリのプラグインディレクトリからインストールします |
| Cursor | Agent Plugins 1.0.0 を読み込みますが、インストールできるのは Cursor Marketplace またはチームマーケットプレイスからのみです。このプラグインがそこに掲載されるまでは、ワンクリックバッジまたはオプション A を使用してください |
インストール方法はどちらか一方にしてください。 プラグインと手動の設定項目を両方使うと、サーバーが 2 つ起動し、エージェントには各ツールが 2 つずつ表示されます。プラグインに切り替える場合は、まず手動の設定項目を削除してください(
claude mcp remove gtags)。
オプション C — 1 行インストーラー(共有バックグラウンドサーバー)
コマンド 1 つ。sudo 不要。どこでも動作します — 制限のある企業用マシン、コンテナー、ビルドサーバーでも使えます。
curl -fsSL https://raw.githubusercontent.com/harshithsunku/mcp-gtags-server/main/scripts/install.sh | bash
サーバー(uv 経由)、GNU Global、universal-ctags、Pygments を含め、すべてホームディレクトリ(~/.gtags-mcp)にインストールされます。完了すると、マシン上のあらゆるクライアントや IDE ウィンドウから接続できる共有バックグラウンド HTTP サーバー(http://127.0.0.1:8383/mcp)が起動し、クライアント向けの正確な設定がコンソールに出力されます。
同じコマンドはいつでも再実行できます。
- 最新の状態ですか? → 「すでにインストール済みで最新の状態です。インストールするものはありません」 と表示され、設定が再度出力されます。
- GitHub/PyPI に新しいリリースがありますか? → パッケージが更新され、古くなった gtags ツールチェーンが削除されて自動的に再インストールされ、バックグラウンドサーバーが新しいバージョンで再起動します。
スラッシュコマンド(MCP プロンプト)
MCP プロンプトに対応しているクライアント(Claude Code、 Cursor)であれば、どのインストール方法でも利用できます。ツールスキーマのコンテキストは消費しません。
| コマンド | 実行内容 |
|---|---|
/gtags:impact [git_ref] | git diff → 変更された関数 → それぞれに対して find_callers を実行 → リスク順に呼び出し元を表示 |
/gtags:explain <symbol> | 定義(#ifdef の各バリエーションを含む)→ 本文 → 呼び出し元 → 短い説明 |
1 つの設定で複数のリポジトリに対応
インストール方法にかかわらず、ユーザーレベルの設定項目 1 つで、開いたすべてのリポジトリに対応します。20 個のリポジトリを使っていても、追加のインストールや設定は不要です。各ツール呼び出しでは、次の順にプロジェクトルートが解決されます。
- ツール呼び出しの
project_root引数(エージェントはこれを指定して任意のツリーを対象にできます) --rootフラグ/GTAGS_MCP_ROOT環境変数- 設定ファイル内の
root(注:ここでルートを固定すると、複数リポジトリへの対応ができなくなります) - クライアントのワークスペースルート(MCP roots プロトコル)— 開いているフォルダーを通知する IDE では、共有 HTTP サーバーでも自動的に適切なリポジトリが選択されます。複数のフォルダーが開いている場合は、エージェントに
project_rootの指定を求めます。ルートが使えるのは、プロトコル改訂が 2025-11-25 までのクライアントに限られます。2026-07-28 改訂では廃止されたため、該当するクライアントはこの手順をスキップします(stdio サーバーは引き続き手順 5 で解決します。共有 HTTP サーバーでは、エージェントがproject_rootを指定します) - サーバーの作業ディレクトリから上位にたどり、最も近い
.git/GTAGSを探します。これが、リポジトリ内で Claude Code/Cursor が起動した stdio サーバーをそのまま使える理由です。
手順 5 は --no-cwd-fallback / GTAGS_MCP_CWD_FALLBACK=0 で無効にできます
(プラグインではこの設定が適用されます)。無効にすると、ツールはサーバーがたまたま実行されているディレクトリをインデックス化する代わりに、project_root の指定を求めます。プラグインクライアントは、プロジェクトではないプラグイン自体のフォルダーからサーバーを起動します。
これで完了です。インデックス作成も設定も不要です。エージェントに 「tcp_v4_rcvを呼び出しているのは誰ですか?」 と尋ねてください。どのリポジトリでも、最初のクエリでそのリポジトリのインデックスが自動的に作成され、以降のクエリには数ミリ秒で回答します。mcp-gtags-server doctorをいつでも実行してサーバーが検出した内容を確認したり、mcp-gtags-server configを実行してクライアント設定を再表示したりできます。
バックグラウンドサーバーの詳細(ネットワークアクセス、ポート、ライフサイクル)
インストーラーはバックグラウンドでmcp-gtags-server --transport http --host 127.0.0.1 --port 8383を実行します(PID:~/.gtags-mcp/server.pid、ログ:~/.gtags-mcp/server.log)。インストーラーで使用する環境変数による上書き設定:
| 変数 | デフォルト | 意味 |
|---|---|---|
GTAGS_MCP_PORT | 8383 | HTTP ポート |
GTAGS_MCP_HOST | 127.0.0.1 | バインドアドレス — 他のデバイスからhttp://<machine-ip>:8383/mcpでサーバーにアクセスするには、0.0.0.0に設定します |
GTAGS_MCP_NO_SERVER | 未設定 | 1 = バックグラウンドサーバーを起動しない |
セキュリティに関する注意: HTTP エンドポイントには認証がありません。デフォルトではローカルホストにバインドされます。0.0.0.0へのバインドは、信頼できるネットワークでのみ行ってください。
手動インストール(システムパッケージを優先する場合、またはGlobalがすでにインストールされている場合)
# 1. GNU Global — EITHER user-space (no sudo):
mcp-gtags-server setup
# OR a system package:
sudo apt install global # Debian/Ubuntu
sudo dnf install global # Fedora
brew install global # macOS
# 2. The server:
uv tool install mcp-gtags-server # or: pip install mcp-gtags-server
サーバーは次の順序でバイナリを検索します:--bin-dir/GTAGS_MCP_BIN_DIR/設定のbin_dir → ~/.gtags-mcp/bin → PATH → ~/.local/bin。
Claude Desktop — 拡張機能バンドルまたは手動設定
最も簡単な方法は、最新リリースからmcp-gtags-server.mcpbをダウンロードし、Claude Desktopの「設定」→「拡張機能」にドラッグして、セットアップ画面でプロジェクトフォルダーを選択することです。初回使用時にgtagsツールチェーンが自動的にインストールされます。
または、claude_desktop_config.jsonに手動で追加します(Desktopはリポジトリ内から起動しないため、プロジェクトを固定してください)。
{
"mcpServers": {
"gtags": {
"command": "uvx",
"args": ["mcp-gtags-server", "--root", "/absolute/path/to/your/project"]
}
}
}
プロジェクトルートを明示的に固定
デフォルトでは、サーバーはクライアントが通知するワークスペースルート(MCP roots protocol)を使用するか、作業ディレクトリから上位へたどり、最も近い.gitまたは既存のGTAGSを見つけてプロジェクトルートを自動検出します。そのため、モノレポ内のどこからクエリを実行しても、リポジトリルートが解決されます。--root /path、GTAGS_MCP_ROOT環境変数、または設定ファイル内のrootで上書きできます。または、個別のツール呼び出しでproject_rootを渡すと、別のツリーをクエリできます。(解決順序の詳細は「1つの設定で複数のリポジトリ」を参照してください。)
設定ファイル — プロジェクトおよびユーザーごとのデフォルト設定
.editorconfigのように、チームがリポジトリを通じてデフォルト設定を共有できるよう、すべての設定をTOMLファイルに保存することもできます。
- プロジェクト:プロジェクトルートの
.gtags-mcp.toml - ユーザー:
~/.config/gtags-mcp/config.toml
# .gtags-mcp.toml
label = "native-pygments" # force a GTAGSLABEL parser label
bin_dir = "/opt/tools/bin" # extra directory searched for gtags/global/ctags
skip_globs = ["*.gen.c"] # never index paths/basenames matching these globs
respect_gitignore = true # default: index only what `git ls-files` reports
enrich = true # default: ctags kind/signature/scope on results
guards = true # default: #ifdef guard stacks on results
macro_resolve = true # default: resolve macro-generated symbols (sys_*, ...)
# root = "/abs/path" # default project root (user config)
優先順位:ツール呼び出しの引数 > CLI フラグ > 環境変数 > プロジェクト設定 > ユーザー設定 > 組み込みのデフォルト。
8 つのツールがあり、update_index を除いてすべて読み取り専用です。各ツールは project_root と
format(デフォルトは "text"、または "json")を受け取ります。リスト形式のツールは limit/offset も受け取ります。
パラメーターの完全なリファレンス:ドキュメント → ツール。
- find_definition — 定義へ移動します。すべての定義について、
#ifdefのガードスタックと ctags の種別/シグネチャに加え、使用状況の概要(参照数/ファイル数、使用頻度の高いファイル、EXPORT_SYMBOL*の状態)を返します。マクロで生成された名前(sys_read→SYSCALL_DEFINE3)も解決します。 - find_references — ガードスタック付きですべての使用箇所を返します。参照が 200 件を超える場合はファイルごとの分布を返し、
path_prefixで 1 つのディレクトリに絞り込めます。 - get_symbol_body — ファイル全体ではなく、1 つの定義(関数、構造体、複数行のマクロ)のソースを返します。
- find_callers — この関数を呼び出す関数を返します。参照をそれぞれの呼び出し元関数に対応付け、重複を除去し、呼び出し数と呼び出し行を示します。
- find_callees — この関数が呼び出す関数を返します。本体から取得した呼び出し箇所をインデックスと照合し、ツリー内(場所付き)と外部に分けて表示します。
- reachability — 関数 A から関数 B への最短の静的呼び出しチェーンを、各呼び出し段階のファイルと行番号とともに返します。経路がない場合は「静的な経路なし」と返します。
- list_file_symbols — ファイルが定義するすべてのシンボル(その API サーフェス)を返します。
- update_index — 編集後にインデックスを同期的に更新します。
full=trueを指定すると、最初から再構築します。書き込みを行う唯一のツールです。
シンボルレベルのツール — ノイズを減らす
ファイルではなく、シンボルをエージェントに渡しましょう。
| ツール | エージェントが取得する情報 |
|---|---|
get_symbol_body | 定義のソースだけです。 271 行の tcp_v4_rcv 関数を取得し、その関数を含む 3,500 行のファイル全体は取得しません。関数、構造体、複数行のマクロに対応します。 |
find_callers | 重複のない呼び出しグラフです。 すべての参照を呼び出し元関数に対応付け、呼び出し数を示します。ext4_mark_inode_dirty の生の参照 245 行は、62 個の呼び出し元に集約されます。必要な深さまで呼び出し元グラフをたどることができます。 |
find_callees | 出力側の呼び出しグラフです。 この関数は何を呼び出すのでしょうか。本体から抽出した呼び出し箇所をそれぞれインデックスで確認し、ツリー内(場所付き)と外部に分けて表示します。 |
reachability | 「この関数はあの関数に到達する可能性がありますか?」 — 呼び出し元グラフの幅優先探索(BFS)により、A から B への最短呼び出しチェーンと、各呼び出し箇所のファイルと行番号(ksys_read → vfs_read → rw_verify_area)を返します。到達できない場合は、関数ポインターに関する注意点を明示した「静的な経路なし」を返します。find_callers を十数回繰り返す代わりに、1 回の呼び出しで済みます。 |
基本的な検索
| ツール | 機能 | 内部で実行するコマンド |
|---|---|---|
find_definition | これはどこで定義されていて、何ですか? #ifdef ガードと ctags メタデータを含む定義に加え、使用状況の概要(参照数/ファイル数、使用頻度の高いファイル、EXPORT_SYMBOL* の状態)を表示します。マクロファミリー(sys_*、trace_*、DEFINE_* の名前)の解決にもフォールバックし、該当するものがない場合は接頭辞が一致する候補を提示します | global -x + マクロ生成シンボルも解決できます(sys_read、SYSCALL_DEFINE3 など) |
find_references | すべての使用箇所と、それぞれのガードスタックを表示します。参照数が 200 を超える場合は、行の一覧ではなくファイルごとの分布を返します(kmalloc の 2,744 件の参照も 1 画面で表示できます)。path_prefix で特定のディレクトリに絞り込み、group_by でどちらの表示形式にするかを指定できます。シンボル使用記録(libc 呼び出し、一部の変数)にもフォールバックし、fallback として明示します | global -rx -S <dir>、フォールバック時は global -sx |
list_file_symbols | ファイルの API サーフェス、つまりそのファイルが定義するすべてのシンボルを表示します | global -fx |
update_index | 編集後にインデックスの最新状態を同期的に保証します。full=true を指定すると最初から再構築します(通常は不要です。インデックスは自動的に更新されます) | gtags -i / gtags |
すべてのクエリツールは、limit/offset によるページネーション、長い行の切り詰め、そして(適用できる場合は)case_insensitive に対応しています。コンテキストウィンドウを決して溢れさせないよう、出力は綿密に設計されています。
また、すべてのツールで MCP ツールアノテーションが宣言されています。update_index を除き、すべて readOnlyHint: true であり、いずれもお使いのマシンの外部にはアクセスしません(openWorldHint: false)。クライアントはこれらのヒントを使って、読み取り専用の呼び出しを自動承認し、並列化できます。各レスポンスでは、エンベロープはテキストコンテンツとして一度だけ含まれ、structuredContent に重複して格納されることはありません。
コンテキストウィンドウを節約する使い方
1. find_definition("kmalloc") → definitions + #ifdef variants + usage spread (3 lines)
2. find_callers("ext4_mark_inode_dirty") → deduped callers, each with its call line
3. get_symbol_body("tcp_v4_rcv") → read the ONE function that matters
4. find_callees("tcp_v4_rcv") → what it depends on, with locations
5. reachability("ksys_read", "rw_verify_area") → the call chain, one line per hop
6. find_references("mutex_lock", path_prefix="fs/ext4") → hot symbol, one subsystem
コンテキストは合計で数百行ほどです。grep してファイルを読む方法では、数万行に達します。
出力とカーネル向けの工夫
出力:デフォルトはコンパクトなテキスト、要求に応じて JSON
v2.0.0 以降、すべてのツールは grep 形式のテキストで回答します。エージェントが最も読み取りやすく、同じ回答を JSON で返す場合と比べてトークンを 2~3 倍節約できます。
kmap: 4 definitions under 3 #if variants · 261 refs in 65 files (top: tools/perf/util/machine.c 26, …)
include/linux/highmem-internal.h:40: static inline void *kmap(struct page *page) [function; #if CONFIG_HIGHMEM]
include/linux/highmem-internal.h:170: static inline void *kmap(struct page *page) [function; #if !CONFIG_HIGHMEM]
next: get_symbol_body, find_callers, find_references
path:line: source の行には、シンボルの種類と、そのシンボルが属する #if/#ifdef のスタックを示すタグが含まれます。ページ分割された結果の末尾には、[1-100 of 5290 · offset=100 for more] のようなフッターが付きます。
v1.x のデフォルトである JSON と比べると、同じカーネルに関する 7 つの質問で、合計トークン数が 20%減少します。個々の検索では最大 68%削減できます。トークン数が増えた呼び出しは find_callers だけです(約 9%増)。意図的な変更で、各呼び出し箇所のソース行が含まれるようになりました。以前はエージェントが確認するために追加の grep を実行していた情報です。
機械可読なエンベロープが必要な場合は、format="json" を指定してください。同じデータを、唯一の信頼できる情報源から出力します。
{
"tool": "find_definition",
"root": "/abs/project/root",
"results": [
{"symbol": "kmap", "path": "include/linux/highmem-internal.h", "line": 40,
"col": 22, "kind": "function", "typeref": "void *", "scope": null,
"signature": "(struct page * page)", "guard": ["CONFIG_HIGHMEM"],
"snippet": "static inline void *kmap(struct page *page)"}
],
"total": 2, "offset": 0, "truncated": false,
"definition_count": 2, "guard_variants": 2, "reference_count": 261,
"file_count": 65, "top_files": [{"path": "…", "count": 26}], "exported": null,
"next_tools": ["get_symbol_body", "find_callers", "find_references"],
"warning": null
}
- シンボルの位置情報には、リポジトリ相対パスを使用する安定したレコードスキーマ
{symbol, path, line, col, kind, typeref, scope, signature, guard, snippet}が常に使われます。キーは追加されることはあっても、メジャーバージョン内で名前が変更されたり削除されたりすることはありません。 kind/typeref/scope/signatureは、シンボルが「何であるか」を示します(v0.8.1 以降)。関数、マクロ、構造体、typedef、列挙型定数のどれなのか、戻り値/対象の型、包含するスコープ(enum:color、struct:item)、パラメーターリストを示します。各ファイルから universal-ctags で抽出され、ビルドもコンパイルデータベースも不要です。キャッシュされ、定義形式の結果(find_definition、list_file_symbols)に追加されます。universal-ctags が利用できない場合、フィールドは単にnullになります。--no-enrich、GTAGS_MCP_ENRICH=0、または.gtags-mcp.tomlのenrich = falseで明示的に無効化できます。guardはシンボルが「いつ」存在するかを示します(v0.9.0 以降)。外側から順に並んだ、包含する#if/#ifdefのスタックです([]= 無条件、null= スキャンが無効、またはファイルを読み取れない)。次のセクションをご覧ください。これが主要な新機能です。resolved_viaは、シンボルが「どのように」見つかったかを示します。リテラルなインデックス一致ではなく、マクロファミリーによる解決が行われた場合に設定されます("macro:SYSCALL_DEFINE"、"fuzzy:vfs_read")。マクロ生成シンボルも解決をご覧ください。next_toolsは、見つかったもの(または見つからなかったもの)に対して、次に呼び出すと最も有用なツールをエージェントに伝えます。total/offset/truncatedはページネーションを制御します。失敗時もerrorフィールドを含むエンベロープが維持され、プロトコル上でisErrorが設定されるため、エージェントは自力で修正できます。- 複合ツールは、同じエンベロープ内でツール形式の
resultsを返します(例:find_calleesは{in_tree, external}、reachabilityはホップチェーン)。 - すべてのツールは MCP ツールアノテーションを宣言します。
update_indexを除き、すべてreadOnlyHint: trueで、マシンの外部にはアクセスしません(openWorldHint: false)。クライアントはこれらを使って呼び出しを自動承認し、並列化できます。
v1.x からアップグレードしますか? 以前のデフォルトを解析していた箇所では、明示的に format="json" を指定してください。symbol_info は find_definition に統合され、summarize_references は find_references に置き換わりました(ファイルごとに自動でグループ化されます)。blast_radius は /gtags:impact プロンプトに置き換わりました。git diff を実行し、変更された関数ごとに find_callers を実行してください。
#ifdef に対応:実際にコンパイルされる定義を把握できます
カーネルやファームウェアのコードでは、同じシンボルを複数回定義し、ビルド設定によってどれを使うか選択します。ほかのビルド不要ツールは、説明のない平坦なリストを返すだけです。そのため、エージェントは kmap の何もしないスタブを読み込み、誤った答えを導き出してしまいます。このサーバーはプリプロセッサの条件文を読み取ります(純粋なスキャンであり、引き続きビルドも compile_commands.json も不要です)。
Symbol: kmap
2 definitions under 2 distinct guards:
[CONFIG_HIGHMEM] defined at include/linux/highmem-internal.h:40 — function kmap(struct page * page) -> void *
[!CONFIG_HIGHMEM] defined at include/linux/highmem-internal.h:170 — function kmap(struct page * page) -> void *
active_config にカーネルの .config パス、または "CONFIG_SMP,BITS_PER_LONG=64,!CONFIG_DEBUG" のようなマクロリストを渡して、find_definition または find_references を呼び出します。条件ガードのスタックがその設定で確実に偽となる定義は除外されます(エンベロープには件数が config_filtered として報告されます)。フィルタリングは意図的に保守的です。.config は CONFIG_* マクロについて閉じた世界として扱われます(=m → CONFIG_X_MODULE や、kbuild のセマンティクスに加え、IS_ENABLED/IS_BUILTIN/IS_MODULE も含みます)。一方、未知のもの(__ASSEMBLY__、ARCH_HAS_*、判定できない算術式など)によって結果が除外されることはありません。
出力をすっきり保つため、細部にも対応しています。従来のインクルードガード(#ifndef FOO_H)を検出して抑制し、#elif の連鎖を明示的な条件(!CONFIG_X86_64 && CONFIG_X86_32)に組み立て、ディレクティブ内のコメントは無視し(誤解を招くため)、破損または一部しかないファイルがクエリに失敗することはありません。.gtags-mcp.toml で --no-guards、GTAGS_MCP_GUARDS=0、または guards = false を指定すると無効にできます。
マクロで生成されるシンボルも解決します(sys_read → SYSCALL_DEFINE3)
カーネルで、あらゆるタグ付けツールに最もよく見られる問題があります。sys_read、trace_sched_switch、css_set_lock は、どこにもリテラルな定義がありません。トークン連結マクロによって生成されるため、通常の検索では何も返ってこないか(もっと悪い場合は、同じ名前のテスト用ヘルパーが返ってきます)。このサーバーはプリプロセッサもビルドも使わず、インデックスだけから解決します。
find_definition("sys_read") → fs/read_write.c:723 SYSCALL_DEFINE3(read, ...) resolved_via: "macro:SYSCALL_DEFINE"
find_definition("__x64_sys_openat")→ fs/open.c:1385 SYSCALL_DEFINE4(openat, ...) (arch entry-point wrappers map back)
find_definition("trace_sched_switch") → include/trace/events/sched.h:220 TRACE_EVENT(sched_switch, ...)
find_definition("css_set_lock") → kernel/cgroup/cgroup.c:82 DEFINE_SPINLOCK(css_set_lock);
対応するファミリー:SYSCALL_DEFINE0..6/COMPAT_SYSCALL_DEFINE*(__x64_/__ia32_/__arm64_/__se_/__do_ のラッパー表記を含む)、トレースポイント(TRACE_EVENT、DEFINE_EVENT、DECLARE_TRACE など)、名前をそのまま使う定義マクロ(DEFINE_SPINLOCK、DEFINE_MUTEX、DEFINE_PER_CPU*、DECLARE_BITMAP、module_param*、DEFINE_/DECLARE_ 形式のマクロ全般)です。さらに、最後の手段として、アンダースコアのバリエーションを試すあいまい検索の層もあります。解決結果はエンベロープ内で resolved_via として示され、同じ名前のテキスト上の別候補より上位にランク付けされます。DEFINE_* の箇所は対応する DECLARE_* より上位にランク付けされます。find_definition はさらに、カーネルシンボルがどの EXPORT_SYMBOL/EXPORT_SYMBOL_GPL の形式でエクスポートされているかを、exported フィールドで報告します。シンボルが通常どおり解決される場合、追加コストはありません(追加のインデックス検索を行うのは sys_*/trace_* のようなファミリー形式の名前だけです)。--no-macro-resolve、GTAGS_MCP_MACRO_RESOLVE=0、または .gtags-mcp.toml の macro_resolve = false を指定すると無効にできます。
インデックス対象(不要なものは除外)
インデックス作成では、ツリーをたどらせるのではなく、明示的なファイルリストを gtags に渡します。
- Git リポジトリ内では、ファイルリストは
git ls-filesから取得します。.gitignoreの内容がそのまま正確に適用されるため、ビルド出力、ベンダー提供のファイル、生成ファイルがインデックスを汚すことはありません。.gtags-mcp.tomlでrespect_gitignore = falseを指定すると無効にできます。 - Git 管理外では、よくある不要なディレクトリ(
.git、node_modules、build、dist、.venvなど)を除外してツリーを走査します。 .gtags-mcp.tomlのskip_globsを使うと、ほかにインデックス対象から外したいものも除外できます。
差分更新時にはファイルリストを再収集するため、新たに無視対象となったファイルはインデックスから削除され、新しいファイルは自動的に追加されます。
多言語プロジェクト(C + Python + ほか)
実際のプロジェクトでは、複数の言語が混在します。C のコアに Python のツール、JS のフロントエンド、Go のサービスが加わることもあります。サーバーはこれを自動的に処理します。
- ネイティブ言語(C、C++、Java、PHP、Yacc、アセンブリ)では、GNU Global の高速な組み込みパーサーを使用します。
- それ以外のすべての言語(Python、Go、Rust、JavaScript、TypeScript、Ruby など、約150言語)は、Global の ctags + Pygments プラグインパーサーを通じてインデックス化されます。同じインデックス、同じツール、同じクエリを利用できます。
1行のインストーラー(および mcp-gtags-server setup)がこれを自動的に有効にします。universal-ctags と Pygments をユーザー領域にインストールし、サーバーは自動的に native-pygments パーサーラベルに切り替わります。システムパッケージを使いたい場合も利用できます。
sudo apt install exuberant-ctags python3-pygments # Debian/Ubuntu
sudo dnf install ctags python3-pygments # Fedora
brew install ctags && pip install pygments # macOS
これで、find_definition("py_util")、get_symbol_body(Python のインデントを認識)、find_callees、find_callers が、ツリー内のすべての言語に対して、ひとつのインデックスで機能します。
--label、GTAGS_MCP_LABEL、または .gtags-mcp.toml の label を使って、特定のパーサーラベルを強制できます(例:ネイティブ言語のみなら default、すべての言語でプラグインを使うなら pygments)。
**正直なところ、注意点があります:**プラグインで解析される言語では、定義の精度は ctags と同等ですが、参照はトークンベースです。C と同等の意味解析による参照追跡やローカルスコープの認識はなく、名前の出現箇所すべてがカウントされます。C/C++ では何も変わらず、この部分は引き続きネイティブパーサーが処理します。
仕組み
アーキテクチャ
IDE ウィンドウごとに長時間稼働するサーバープロセスが1つ(stdio)、またはマシン全体で共有する HTTP サーバーが1つ動作します。負荷の大きい処理はすべてディスク上にあり、共有されます。ツールチェーンはマシンごとに1回だけインストールされ、インデックスはリポジトリごとに1回だけ構築されます。
flowchart LR
subgraph clients["MCP clients"]
CC["Claude Code / Cursor / VS Code"]
CD["Claude Desktop (.mcpb)"]
end
subgraph proc["mcp-gtags-server — spawned once per window, lives for the session"]
T["11 navigation tools"]
RR["root resolution<br/>project_root → env → config → client roots → cwd"]
end
subgraph disk["your machine, user space (no sudo)"]
TC["~/.gtags-mcp<br/>global · gtags · ctags · Pygments<br/>self-installs on first use"]
IX["<repo>/.gtags-mcp/GTAGS<br/>one index per repo, auto-built"]
end
CC -- "stdio (uvx)" --> T
CD -- "stdio" --> T
T --> RR
RR -- "runs global (ms, indexed)" --> TC
TC -- "B-tree lookup" --> IX
ツール呼び出しの一連の流れ
バイナリは呼び出しごとに再実行されません。サーバープロセスは稼働し続け、各呼び出しは1つの JSON-RPC メッセージと、ミリ秒単位で完了する global のサブプロセス1つで処理されます。
sequenceDiagram
participant A as Agent
participant S as server (long-lived process)
participant G as global (GTAGS index)
A->>S: find_definition("tcp_v4_rcv")
Note over S: first call on this machine?<br/>toolchain installs itself in the background,<br/>calls answer "installing — retry shortly"
Note over S: first query in this repo?<br/>index auto-builds once (~66 s for the kernel)
S->>G: global -dx tcp_v4_rcv
G-->>S: net/ipv4/tcp_ipv4.c:2067 (milliseconds)
S-->>A: narrow JSON answer — no grep firehose
- **このツリーへの最初のクエリですか?**インデックスは自動的に構築されます(処理がブロックするのはこの操作だけで、しかも1回限りです)。
- **インデックスファイルはどこに保存されますか?**プロジェクトルートにある単一の
.gtags-mcp/フォルダーです。コードの隣にファイルが散らばることはありません。このフォルダーには独自の.gitignoreが含まれているため、自分の.gitignoreに手を加えなくてもgit statusはクリーンな状態を保ちます。ルートレベルに既存のGTAGSがある場合(旧バージョンのものや、自分で実行した gtags によるもの)は、そのまま引き続き使用されます。保存場所はmcp-gtags-server doctorで確認できます。 - ファイルが変更されましたか?デバウンス付きの増分更新がバックグラウンドで実行されます。
gtags -iがバックグラウンドで追いつく間も、クエリには常に現在のインデックスから即座に応答します。カーネルでの測定では、25秒かかる鮮度チェックが見えないところで実行されている間も、クエリは0.02秒で返ります。古さの上限はデバウンスの待機時間によって決まります。編集直後に同期的な更新を行い、確実に最新の状態を保証するにはupdate_indexを呼び出してください。 - **結果が膨大ですか?**ページネーションのフッターが、次のページを取得する方法をエージェントに正確に伝えます。また、ツール自体がより絞り込んだ別のツールを提案することもあります(500以上のファイルで使われているシンボルに対する
find_callersは、ファイルごとにグループ化するfind_referencesを提案します)。
FAQ
LSP(言語サーバープロトコル)ではなく gtags を使うのはなぜですか?
LSP サーバーはより豊かなセマンティクスを提供しますが、動作するビルド設定、エディターごとのセットアップ、大規模なコードツリーではかなりのウォームアップ時間が必要です。gtags は設定不要で、約1分で3,700万行をインデックス化し、LSP が処理しきれないカーネル規模のコードベースにも対応します。また、ファジーパーサーはコードが現在コンパイルできるかどうかを問いません。C/C++ のナビゲーションに関する質問――定義、参照、呼び出し元――には、実用性と機能のバランスが取れた選択肢です。(コンパイルデータベースがあるケース向けに clangd をラップする案も検討されましたが、意図的に却下されました。動作する compile_commands.json を持つユーザーは、すでに clangd とそのエコシステムを利用できるためです。詳しくはROADMAP.mdを参照してください。)
どの言語に対応していますか? C、C++、Yacc、Java、PHP、アセンブリにネイティブ対応し、ctags/Pygments プラグインパーサーを通じて Python、Go、Rust、JS/TS、Ruby など約150の言語にも対応します(複数言語のプロジェクトを参照してください)。
エージェントがインデックスを管理する必要はありますか?
いいえ。それがこのツールの要点です。初回クエリ時にビルドし、適応型デバウンスでバックグラウンド更新を行い、ブロックは一切ありません。クエリがインデックスのメンテナンスを待つことはありません。明示的な update_index ツールは、編集後に同期的に最新状態を保証する手段と、full=true による最初からの再ビルドという、いざというときのためにのみ用意されています。
インデックスはどこに保存されますか?削除してもよいですか?
プロジェクトルートの .gtags-mcp/ に保存されます(Git の無視対象に自動追加されます)。いつでも自由に削除できます。次のクエリ時に最初から再ビルドされます。
エージェントに組み込みのツールがある場合、競合しませんか? ツールの説明はモデルを適切に誘導するように書かれており、grep ではなくインデックス検索をいつ使うべきかを示しています。実際には、エージェントはより速く範囲も絞られたツールを自然に選択します。
起動時に ModuleNotFoundError: No module named 'mcp.server.fastmcp' が発生しますか?
v1.4.2 までのリリースでは mcp 依存関係に上限が指定されていなかったため、MCP Python SDK 2.0 のリリース後にインストールすると、インポートできない SDK が解決されていました。v1.4.3 では SDK を 2.0 未満に制限して修正され、v1.5.0 以降は SDK 2.x(mcp>=2.2,<3)でネイティブに動作し、2024-11-05 から 2026-07-28 までのすべてのプロトコルリビジョンに対応します。uvx --refresh mcp-gtags-server --help(または uvx mcp-gtags-server@latest)を実行するか、インストーラーを再実行して修正を適用してください。古いリリースを使い続ける必要がある場合は、SDK を自分で固定してください。uvx --with 'mcp<2' [email protected]
開発
git clone https://github.com/harshithsunku/mcp-gtags-server
cd mcp-gtags-server
uv run --extra dev pytest # 325 tests; e2e tests auto-skip if GNU Global is absent
npx @modelcontextprotocol/inspector mcp-gtags-server # poke at it interactively
テストでは一時ディレクトリに実際の C プロジェクトをビルドし、自動インデックス化、自動更新、呼び出し元のマッピング、関数本体の抽出、ページネーション、ユーザー空間のバイナリ検出、設定の階層化をエンドツーエンドで検証します。
正確性は想定するのではなく、測定も行います。mcp-gtags-server eval --golden evals/golden.jsonl --root <kernel-tree> を実行すると、実際のカーネルを対象に、8つのツール(定義、マクロ解決、参照、呼び出し元、呼び出し先、本体、ガード、到達可能性、メンテナンス)を網羅する64ケースのゴールデンテストセットが実行され、再現率と precision@1 が出力されます。CI では、固定タグを使って毎週これを実行しています。現在の数値についてはdocs/capability.mdを参照してください。
リリース手順:pyproject.toml の version を更新し、vX.Y.Z のタグを付けて push すると、CI が PyPI に公開し、ユーザーは次回インストーラーを再実行した際に更新を取得できます。ビルド済みの GNU Global バイナリは、global-v<version> のタグを付けて再ビルドできます(または gh workflow run release-binaries.yml -f version=<version> を実行して、既存リリースのアセットをその場で置き換えます)。Linux ビルドは manylinux_2_28 コンテナー内で実行されるため、glibc ≥ 2.28 のホストで動作します。CI のシンボル上限チェックによってこれを保証しています。
ロードマップ
ROADMAP.md をご覧ください。v0.8.0 では構造化 JSON 出力、v0.8.1 では ctags メタデータの拡充(kind/signature/scope)、v0.9.0 では #ifdef/設定ガードへの対応(カーネルやファームウェアのツリー向けの主要機能)がリリースされました。さらに v1.0.0 では、以下の機能がすべてリリースされました。マクロファミリーのシンボル解決(sys_read → 対応する SYSCALL_DEFINE3 の箇所)、エージェント向けワークフローツール(到達可能性、差分影響分析)、破損したインデックスデータベースからの自動復旧、そして正確性評価ハーネスです。正確性評価ハーネスは、固定された kernel v6.16 を対象にした 64 ケースのゴールデンセットで、CI において再現率 100%/precision@1 100% を達成しており、実測結果の詳細は docs/capability.md に記載しています。技術面のマイルストーンはすべて完了しており、残るのは配布(MCP レジストリ、ディレクトリ、解説記事)です。
貢献を歓迎します。issue または PR をお寄せください。
ライセンス
MIT © Harshith Sunku
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。