M

MCPUNK代码块

@jurasofish/mcpunk
0 Stars 346 次浏览 jurasofish 更新于 2026-08-23

通过智能代码搜索与代码库进行对话,无需嵌入式方法,而是将文件分解为逻辑块,为大型语言模型(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 使你能够通过对话来探索和理解代码库。它的工作原理如下:

  1. 将文件分解成逻辑块(函数、类、Markdown部分)
  2. 给LLM提供搜索和查询这些块的工具
  3. 让LLM找到回答问题所需的特定代码

无需嵌入,无需复杂的配置 - 只需清晰可审计的搜索,你可以看到并引导。
它与Claude Desktop或任何其他MCP客户端配合使用效果非常好。

GitHub仓库

基于以下考虑构建

  • 上下文为王 - LLM只有在提供了适当的上下文时才能表现出色。
  • 上下文是宝贵的 - LLM需要上下文,但它们不能处理过多的信息。
    这是一个悲剧!MCPunk是一种RAG,它天生就能为LLM提供上下文提示,
    使LLM能够真正聚焦于相关的内容。
  • 人在环中 - 可以清楚地看到LLM考虑了哪些数据以及它是如何找到这些数据的。
    可以在聊天中跳转并指导事情向你想要的方向发展。

设置

这是针对Claude Desktop的说明,但MCPunk可以在任何使用MCP的地方使用。

  1. 安装uv
  2. 将下面的代码片段放入你的claude_desktop_config.json
    (关于claude_desktop_config.json的详细信息,包括位置)
  3. 重启Claude Desktop,你应该会在一小段时间后看到可用的工具,如下面的屏幕截图所示
  4. 开始聊天:“嘿,伙计,你能设置~/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:
    1. 首先,用户需要通过使用 configure_project 工具将 mcpunk 配置为与其项目一起工作
    2. 查看最近检出的分支(以确定要进行差异比较的对象)
    3. 然后,获取当前分支(HEAD)与参考分支之间的差异
      这将显示当前分支(HEAD)与指定参考分支之间的差异。
      ref 参数应是你想要比较的基础分支的名称(如 "main" 或 "develop")。
  • [User] 干得好伙计!

PR 审查

  • [user] 嘿伙计,你能帮我设置 ~/git/mcpunk 仓库,并查看当前分支与 scratch/1.5 分支的差异吗?
  • [Claude] 设置 ~/git/mcpunk 并调用 diff_with_ref 对于 ref scratch/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 速成课程

请参阅:

Roaming RAG 的要点是:

  1. 将内容(代码库、PDF 文件等)分解成“块”。每个块是一个“小”逻辑项,比如一个函数、Markdown 文档中的一个部分或代码文件中的所有导入。
  2. 提供给 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。要添加一个分块器:

可以实现某种插件系统,让模块宣传它们有 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
  • 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 工作流。

相关 MCP 服务