Two weeks ago I migrated this blog from Astro 5 to Astro 6. Claude Code was supposed to know Astro - and it did. Unfortunately, it knew version 5. The code it proposed was technically valid, the syntax ran, the commands executed, but in several places it used APIs that had been rewritten in v6. Content collections, Markdown rendering, the shape of astro.config.mjs - small but expensive differences everywhere. An hour later, after three rounds of “write, break, fix”, the migration was done. Most of that hour went into fighting the model’s knowledge that was six months out of date.

This problem is not just mine. Anyone who uses an LLM to work with code knows the feeling: the model confidently suggests a solution using an API that no longer exists, or proposes syntax from a version you aren’t using. That’s not a bug - it’s the natural consequence of training-data cutoff. The real question is: what do you do about it?

Up to this point, the answers weren’t great. You can copy doc fragments into the prompt by hand - works, but it’s manual. You can use web search - which has its own set of problems, coming up in a minute. You can keep project context in CLAUDE.md - but that’s for your own knowledge, not for docs of third-party libraries. Something in between was missing: a tool that gives the model access to the current, official documentation of a specific library version, on demand.

That something turned out to be context7 - an MCP server from Upstash, which this post is about.

Why web search isn’t enough

The natural first question is: “Why another tool? Claude already has web search.” It does, and in some cases it helps - but only in some.

Web search hands the model a list of links to open and read. The problem is that search results for “React useEffect” typically contain:

  • The official documentation (good, but often the wrong version - web search doesn’t version-match against your project).
  • A 2019 Stack Overflow answer showing a pattern that’s been obsolete for years.
  • Medium articles auto-generated by AI that repeat stale assumptions from training data.
  • YouTube tutorials whose transcript form is worthless as LLM input.
  • Lately, increasing volumes of content farms publishing AI-slop on every popular term.

The model has to filter all of this for what actually applies in the version you’re using. Success rate varies. Realistically: in 60% of cases I get something sensible; in 40% the answer could have come straight from the model’s training data anyway - i.e., the stale one.

Official docs via web search are also too big to chew. react.dev/reference is hundreds of pages. The model has to choose what to read and often lands on v19 instead of v20 because v19 has more link juice. It ends up with a slice that no longer applies.

I needed something that works differently: goes directly into the library’s source repo, reads docs in the exact version I’m using, and returns just that chunk to the model. No noise, no AI-slop, no version mismatches.

What context7 does

Context7 is an MCP server built by Upstash. Technically, it’s a process (npx @upstash/context7-mcp) that Claude Code spawns at startup and talks to over the MCP protocol. It exposes two tools:

  • resolve-library-id - takes a library name (“astro”, “react”, “prisma”, “django”) and returns the canonical identifier used by the server. This is the disambiguation step: “next” can mean Next.js or an unrelated npm package.
  • query-docs - takes a library id, a version, and a question, and returns fragments of the official documentation plus code examples.

The flow looks like this: I ask Claude how to configure content collections in Astro 6. The model calls resolve-library-id("astro"), gets the canonical id. Then it calls query-docs(id, "6", "content collections configuration"). The response is a fragment of Astro 6’s official docs - the fragment goes into the model’s context, and the model generates an answer using the correct API. The entire MCP conversation happens under the hood; I just see the final answer, which this time uses the right API.

The server is hosted by Upstash. No API key, no cost. The index covers most popular libraries: React, Next.js, Vue, Svelte, Angular, Astro, Prisma, Django, Flask, FastAPI, Spring Boot, Express, Tailwind, shadcn/ui, Laravel, Rails, Go, Rust, and hundreds more. Indexing pulls from official repositories, so you get what the authors wrote and merged to main - not what someone wrote on Medium three years ago.

Setup in Claude Code

Three installation options, easiest first:

1) Via the marketplace (simplest):

claude plugin install context7@claude-plugins-official

2) Manually in project .mcp.json:

{
  "context7": {
    "command": "npx",
    "args": ["-y", "@upstash/context7-mcp"]
  }
}

3) Globally in ~/.claude/mcp.json - same thing but visible across all projects.

Once installed, Claude Code sees two new tools: mcp__context7__resolve-library-id and mcp__context7__query-docs. Importantly, the MCP itself ships with an instruction block for the model - a built-in description that tells it precisely when to reach for these tools:

Use this server to fetch current documentation whenever the user asks about a library, framework, SDK, API, CLI tool, or cloud service - even well-known ones like React, Next.js, Prisma, Express, Tailwind, Django, or Spring Boot. (…) Use even when you think you know the answer - your training data may not reflect recent changes.

That sentence - “even when you think you know the answer” - is the key. Without it, the model would only call context7 when it couldn’t work things out on its own. That means: only after it had already made a mistake or become uncertain. The MCP instruction changes the default from “use your own knowledge, web search as backup” to “call context7 for every library; internal knowledge is the fallback”.

When to use it

The official context7 guidance: use it for questions about libraries, frameworks, SDKs, APIs, CLI tools and cloud services, even for well-known ones. That includes API syntax, configuration, version migrations, library-specific debugging, setup instructions, and CLI usage.

Don’t use it for: refactoring, writing scripts from scratch, debugging business logic, code review, or general programming concepts. These are things external docs won’t help with.

In my daily work, context7 earns its keep in three roles.

First, migrations between versions. A “React 19 released” banner on the homepage is one thing; the API diff, breaking changes, and new hooks are another. With context7, the model gets the diff on a plate instead of guessing. On my project, the next Astro migration took 20 minutes instead of an hour.

Second, libraries with fast release cycles. shadcn/ui, Playwright, recent Tailwind releases - anything that ships weekly while the model’s training data is six months old. Context7 returns the current component signature, the current selector syntax, the current CLI command names.

Third, rarely used slices of an API. The model knows useState and useEffect by heart. But useInsertionEffect, or a niche hook from React Query 5 that the authors renamed at release, comes back from training data in the pre-rename form. Context7 returns the current one.

Where context7 breaks down

No tool is perfect. Context7 has a handful of real limitations worth knowing before you set it as default.

  • Libraries not in the index. A small npm package with 50 stars may not be covered. Then resolve-library-id returns nothing and the model falls back to web search or training data.
  • Internal company SDKs. Context7 is useless here - it has no access to your GitHub. You need your own MCP for this (I wrote about this in the first MCP for QA).
  • Unindexed docs or unusual formats. Libraries that keep documentation only in a wiki, PDFs, or as doctest comments in code may not be covered.
  • Freshly released versions. The index has some lag relative to a release. For a library released yesterday, context7 may not yet have the latest version.
  • Inconsistency between docs and code. If a library’s documentation is itself outdated (it happens), context7 will return you outdated information. Garbage in, garbage out.

In my workflow, when context7 returns something strange, I have a simple fallback: I ask the model to verify the suggestion against the project’s package.json (what version I actually have) and then against the official GitHub release notes via web search. Three sources, one decision.

How it layers with everything else

Context7 is not an “instead of” tool - as with most MCPs, its strength is where it sits in the layering.

Imagine a task: “add a new API endpoint to the project, following our conventions, using the current FastAPI API”. Three sources of knowledge the model needs to reconcile:

  • Project conventions - in CLAUDE.md (“every endpoint has a test, every Pydantic model lives in models/, for auth we use deps/auth.py”).
  • Workflow - in a skill (“test first, then implementation, then coverage check”).
  • Current library API - in context7 (“how does Depends work in FastAPI 0.115? Has BackgroundTasks changed?”).

Each of these three sources covers a different gap. CLAUDE.md says how we do it. The skill says in what order. Context7 says with what API. None of them works alone. Together - as you see in well-configured Claude Code setups - they produce work that not only runs, but fits the project and uses current syntax.

If you want the wider picture of where this all sits, I described it in Holak’s scale - context7 lives on layer 8 (“tools and MCP”), not layer 7 (“skills”). The distinction matters: a skill modifies the model’s behaviour; an MCP gives it access to a source.

The verdict - default on

For context7, the conclusion is unusually simple. Three lines in .mcp.json, no API key, no cost, no per-project configuration. For anyone using Claude Code to work with code, leaving it on by default delivers concrete wins:

  • Fewer API hallucinations, because the model gets an up-to-date source.
  • Fewer write-fix-write cycles, because the docs in the model’s context are complete.
  • Shorter migrations and faster onboarding into new libraries.
  • Fewer stalls on niche, rarely used APIs.

In my setup context7 has been on globally for about a month. There’s been no situation where I had to turn it off because it got in the way. There’s been a series of situations where, without it, I’d have wasted half an hour fighting the model’s stale knowledge.

One thing to keep in mind: context7 doesn’t read your mind. You still need to know that you’re on Astro 6, not 5; that FastAPI is 0.115, not 0.104. In an ideal world, Claude Code would read package.json/requirements.txt itself and pass the version into context7. In reality, you often have to say it in the prompt: “I’m on React 19, check context7”. Once that one habit sticks, context7 works in the background without you thinking about it. And that might be the best recommendation you can give a developer tool.