MCPUNK代码块
通过智能代码搜索与代码库进行对话,无需嵌入式方法,而是将文件分解为逻辑块,为大型语言模型(LLM)提供搜索这些块的工具,并让它找到回答问题所需的特定代码。
MCP 服务配置
复制以下 JSON 到 OPClaw 或其他 MCP 客户端的配置文件中即可使用
{
"mcpServers": {
"MCPunk": {
"args": [
"--from",
"/Users/michael/git/mcpunk",
"--no-cache",
"mcpunk"
],
"command": "/Users/michael/.local/bin/uvx"
}
}
}
该服务需要配置环境变量:MCPUNK_INCLUDE_CHARS_IN_RESPONSE
服务介绍
MCPunk 🤖
与你的代码库进行对话,无需嵌入,通过给LLM提供智能搜索代码的工具。
MCPunk 使你能够通过对话来探索和理解代码库。它的工作原理如下:
- 将文件分解成逻辑块(函数、类、Markdown部分)
- 给LLM提供搜索和查询这些块的工具
- 让LLM找到回答问题所需的特定代码
无需嵌入,无需复杂的配置 - 只需清晰可审计的搜索,你可以看到并引导。
它与Claude Desktop或任何其他MCP客户端配合使用效果非常好。
基于以下考虑构建
- 上下文为王 - LLM只有在提供了适当的上下文时才能表现出色。
- 上下文是宝贵的 - LLM需要上下文,但它们不能处理过多的信息。
这是一个悲剧!MCPunk是一种RAG,它天生就能为LLM提供上下文提示,
使LLM能够真正聚焦于相关的内容。 - 人在环中 - 你可以清楚地看到LLM考虑了哪些数据以及它是如何找到这些数据的。
你可以在聊天中跳转并指导事情向你想要的方向发展。
设置
这是针对Claude Desktop的说明,但MCPunk可以在任何使用MCP的地方使用。
- 安装uv
- 将下面的代码片段放入你的
claude_desktop_config.json中
(关于claude_desktop_config.json的详细信息,包括位置) - 重启Claude Desktop,你应该会在一小段时间后看到可用的工具,如下面的屏幕截图所示
- 开始聊天:“嘿,伙计,你能设置~/git/mcpunk项目并告诉我python文件是如何被分块的吗?”
("command": "uvx",可能不起作用,你可能需要使用例如"command": "/Users/michael/.local/bin/uvx",)
{
"mcpServers": {
"MCPunk": {
"command": "uvx",
"args": ["mcpunk"]
}
}
}

使用示例
回答关于你的代码库的问题
- [User] 嘿伙计,你能帮我设置 ~/git/mcpunk 仓库吗?然后帮我理解 mcpunk 的用户如何获取当前检出分支的 git diff
- [Claude] 调用
configure_project - [Claude] 调用
list_all_files_in_project - [Claude] 调用
find_files_by_chunk_content - [Claude] ...总共调用了 21 次 MCPunk 工具。
- [Claude] 现在我明白了 mcpunk 中 git diff 功能是如何工作的。让我总结一下用户如何获取当前检出分支的 git diff:
若要在使用 mcpunk 配置的仓库中获取当前检出分支的 git diff:- 首先,用户需要通过使用 configure_project 工具将 mcpunk 配置为与其项目一起工作
- 查看最近检出的分支(以确定要进行差异比较的对象)
- 然后,获取当前分支(HEAD)与参考分支之间的差异
这将显示当前分支(HEAD)与指定参考分支之间的差异。
ref 参数应是你想要比较的基础分支的名称(如 "main" 或 "develop")。
- [User] 干得好伙计!
PR 审查
- [user] 嘿伙计,你能帮我设置 ~/git/mcpunk 仓库,并查看当前分支与
scratch/1.5分支的差异吗? - [Claude] 设置 ~/git/mcpunk 并调用
diff_with_ref对于 refscratch/1.5 - [Claude] 我看到你做了几个更改,主要是添加了一个新的测试文件
tests/test_git_analysis.py... - [user] 这些改动如何融入到整个代码库中?
- [Claude] 执行了 5 次工具调用来按块列出文件、列出块、获取块详细信息
- [Claude] 我明白了 - 该代码解析 git reflog 输出来跟踪最近检出的分支。主要函数 get_recent_branches 接受一个仓库路径,并返回最后 N 个被检出的分支,使用 _branches_from_reflog 作为辅助函数来解析原始的 reflog 输出。
- [User] 如果你很急,需要指导某人审查这项工作,你会让他们关注哪些方面?请概述具体的工作部分
- [Claude]
_branches_from_reflog中的split("to ")[-1]看起来很脆弱- 测试数据仅展示了简单的分支名称,如果有空格或特殊字符怎么办?
- example_reflog 是否代表真实的 git reflog 输出?
- 我们是否针对实际的 git 行为进行了测试?
- [User] 你是最棒的!
跨多个代码库工作
你可以要求你的大语言模型设置多个项目,并且它可以在这些项目之间自由查询。如果一个项目依赖另一个项目,而它们位于不同的仓库中,这非常方便。在这种情况下,大语言模型应该能够通过导入识别这一点。
MCPunk 是什么及其他背景
MCPunk 是一个提供工具的 MCP 服务器,用于
- 配置一个项目,这是一个文件目录。配置后,文件将被分割成逻辑块。MCPunk 是为代码设计的,但实际上它可以应用于任何文档,甚至如果你想的话也可以应用于图像。
- 在项目中搜索包含特定文本的文件
- 在文件中搜索包含特定文本的块
- 查看特定块的全部内容
此外,它还提供了一些内置的分块器。其中最成熟的是 Python 分块器。
MCPunk 不必用于对话。例如,它可以作为 CI 管道中的代码审查的一部分使用。它实际上是一种通用的 RAG。
sequenceDiagram
participant User
participant Claude as Claude Desktop
participant MCPunk as MCPunk Server
participant Files as File System
Note over User,Files: Setup Phase
User->>Claude: Ask question about codebase
Claude->>MCPunk: configure_project(root_path, project_name)
MCPunk->>Files: Scan files in root directory
Note over MCPunk,Files: Chunking Process
MCPunk->>MCPunk: For each file, apply appropriate chunker:
MCPunk->>MCPunk: - PythonChunker: functions, classes, imports
MCPunk->>MCPunk: - MarkdownChunker: sections by headings
MCPunk->>MCPunk: - VueChunker: template/script/style sections
MCPunk->>MCPunk: - WholeFileChunker: fallback
MCPunk->>MCPunk: Split chunks >10K chars into parts
MCPunk-->>Claude: Project configured with N files
Note over User,Files: Navigation Phase<br>(LLM freely uses all these tools repeatedly to drill in)
Claude->>MCPunk: list_all_files_in_project(project_name)
MCPunk-->>Claude: File tree structure
Claude->>MCPunk: find_files_by_chunk_content(project_name, "search term")
MCPunk-->>Claude: Files containing matching chunks
Claude->>MCPunk: find_matching_chunks_in_file(project_name, file_path, "search term")
MCPunk-->>Claude: List of matching chunk IDs in file
Claude->>MCPunk: chunk_details(chunk_id)
MCPunk-->>Claude: Full content of specific chunk
Claude->>User: Answer based on relevant code chunks
Note over User,Files: Optional Git Analysis
Claude->>MCPunk: list_most_recently_checked_out_branches(project_name)
MCPunk->>Files: Parse git reflog
MCPunk-->>Claude: List of recent branches
Claude->>MCPunk: diff_with_ref(project_name, "main")
MCPunk->>Files: Generate git diff
MCPunk-->>Claude: Diff between HEAD and reference
Roaming RAG 速成课程
请参阅:
- https://arcturus-labs.com/blog/2024/11/21/roaming-rag--make-_the-model_-find-the-answers/
- https://simonwillison.net/2024/Dec/6/roaming-rag/
Roaming RAG 的要点是:
- 将内容(代码库、PDF 文件等)分解成“块”。每个块是一个“小”逻辑项,比如一个函数、Markdown 文档中的一个部分或代码文件中的所有导入。
- 提供给 LLM 工具来搜索块。MCPunk 通过提供工具来搜索包含特定文本的块的文件,并列出特定块的全部内容来实现这一点。
与更传统的“向量搜索”RAG 相比:
- LLM 必须深入查找块,并自然地意识到它们的更广泛上下文(如它们所在的文件)
- 块应该始终是连贯的,比如一个完整的函数。
- 你可以确切地看到 LLM 正在搜索什么,如果搜索效果不佳通常很明显,你可以通过建议改进的搜索词来帮助它。
- 需要精确的搜索匹配。MCPunk 并不提供任何形式的模糊搜索。
块
块是文件的一个子部分。例如,
- 单个 Python 函数
- Markdown 部分
- 从 Python 文件中提取的所有导入
块由 分块器 从文件创建,MCPunk 自带了一些内置的分块器。
当在 MCPunk 中设置项目时,它会遍历所有文件并应用第一个适用的分块器。然后,LLM 可以使用工具来 (1) 查询包含特定文本块的文件,(2) 查询特定文件中的所有块,以及 (3) 获取块的全部内容。
这个基本基础使 Claude 能够通过从广泛的文件搜索开始,逐步缩小到相关区域,从而有效地导航相对较大的代码库。
内置的分块器:
PythonChunker将内容分块为类、函数、文件级导入和文件级语句(例如全局变量)。适用于以.py结尾的文件。VueChunker将内容分块为 'template', 'script', 'style' 块 - 或者任何顶级<blah>....</blah>项。适用于以.vue结尾的文件。MarkdownChunker将内容按标题分块为 markdown 部分。适用于以.md结尾的文件。WholeFileChunker是一个后备分块器,它将整个文件作为一个块处理。适用于任何文件。
任何超过 10k 字符长的块(可配置)将自动分割成多个块,名称后缀为 part1, part2 等。这有助于避免超出上下文限制,同时仍然允许合理地浏览块。
自定义分块器
每种类型的文件(例如 Python 与 C)都需要一个自定义分块器。MCPunk 提供了一些内置的分块器。如果没有特定的分块器匹配某个文件,则使用默认分块器,该分块器将整个文件放入一个块中。
当前建议添加分块的方式是 fork 该项目并添加它们,并按照 开发 运行 MCPunk。要添加一个分块器:
- 在 file_chunkers.py 中继承
BaseChunker添加它。 - 在 file_breakdown.py 的
ALL_CHUNKERS中添加它。
可以实现某种插件系统,让模块宣传它们有 MCPunk 可使用的自定义分块器,就像 pytest 的插件系统一样,但目前没有计划实施这个功能(除非有人想做)。
限制
- 有时 LLM 在搜索方面表现不佳。例如,搜索 "dependency" 时会遗漏 "dependencies" 等术语。可以考虑对这些词进行词干提取。
- 有时 LLM 会尝试查找特定的关键代码段,但未能找到,然后继续执行而不承认其上下文意识有限。
- “大型”项目尚未经过充分测试。包含约 1000 个 Python 文件、总计约 250k 行代码的项目工作得很好。设置项目大约需要 5 秒。随着代码库规模的增加,初始分块所需的时间也会增加,并且可能需要更复杂的搜索。代码通常不是针对大规模代码库编写的——你会看到诸如所有数据都存储在内存中、通过遍历所有数据来搜索等做法,这些都是亟需基本优化的地方。
- 对于小型项目,可能更适合将所有代码连接起来并直接放入上下文中。只有当这样做不切实际时,MCPunk 才真正适用。
- 在某些情况下,显然最好让 LLM 获取整个文件,而不是让它一次挑选一个块。MCPunk 没有这种机制。实际上,我发现这并不是一个大问题。
配置
各种配置可以通过以 MCPUNK_ 为前缀的环境变量进行设置。
有关可用选项,请参阅 settings.py - 这些设置通过 Pydantic Settings 从环境变量中加载。
例如,要配置 include_chars_in_response 选项:
{
"mcpServers": {
"MCPunk": {
"command": "uvx",
"args": ["mcpunk"],
"env": {
"MCPUNK_INCLUDE_CHARS_IN_RESPONSE": "false"
}
}
}
}
路线图与开发状态
MCPunk 已经接近功能完整。
它还没有得到广泛使用,作为用户,你可能会遇到一些错误或粗糙的地方。欢迎在 https://github.com/jurasofish/mcpunk/issues 提交错误报告。
路线图想法
- 添加一系列提示来帮助使用 MCPunk。没有真正的“向外星人解释如何制作煎饼”类型的提示,事情会显得有些平淡。
- 在提取 Python 模块级语句时包含模块级别的注释。
- 可能实现搜索时的词干提取
- 改变整个“项目”概念,使其不需要实际存在的文件 - 这将允许项目中有“虚拟”文件。
- 考虑将文件从路径改为 URI,这样可以是
file://.../http[s]:///gitdiff://或其他任意 URI
- 考虑将文件从路径改为 URI,这样可以是
- Git 差异的分块。目前有一个工具可以获取整个差异,这可能会非常大。相反,可以将工具改为
add_diff_to_project并将文件放在gitdiff://URI 或某个虚拟路径下。 - 项目的缓存,这样每次重启 MCP 客户端时不必重新解析所有文件。这可能比较棘手,因为代码块中的更改会使缓存失效。由于在我的用例中速度并不是特别慢,因此可能不会优先考虑。
- 允许用户提供自定义代码来进行分块,类似于 pytest 插件
- 可以使用类似 tree sitter 的东西来实现更通用的分块器
- 跟踪发送/接收的字符,理想情况下按聊天记录
- 按聊天记录的状态、日志等
开发
请参阅 run_mcp_server.py。
如果你像下面这样设置了 claude 桌面应用,那么你可以重新启动它来查看你在本地仓库中对 MCPunk 所做的最新更改。
{
"mcpServers": {
"MCPunk": {
"command": "/Users/michael/.local/bin/uvx",
"args": [
"--from",
"/Users/michael/git/mcpunk",
"--no-cache",
"mcpunk"
]
}
}
}
测试、代码检查、持续集成
请参阅 Makefile 和 GitHub Actions 工作流。