Context7 MCP を入れたのに、Claude Code が params を同期オブジェクトとして受け取る Next.js 14 時代のコードを返してきた——導入直後の私が最初にぶつかったのは、これでした。use context7 と末尾に書いたはずなのに、生成されたコードは以前と変わりません。
ドキュメント注入の MCP は、入れれば終わりではありません。やっかいなのは、注入が不発でも何のエラーも出ないことです。Claude は学習済みの知識で淡々とコードを書き、こちらは「Context7 が効いている前提」で受け取ってしまう。個人開発で半年ぶんの自動投稿パイプラインを一人で回していると、この「静かな不発」が積み重なって、あとで動かないコードの手直しに時間を取られます。私自身、最初の数日はこの不発に気づけませんでした。
この記事は Context7 のセットアップ手順ではなく、注入が本当に効いているかを運用でどう確かめ、効かなかったときにどう拾うかの実装メモです。
「use context7」と書いても、参照されないことがある
まず押さえておきたいのは、use context7 は強制ではなく示唆だということです。Claude がそのターンで「ドキュメントを引く必要はない」と判断すれば、ツールは呼ばれません。短い質問、抽象的な依頼、あるいはコンテキストに既にそれらしい情報がある場合に起こりやすい挙動です。
つまり、注入が効いたかどうかはツール呼び出しが実際に発火したかを見るのが一番確実です。Claude Code には MCP の状態を確認する /mcp がありますが、これは接続の有無を見るもので、各ターンで呼ばれたかまでは追えません。そこで、フックでツール呼び出しを記録します。
~/.claude/settings.json に PostToolUse フックを足し、Context7 のツールが呼ばれたらログに残します。
{
"hooks": {
"PostToolUse": [
{
"matcher": "mcp__context7__.*",
"hooks": [
{
"type": "command",
"command": "echo \"$(date -Iseconds) context7 called in $CLAUDE_PROJECT_DIR\" >> ~/.claude/context7-calls.log"
}
]
}
]
}
}
matcher は MCP ツール名の正規表現です。Context7 のツールは mcp__context7__resolve-library-id と mcp__context7__get-library-docs の2つなので、mcp__context7__.* で両方を拾えます。コード生成を頼んだあとにこのログが伸びていなければ、その回は注入が不発だったということです。
数日ログを眺めると、自分の頼み方の癖が見えてきます。私の場合「このコンポーネントをリファクタして」のような曖昧な依頼でツールが呼ばれていないことが多く、ライブラリ名を主語に置くと安定して発火するようになりました。
取得されるドキュメントにも、当たり外れがある
ツールが呼ばれていても安心はできません。Context7 は内部で2段階——まず resolve-library-id でライブラリを特定し、次に get-library-docs で本文を取得します。この特定段階で、似た名前の別ライブラリや、古いメジャーバージョンのページに解決されることがあります。
ここで効くのが、曖昧さを残さない指定です。ライブラリ名だけでなく、Context7 が内部で使う ID 形式(/組織名/リポジトリ名、必要ならバージョンまで)を直接渡すと、解決のぶれが減ります。
Next.js 15 の App Router で動的ルートの params を扱うコードを書いてください。
ライブラリは /vercel/next.js のバージョン 15 系のドキュメントを参照してください。
use context7
変更の速いライブラリほど、このバージョン明示の効果が大きく出ます。Tailwind CSS の v3 と v4 のように設定方式が根本から変わったケースでは、バージョンを言わないと旧版の tailwind.config.js 前提のコードが返りがちです。逆に Day.js のような安定したライブラリでは、ここまで神経質になる必要はありません。
「効いているか」を毎回、機械的に確かめる
人間がコードを目視で「これは最新っぽい」と判断するのは当てになりません。私は、学習データ後に変わったことが分かっている API を踏み絵にするやり方に落ち着きました。Next.js 15 で params が Promise になった変更は、まさに踏み絵に向いています。注入が効いていれば Promise< と use( が現れ、効いていなければ同期アクセスのままです。
生成されたファイルに対して、この差分を自動でチェックする小さなハーネスを置いています。
// scripts/verify-fresh.mjs
// 生成された Next.js ページが v15 の params 仕様に沿っているかを検証する。
// "古いパターンが残っていないか" を機械的に弾くための踏み絵。
import { readFileSync } from 'node:fs';
const file = process.argv[2];
if (!file) {
console.error('usage: node verify-fresh.mjs <生成されたファイル>');
process.exit(2);
}
const src = readFileSync(file, 'utf8');
const usesParams = /params/.test(src);
if (!usesParams) {
console.log('skip: params を扱っていないファイルです');
process.exit(0);
}
// v15 では params は Promise。await か React の use() で解決しているはず。
const isFresh = /params\s*:\s*Promise</.test(src)
&& /(await\s+params|use\(\s*params\s*\))/.test(src);
if (isFresh) {
console.log('ok: Next.js 15 の params 仕様に沿っています');
process.exit(0);
}
console.error('NG: 旧 App Router (同期 params) のパターンが残っています');
console.error(' → ライブラリ ID とバージョンを明示して再生成してください');
process.exit(1);
node scripts/verify-fresh.mjs app/items/[id]/page.tsx のように回し、終了コードで判定します。CI に組み込めば、注入が不発だった生成物がそのままマージされる事故を止められます。踏み絵は対象ライブラリごとに用意するのが理想ですが、まずは自分が一番よく外すライブラリ一つから始めれば十分です。私は Prisma のリレーション定義でも同じ発想の検証を足しています。
ポイントは、検証を「コードが動くか」ではなく「古いパターンが残っていないか」に向けることです。動くかどうかは別のテストの仕事で、ここで見たいのは鮮度だけだからです。
カバーされていないライブラリに当たったとき
Context7 の対応ライブラリは多いものの、ニッチなパッケージや公開直後のものは未対応のことがあります。このとき Context7 は空に近い結果を返し、Claude は学習知識にフォールバックして——また静かに古いコードを書きます。
未対応を前提に、二段構えにしておくと安全です。まず resolve-library-id が当たらなかったら、公式ドキュメントの URL を直接渡して読ませる。Claude Code であれば WebFetch 系のツール、もしくは手元にドキュメントを落としてファイルとして渡す方法が使えます。
このライブラリは Context7 では見つからないかもしれません。
見つからない場合は、私が貼る公式ドキュメントの内容だけを根拠にコードを書いてください。
学習済みの記憶でAPIを補完しないでください。
[ここに公式ドキュメントの該当セクションを貼る]
「学習済みの記憶で補完しないで」という一文が地味に効きます。これを書かないと、Claude は貼られたドキュメントと記憶を混ぜてしまい、結果として一部だけ古いコードになることがあるためです。
CLAUDE.md に鮮度ルールを書き、対象は絞る
毎回 use context7 と打つのは続きません。プロジェクトの CLAUDE.md にルールを書けば、対象ライブラリのコードを書くときに自動で参照されるようになります。ただし全ライブラリを対象にしてはいけません。Context7 が返すドキュメントはトークンを消費し、コンテキストを圧迫するからです。安定したライブラリまで毎回引かせると、肝心のコードに割けるコンテキストが削られ、かえって質が落ちます。
対象は「変更が速く、外しやすいもの」に絞ります。私の判断軸は次の通りです。
| ライブラリの性質 | Context7 を常用するか | 理由 |
| App Router・Server Components 系(Next.js, React) | 常用する | メジャーごとに API 形が変わり、最も外しやすい |
| 設定方式が変わった CSS・ORM(Tailwind v4, Prisma, Drizzle) | 常用する | バージョン間で設定の互換性が低い |
| UI コンポーネント(shadcn/ui 等) | ケースによる | コンポーネント構造の刷新時のみ効果大 |
| 安定した汎用ユーティリティ(Lodash, Day.js) | 常用しない | API がほぼ変わらず、注入はコンテキストの無駄 |
CLAUDE.md には、この絞り込みをそのまま書きます。
## コード生成の鮮度ルール
次のライブラリのコードを書くときは、必ず context7 で最新ドキュメントを参照すること。
対象: Next.js, React, Tailwind CSS, Prisma, Drizzle ORM
参照したら、生成物に旧バージョンのパターンが残っていないか自己確認すること。
上記以外の安定ライブラリでは context7 を使わない(コンテキストの節約のため)。
対象を明文化しておくと、複数のリポジトリを横断して作業するときにも判断がぶれません。私は4つのサイトを同じ方針で運用しているので、この数行をテンプレートとして各 CLAUDE.md の冒頭に置いています。
数週間運用して、落ち着いた使い方
Context7 を導入して一番変わったのは、コードを受け取ったあとの「これ、最新だろうか」という小さな疑念に毎回付き合わなくてよくなったことです。ただ、それは「入れたから」ではなく「注入が効いたかを確かめる仕組みを足したから」だと感じています。MCP を入れただけの最初の数日は、むしろ効いているつもりで古いコードを通してしまい、以前より厄介でした。
ドキュメント注入系の MCP は、効果が見えにくいぶん、検証とセットでないと信頼に変わりません。個人的に運用へ定着したのは、次の三つを置いてからでした。
- フックで Context7 のツール呼び出しを記録し、不発の回を検知する
- 学習後に変わった API を踏み絵にして、生成物の鮮度を機械チェックする
- 未対応ライブラリは「記憶で補完しない」指示と公式ドキュメントの手渡しで備える
この三つを揃えてから、ようやく道具として腰を据えられた感覚があります。私はこの順番で足すことを推奨します。最初から完璧を狙うより、検知・検証・備えを一つずつ積むほうが、運用は崩れにくいからです。
次の一歩としては、自分が直近で一番よく古いコードを書かれたライブラリを一つ選び、その API の「変わった点」を踏み絵にした検証を一本だけ書いてみてください。万能の検証を目指すより、一番痛いところに一つ置くほうが、運用は続きます。