Codebase Memory MCP:为编程 Agent 构建结构化代码知识图谱
将代码解析为节点(组件/函数/Hook)和边(CALLS/IMPORTS/HTTP_CALLS)组成的知识图谱,Agent 可先查询结构再精准打开相关文件,减少重复索引开销。
完整中文译文
Why Codebase Memory MCP?
随着前端项目规模扩大,理解组件、hooks、stores、services 和 API 之间的关联关系对编码 Agent 而言愈发困难。Claude Code、Codex 或 Cursor 这类工具可能需要搜索并打开多个文件才能回答一个简单的问题。Codebase Memory MCP 通过构建项目的知识图谱,将这些关联关系预先存储起来,使 Agent 能够更快地理解代码库。
Read More: Personal blog
What is Codebase Memory MCP?
Codebase Memory MCP 是一个用于结构化代码库分析的 MCP 服务器。它对源代码进行索引,并将项目不同部分之间的关系存储为图结构。
GitHub repository: DeusData/codebase-memory-mcp
在一个前端项目中,图节点可以代表组件(components)、函数(functions)、hooks、模块(modules)和路由(routes),而边则描述了 CALLS(调用)、IMPORTS(导入)和 HTTP_CALLS(HTTP 调用)等关系。
Codebase
↓
Parse & Index
↓
Knowledge Graph
↓
MCP
↓
Coding Agent
Agent 无需在每个任务中从头开始探索代码库,而是可以先查询其结构,然后仅打开实际相关的文件。
Example in a React project
设想一个 React 商店页面的部分结构如下:
src/
├── components/
│ └── AddToCartButton.tsx
├── hooks/
│ └── useCart.ts
├── stores/
│ └── cartStore.ts
└── services/
└── cartApi.ts
加入购物车组件:
import { useCart } from "@/hooks/useCart";
type Props = {
productId: string;
};
export function AddToCartButton({ productId }: Props) {
const { addItem } = useCart();
return (
<button onClick={() => addItem(productId)}>
Add to cart
</button>
);
}
import { useCartStore } from "@/stores/cartStore";
import { addCartItem } from "@/services/cartApi";
export function useCart() {
const addLocalItem = useCartStore((state) => state.addItem);
async function addItem(productId: string) {
addLocalItem(productId);
await addCartItem(productId);
}
return { addItem };
}
export async function addCartItem(productId: string) {
return fetch("/api/cart", {
method: "POST",
body: JSON.stringify({ productId }),
});
}
对开发者而言,执行流程很容易追溯。但首次查看该代码库的 Agent 仍需发现这些关联关系。Codebase Memory 可以将它们以结构化方式存储:
AddToCartButton
↓
useCart.addItem
↓
cartStore.addItem
↓
addCartItem
↓
POST /api/cart
像"加入购物车的流程是什么?"或"谁调用了 addItem?"这样的问题,无需先对整个项目进行广泛搜索就能调查。
What role does MCP play?
Codebase Memory 本身不是 LLM 或编码 Agent。MCP(Model Context Protocol)是 Agent 访问 Codebase Memory 工具的接口。
整体流程如下:
Developer
↓
Coding Agent
↓
MCP Tool
↓
Codebase Memory
↓
Knowledge Graph
↓
Structured Result
例如,如果你问:
What calls addItem?
Agent 可以使用图工具追踪入站路径,然后用自然语言解释结果。
What does the knowledge graph store?
知识图谱将项目转化为节点以及节点之间的关系。
ProductPage
│
▼
ProductDetails
│
▼
AddToCartButton
│
▼
useCart
│
▼
addCartItem
│
▼
POST /api/cart
在大型项目中,这个图可以保留数千个符号之间的关系,并帮助 Agent 在读取源文件之前缩小问题范围。
How does Codebase Memory analyze code?
该工具使用 Tree-sitter 来解析源代码。Tree-sitter 不将文件视为纯文本,而是将它们的语法公开为 AST(抽象语法树)。
import { getUser } from "./userApi";
export async function loadProfile() {
return getUser();
}
文本搜索可以找到字符串 getUser,而结构化分析可以识别以下关系:
loadProfile
│ CALLS
▼
getUser
getUser
│ IMPORTED FROM
▼
./userApi
这在 TypeScript 和 React 项目中尤为重要,因为架构很大程度上是由导入、组件、hooks 和函数调用塑造的。
设想一个 Next.js 产品页面:
import { getProduct } from "@/services/productApi";
import { ProductDetails } from "@/components/ProductDetails";
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const product = await getProduct(id);
return <ProductDetails product={product} />;
}
而 ProductDetails 渲染了多个其他组件:
export function ProductDetails({ product }) {
return (
<>
<ProductGallery images={product.images} />
<ProductPrice price={product.price} />
<AddToCartButton productId={product.id} />
</>
);
}
Agent 现在可以调查以下结构化问题:
- ProductDetails 在哪里被使用?
- 什么路径连接了 ProductPage 和 AddToCartButton?
- 项目的哪些部分调用了 getProduct?
- 如果 AddToCartButton 发生变化,可能会影响什么?
这些正是图结构比纯文本搜索更有价值的问题类型。
Important Codebase Memory MCP tools
Codebase Memory 暴露了多个 MCP 工具用于索引、搜索和分析图。
分析代码库并构建初始项目图。
查找存储在图中的函数、类、模块和其他符号。
追踪调用路径,适用于"什么调用了这个函数?"或"这个函数调用了什么?"等问题。
提供项目架构、包、路由、入口点和重要代码区域的高级视图。
检查 Git 变更,帮助 Agent 识别修改的大致影响范围。
返回特定符号的源代码,使 Agent 无需始终读取整个文件。
直接搜索索引后的源代码。
对知识图谱执行更高级的查询。
Impact analysis in frontend projects
Codebase Memory 的一个有用应用是查找变更的影响范围。
设想你的设计系统中有一个共享按钮:
<Button loading={true}>Save</Button>
你想将其 API 改为:
<Button status="loading">Save</Button>
如果该组件在数十个屏幕中被使用,重构前你需要知道谁依赖它。
Button
├── LoginForm
├── CheckoutForm
├── ProductCard
├── DeleteModal
└── ProfileSettings
知识图谱可以帮助 Agent 查找用法和依赖路径,从而使变更前的影响范围更加清晰。
Codebase Memory vs. grep
grep 和普通搜索基于文本操作:
grep -R "addItem" src/
这会找到包含字符串 addItem 的文件,但不一定会告诉你哪个符号连接到哪个其他符号。
区别可以总结如下:
grep
↓
"Where does the text addItem appear?"
Knowledge Graph
↓
"What calls addItem?"
"What does addItem call?"
"What path connects a component to addItem?"
因此 Codebase Memory 并不替代文本搜索,而是在其基础上增加了一层结构化能力。
Codebase Memory vs. RAG
使用 RAG 时,源代码通常被分割成块,并使用嵌入向量来检索与问题语义相关的代码。
Source Code
↓
Chunks
↓
Embeddings
↓
Vector Search
↓
Relevant Code
知识图谱解决的是不同的问题:
Component
↓
Hook
↓
Store
↓
Service
↓
API
简而言之,RAG 帮助回答"哪些代码可能与我的问题相关?",而图帮助回答"这些代码部分是如何连接的?"
Reducing context usage
编码 Agent 在探索代码库时通常会将许多文件加载到模型上下文中。文件越多,消耗的 token 越多,不相关信息也在争夺注意力。
Codebase Memory 可以改变这个流程:
Whole Repository
↓
Knowledge Graph
↓
Relevant Symbols
↓
Relevant Files
↓
LLM Context
Agent 可以先用图缩小问题范围,然后只读取实际需要的源代码。
Keeping the graph updated
知识图谱只有在与代码库保持一致时才有用。Codebase Memory 支持项目变更,因此初始索引之后,图数据可以随文件变化而更新。
Initial Index
↓
Knowledge Graph
↓
Code Changes
↓
Incremental Update
↓
Updated Graph
这意味着 Agent 不需要在每次小修改后从头开始探索整个代码库。
When does Codebase Memory make sense?
- 中大型 React、Next.js 或 TypeScript 项目
- 包含大量组件、hooks、stores 和 services 的代码库
- 频繁使用编码 Agent 的团队
- 依赖和调用链追踪困难的代码库
- 大型设计系统和组件库
- 重构前需要影响分析的项目
- Agent 花太多时间搜索和打开文件的工作流
对于只有几个文件的小型项目,索引和维护图可能几乎没什么价值。随着代码库的增长,拥有一个结构化映射会变得有用得多。
Codebase Memory MCP 在编码 Agent 和代码库之间增加了一层结构化记忆。Agent 无需在每个任务中重新发现文件关联,而是可以查询持久化的知识图谱以获取函数、调用链、依赖、路由和变更的大致影响。
对于大型前端项目,这意味着 Component → Hook → Store → Service → API 这样的流程变得可以直接查询,帮助 Agent 在将大量文件加载到上下文之前就知道该去哪里查找。