Context7,让Cursor智能10倍?

2,347 阅读5分钟

最近,Context7这个MCP有点火,网上到处都在说 "Context7 Solves LLMs' Biggest Flaw" , "Context7 Will Change AI Coding" , "Context7 Makes Cursor 10x Smarter" 。所以这个玩意真的这么神奇么,底层到底是个啥?

Context7是啥

根据官方描述,Context7将 最新的 特定版本的文档及代码片段 等信息直接放到prompt中,大模型可参考最新的信息来编写代码,而不会受到过期知识的影响。

所以简单来说,Context7就是让大模型在回答问题前,强制搜一下最新的信息,补充一下上下文,然后再根据补充后的信息进行输出。(那不就是一个web search嘛)

简单尝试

安装步骤就不写了,可以参考 github.com/upstash/con…

问个简单的问题,React19中新推出了useOptimistic(具体这个API是干啥的不重要),对比一下是否使用Context7对结果的影响。

  • 不使用Context7:Claude3.7认为这个API是React18中还在实验性的Hook。(当然了,Claude3.7训练完成的时候这个Hook还在实验中)

  • 使用Context7:Claude3.7经过了两次MCP调用后,查到这是在React19中的Hook。

对于这个问题,显然使用了Context7之后,大模型给的答案更新。(虽然这个Hook在React18实验版和React19里的用法差不多,预期也不会对结果产生很大影响,但是可能对于其他迭代较快的语言或者框架来说,获取更新的知识意味着大模型能更好的帮我们解决问题,毕竟信息肯定越新越好)

浅看下代码

浅看一下Context7 MCP的代码,其主要提供了两个tool

  • resolve-library-id:先让大模型判断下需要查询哪个library,在返回结果里找到最相关的library id。(内部主要是调用了API接口查询,再格式化返回给大模型)
server.tool(
  "resolve-library-id",
  `Resolves a package/product name to a Context7-compatible library ID and returns a list of matching libraries.`,
  {
    libraryName: z
      .string()
      .describe("Library name to search for and retrieve a Context7-compatible library ID."),
  },
  async ({ libraryName }) => {
    // 调用API查询最相关的library
    const searchResponse = await searchLibraries(libraryName);
    
    // ... 省略多个异常处理
    
    // 格式化处理
    const resultsText = formatSearchResults(searchResponse);

    return {
      content: [
        {
          type: "text",
          text: `Available Libraries (top matches):
----------
${resultsText}`,
        },
      ],
    };
  }
);

实际大模型调用的输入输出如下:

// 输入
{
  `libraryName`: `React`
}
// 输出
Available Libraries (top matches):

Each result includes:
- Library ID: Context7-compatible identifier (format: /org/repo)
- Name: Library or package name
- Description: Short summary
- Code Snippets: Number of available code examples
- Trust Score: Authority indicator

For best results, select libraries based on name match, trust score, snippet coverage, and relevance to your use case.

----------

- Title: React-XR
- Context7-compatible library ID: /pmndrs/xr
- Description: 🤳 VR/AR for react-three-fiber
- Code Snippets: 68
- Trust Score: 9.6
----------
- Title: React95
- Context7-compatible library ID: /react95/react95
- Description: A React components library with Win95 UI
- Code Snippets: 18
- Trust Score: 7.8
----------
- Title: React
- Context7-compatible library ID: /reactjs/react.dev
- Description: The React documentation website
- Code Snippets: 2059
- Trust Score: 9
----------
- Title: React Flow
- Context7-compatible library ID: /xyflow/xyflow
- Description: React Flow | Svelte Flow - Powerful open source libraries for building node-based UIs with React (https://reactflow.dev) or Svelte (https://svelteflow.dev). Ready out-of-the-box and infinitely customizable.
- Code Snippets: 21
- Trust Score: 9.5
----------
// ...以下省略更多内容

可以看到,在查询React相关的library时,API会返回多个相关的内容,包含Title、library ID、Description、Code Snippets、Trust Score。大模型可从返回的多个相关library中,找一个和用户提问最相关的,记录下library ID(在本Case中,大模型会记录/reactjs/react.dev),再继续调用下一个工具。

  • get-library-docs:根据library ID和用户查询的关键词,查询相关的代码片段
server.tool(
  "get-library-docs",
  "Fetches up-to-date documentation for a library. You must call 'resolve-library-id' first to obtain the exact Context7-compatible library ID required to use this tool.",
  {
    context7CompatibleLibraryID: z
      .string()
      .describe(
        "Exact Context7-compatible library ID (e.g., 'mongodb/docs', 'vercel/nextjs') retrieved from 'resolve-library-id'."
      ),
    topic: z
      .string()
      .optional()
      .describe("Topic to focus documentation on (e.g., 'hooks', 'routing')."),
    tokens: z
      .preprocess((val) => (typeof val === "string" ? Number(val) : val), z.number())
      .transform((val) => (val < DEFAULT_MINIMUM_TOKENS ? DEFAULT_MINIMUM_TOKENS : val))
      .optional()
      .describe(
        `Maximum number of tokens of documentation to retrieve (default: ${DEFAULT_MINIMUM_TOKENS}). Higher values provide more context but consume more tokens.`
      ),
  },
  async ({ context7CompatibleLibraryID, tokens = DEFAULT_MINIMUM_TOKENS, topic = "" }) => {
    // Extract folders parameter if present in the ID
    let folders = "";
    let libraryId = context7CompatibleLibraryID;

    if (context7CompatibleLibraryID.includes("?folders=")) {
      const [id, foldersParam] = context7CompatibleLibraryID.split("?folders=");
      libraryId = id;
      folders = foldersParam;
    }
    // 根据topic,查询相关代码片段
    const documentationText = await fetchLibraryDocumentation(libraryId, {
      tokens,
      topic,
      folders,
    });

    if (!documentationText) {
      return {
        content: [
          {
            type: "text",
            text: "Documentation not found or not finalized for this library. This might have happened because you used an invalid Context7-compatible library ID. To get a valid Context7-compatible library ID, use the 'resolve-library-id' with the package name you wish to retrieve documentation for.",
          },
        ],
      };
    }

    return {
      content: [
        {
          type: "text",
          text: documentationText,
        },
      ],
    };
  }
);

实际大模型调用的输入输出如下:

// 输入
{
  `topic`: `useOptimistic`,
  `tokens`: 4000,
  `context7CompatibleLibraryID`: `/reactjs/react.dev`
}
// 响应
TITLE: Initializing useOptimistic Hook in Component - JavaScript
DESCRIPTION: Imports the `useOptimistic` hook and demonstrates its basic usage within a functional React component (`AppContainer`), showing how to define the `updateFn` to merge the current state with an optimistic value. Requires importing `useOptimistic` from 'react'.
SOURCE: https: // github.com / reactjs / react.dev / blob / main / src / content / reference / react / useOptimistic.md#_snippet_1

LANGUAGE: js
CODE:
```
import { useOptimistic } from 'react';

function AppContainer() {
  const [optimisticState, addOptimistic] = useOptimistic(
    state,
    // updateFn
    (currentState, optimisticValue) => {
      //  merge  and  return  new state
      //  with optimistic value
    }
  );
}
```

----------------------------------------

TITLE: Implementing Optimistic Form Updates with useOptimistic - React/JavaScript
DESCRIPTION: Demonstrates a full implementation of optimistic UI updates using `useOptimistic` for sending messages via a form. It shows how to update the UI immediately upon submission (`addOptimisticMessage`), reset the form, perform the asynchronous action (`sendMessageAction`) using `startTransition`, and manage the state with `useState`. Requires `react`, `useOptimistic`, `useState`, `useRef`, `startTransition`, and a message delivery action.
SOURCE: https: // github.com / reactjs / react.dev / blob / main / src / content / reference / react / useOptimistic.md#_snippet_2

LANGUAGE: js
CODE:
```
import { useOptimistic, useState, useRef, startTransition } from "react";
import { deliverMessage } from "./actions.js";

function Thread({ messages, sendMessageAction }) {
  const formRef = useRef();
  function formAction(formData) {
    addOptimisticMessage(formData.get("message"));
    formRef.current.reset();
    startTransition(async () => {
      await sendMessageAction(formData);
    });
  }
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      {
        text: newMessage,
        sending: true
      },
      ...state,
    ]
  );

  return (
    <>
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Send</button>
      </form>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "Hello there!", sending: false, key: 1 }
  ]);
  async function sendMessageAction(formData) {
    const sentMessage = await deliverMessage(formData.get("message"));
    startTransition(() => {
      setMessages((messages) => [{ text: sentMessage }, ...messages]);
    })
  }
  return <Thread messages={messages} sendMessageAction={sendMessageAction} />;
}
```

实际Context7的Server端在/reactjs/react.dev文档中找到了和useOptimistic相关的代码片段,并标明TITLE、DESCRIPTION、SOURCE、LANGUAGE、CODE,大模型可根据文档返回的内容,来决定代码具体的使用方式。

小结:Context7 MCP中主要有两个方法

  • resolve-library-id:查找某个技术栈/框架对应的文档ID
  • get-library-docs:根据文档ID和具体topic,查询相关的代码片段和说明

在调用MCP后,大模型有了更新更准确的文档说明,再返回给用户

文档如何切片

从Context7 MCP端的代码来看,其本质和web search功能差不多,强制让大模型在回答问题前,先查询一下最新的文档。为了让查询的效果更好,Context7的Server端维护了文档切片索引

context7.com/ 可以看到,其官方维护了10000+个library的文档切片,大家也可以手动添加贡献github仓库,官方会从仓库中提取.md等相关说明文件,解析其中的代码片段,构建索引,方便后续的查询。

我们手动查一下刚刚使用的useOptimistic试试

context7.com/reactjs/rea…

可以看到每个代码片段会对应有来源(也就是library官方仓库里的md文件)。并为每一个代码片段加上对应的描述。

github.com/reactjs/rea…

在实际使用时,Server还会给每个代码片段添加Trust Score,来标识此代码的置信度。虽然官方没说这个值是怎么算出来的,推测有可能和代码相关度、仓库活跃度、文档完整性等多个方面加权得到。(即使后面这个值的算法有修改,大家也不用重新安装MCP)

由此可见,Context7查询准确的前提是:对应的 Github 仓库里得有 md 说明文档,如果一个框架只有代码实现,但没有使用文档,那Context7也无能为力了。

总结

Context7 通过文件类型过滤和切片机制,将 GitHub 上的文档转换为代码片段集合。其切片机制综合考虑了文件大小、文档结构和代码块分布,在保持语义完整性的同时,实现了高效的内容分块和索引。

Context7 MCP强制大模型在回答问题前,先查找相关主题最新的代码片段,并填充到上下文,综合用户问题,提供更准确、更新的代码辅助体验。


参考文档

upstash.com/blog/contex…

github.com/upstash/con…

context7.com/