mcpField
M
MCP CCPP Project Indexer

MCP CCPP Project Indexer

本地服务
github.com/walti1972开发工具104 周前更新

关于 MCP CCPP Project Indexer

MCP CCPP Project Indexer 为大型 C++ 项目构建确定性的文件、符号、源码范围和 C++20 模块索引,供 AI 辅助导航。它向编码 Agent 提供精简的定位信息和可核查的原始源码,不声称进行语义分析。

主要功能

  1. 01符号与声明查询
  2. 02读取精确源码范围
  3. 03映射 C++20 模块与分区
  4. 04将变更片段关联到符号
  5. 05增量更新索引
  6. 06可选 TUI 控制中心

适用场景

  1. 01在大型 C++ 代码库中查找并检查符号
  2. 02追踪 C++20 模块间的导入与导出
  3. 03根据索引声明审查变更片段

MCP 相关

它作为 MCP 服务运行,向 MCP 客户端提供索引查询和精确源码范围。客户端可定位符号、文件、模块和变更范围,再请求相关源码。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

mcp-cpp-project-indexer

mcp-cpp-project-indexer 是一个确定性的 C++ 源码范围索引器,适用于大型、模块密集型项目和基于 MCP 的 AI 代码导航。

它不是编译器、LSP 替代品、重构引擎、语义分析器,也不是调用图构建器。

它的工作很简单:

Find code. Read code. Do not guess code.

该索引器将 C++ 符号、文件和 C++20 模块映射到精确的源代码范围,让 AI 只需读取所需代码。

项目及相关 AI 编排工作的文档见 MEF Programming 主页,其中包括我们正在围绕 MCP 工具使用构建的持续中继/治理层。


30 秒概览

mcp-cpp-project-indexer 会在 C++ 源代码树上构建轻量级路由索引。MCP 客户端随后可以提出确定性问题,例如:

  • 这个函数/类/数据成员在哪里?
  • 应该读取哪个精确的源代码范围?
  • 哪个模块导入或导出这个分区?
  • 哪个变更区块与哪个已索引符号或数据范围相交?

索引器会返回元数据和原始源代码范围。它不会声称理解程序。AI 仍须阅读返回的源代码,并根据这些证据进行推理。

最简工作流:

User asks about Widget::OnScroll
-> find_symbol("Widget::OnScroll")
-> read_symbol(symbolId)
-> AI explains only what was visible in that source range

这样一来,只有在需要精确的源代码证据时,大型 C++ 项目才会进入提示词。


5 分钟快速入门

1. 克隆此仓库
git clone https://github.com/walti1972/mcp-cpp-project-indexer.git
cd mcp-cpp-project-indexer
2. 为你的 C++ 项目构建索引
python <indexer-root>\build_project_index.py `
  --root <project-root> `
  --output-root <project-root>\.mcp-cpp-project-indexer

生成的索引写入:

<project-root>\.mcp-cpp-project-indexer
3. 启动 MCP 服务
python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer

对于多个 MCP 客户端或长期运行的共享进程,请使用 HTTP 传输:

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --transport http `
  --http-host 127.0.0.1 `
  --http-port 8765
4. 将服务添加到你的 MCP 客户端

LM Studio 风格的最简配置:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "command": "python",
      "args": [
        "<indexer-root>\\code_index_mcp_server.py",
        "--project-root",
        "<project-root>",
        "--index-root",
        "<project-root>\\.mcp-cpp-project-indexer"
      ]
    }
  }
}
5. 请求精确源代码,而不是整个文件

适合作为首次请求的示例:

Find the symbol Widget::OnScroll, read its implementation, and explain only
what is visible in the source range.

预期工具调用路径:

find_symbol -> read_symbol -> source-grounded answer

为获得最佳效果,请将 prompt_template.md 中的规则提供给你的 AI。简而言之:

Use metadata to locate code. Read exact source ranges before explaining behavior.
Do not infer implementation behavior from metadata alone.

目录


仓库布局

根目录下的公开 readme.md 面向用户,介绍项目文档。实际的 Python 实现位于 src/ 下:

src/
  README.md
  indexer/
    build_project_index.py
    update_project_index.py
    cpp_project_index.py
  server/
    code_index_mcp_server.py
    server_ui/
  ui/
    indexer_tui.py
    indexer_control.py

根目录下的 build_project_index.py、code_index_mcp_server.py、 indexer_tui.py 和 update_project_index.py 等脚本是兼容性封装脚本。 它们会将执行路由到实现包,同时确保现有命令行和 MCP 客户端配置继续可用。

src/ 下各目录内的 README 使用项目索引器导览格式,让 Agent 能找到合适的起点,而无需将根目录下的公开 README 改成仅供机器使用的文档。


🚀 生产规模与性能

本项目用于真实的 C++ 代码库,而不只是玩具示例。近期的两次规模测试展示了其适用范围:

项目文件数源代码行数词法分析器令牌数符号数数据声明数C++20 模块数完整构建
匿名化商业 C++20 项目7,046979,6584,682,88297,92436,5513,75419.5s
Chromium 检出目录137,62230,792,607137,365,3992,327,255818,1880~24m 32s

这些数字取决于机器环境。Chromium 测试在一台高核心数工作站上使用了 --jobs 60,该工作站配备 Intel Xeon Silver 4316 系统、128 GB RAM 和企业级 NVMe SSD 存储。它是很有价值的公开压力测试,因为它覆盖了超大型、基于传统 include 的 C++ 代码库;匿名化商业项目则覆盖了密集的 C++20 模块和分区元数据。Chromium 测试还大规模验证了数据/成员索引器:修复嵌套模板 >> 深度处理后,公开压力测试发现了额外的 46,529 个数据声明和 66,866 个数据名称别名。

基于 SQLite 的查找索引让服务即使面对 Chromium 规模也能快速启动:MCP 服务可以立即启动,并在启动后保持约 200 MB RAM 的内存占用,而不必将数百万条符号/数据/名称记录加载到 Python 对象中。

它专为这样的工作流而设计:将 Codex 桌面应用或其他 MCP 客户端与 Visual Studio 导航结合使用,并在需要时参考 IDA Pro 等工具提供的二进制文件/反编译证据。

在一次测量过的工作流中,精确的源代码范围路由将读取的源代码文本从约 2,000 行减少到了 283 行,减少了 86%。


TUI 控制中心

日常使用时,索引器提供可选的鼠标操作 TUI。它将项目索引变成一个小型本地控制中心:

  • 在同一处启动 HTTP MCP 服务和监视器
  • 执行完整构建、增量更新、快速更新和模块映射重建
  • 实时查看服务、监视器、锁、进程、令牌和索引统计信息
  • 查看构建/更新日志,无需切换工具
  • 按需切换诊断文件部分,以深入查看解析器证据

TUI 控制中心

安装可选的 UI 依赖项,并指定项目/索引路径来启动控制中心:

pip install -r <indexer-root>\requirements-ui.txt

python <indexer-root>\indexer_tui.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --jobs 20 `
  --http-url http://127.0.0.1:8765

UI 是可选的;核心索引器仍然保持轻量依赖,也可以完全通过脚本或 MCP 客户端驱动。如需了解设置和键盘快捷键,请参阅控制中心。


💡 为什么使用这个工具?

大型 C++ 项目往往需要将整个文件加载到大模型中,才能查找一个函数、类、导入项或声明,因此成本很高。C++20 模块让问题更加棘手:许多 IDE/LSP 风格的工具仍难以处理大型模块图、分区、生成的 SDK 头文件以及特定于构建的配置。

这个索引器解决的是一个范围更窄但非常实际的问题:它为 AI 提供一张小型、确定性的路由图。AI 可以先定位相关符号、模块、文件或变更代码块,然后只读取任务所需的精确原始源代码行。

真实缺陷查找工作流示例:

Whole file context:     ~2000 source lines
On-demand source reads:  ~283 source lines
--------------------------------------------
Reduction:               ~86% less source text

📊 前后对比

标准 AI 代码导航使用 mcp-cpp-project-indexer
❌ AI 为查找符号而读取整个文件✅ AI 先获取精简元数据,再读取准确的源代码范围
❌ 上下文被无关的声明和实现填满✅ 上下文始终聚焦于相关代码行
❌ C++20 模块的使用方/导入项难以追踪✅ 模块导入、重新导出、分区和使用方均可直接查看
❌ 代码审查一开始需要手动扫描变更文件✅ 变更块会映射到已建立索引的符号/数据范围
❌ 工具可能让人误以为它具备实际并不具备的语义确定性✅ 索引器只返回路由信息和原始源代码范围

结果是 token 用量更少、延迟更低、上下文偏移更少,分析也更有源代码依据。


工作原理

索引器刻意避免假装自己是编译器。

  1. 快速扫描 token/结构 使用轻量级 Python 词法分析器和结构解析器扫描源文件。输出是确定性的目录:文件、符号、数据声明、词法 #include 指令、源代码范围、诊断信息和模块信息。

  2. C++20 模块映射 对模块接口、分区、导入、导出导入和使用方建立索引,让 AI 无需要求 LSP 解决整个构建问题,即可追踪模块繁多的代码。

  3. 增量更新和监视器 更新器会跟踪内容哈希,并尽可能只重写变更的索引数据。可选的监视器可在你使用 Visual Studio 时保持 MCP 服务缓存最新。

  4. 支持精简输出控制的 MCP 工具 工具优先提供准确的路由元数据。AI 仅在需要时逐步深入:精简符号查找、文件/模块/变更概览、准确的 read_symbol 或 read_range,然后再递归读取更深层的源代码。

索引器只是目录。AI 会根据明确读取的原始代码行进行递归探索和代码审查。


核心工作流

不要这样做:

Read Renderer.cpp completely: ~2000 lines

改为这样做:

find_symbol("Renderer::Paint")
read_symbol(symbolId)
inspect visible calls
read only relevant project callees

审查变更代码时:

list_changed_files
get_file_change_hunks(includeIndexedRangeSummary:true, includeSource:false)
get_file_change_hunks(symbolId/dataId, includeSource:true)
read_symbol/read_range only when current source behavior is needed

功能

扫描器从 C++ 源文件中提取路由信息:

  • 文件及稳定的文件 ID
  • C++20 模块和分区
  • 词法 #include 指令
  • 导入和导出
  • 命名空间
  • 类 / 结构体 / 枚举
  • 函数 / 方法
  • 构造函数 / 析构函数 / 运算符
  • 声明和内联定义
  • 准确的 startLine / endLine
  • 针对结构可疑文件的诊断信息

它基于流/token,而非正则表达式。


不提供的功能

有意不包含:

  • 不提供编译器精确的全程序调用图
  • 不提供 find_references
  • 不进行类型解析
  • 不进行模板实例化解析
  • 不进行编译器精确的重载解析
  • 不进行宏展开
  • 不生成语义摘要
  • 不进行 Bug 分析
  • 不提供 analyze_symbol(symbolId)

AI 应读取源代码范围,并根据原始代码进行推理。


输出布局

默认输出目录:

<project-root>/.mcp-cpp-project-indexer/

生成的文件:

.mcp-cpp-project-indexer/
  manifest.json
  files/
    f_<pathHash>.json
  index.sqlite
  modules.json
  diagnostics.json
  update_state.json      # written by build/update; used for fast incremental updates
  module_map.json        # generated by build_module_map.py
  .watch_update_summary.json  # temporary watcher/update summary
  .update.lock           # process lock for index writers
  .watcher.lock          # process lock for one active watcher

全局符号和数据路由索引存储在 index.sqlite 中。每个文件的 JSON 索引仍是准确源代码范围和增量重建的事实来源。

可选的 JSONL 导出:

python <indexer-root>\export_index_jsonl.py --index-root <project-root>\.mcp-cpp-project-indexer --kind symbols --output symbols.jsonl
python <indexer-root>\export_index_jsonl.py --index-root <project-root>\.mcp-cpp-project-indexer --kind data --output data.jsonl

只有使用 --emit-diagnostics 或 --emit-diagnostic-file-indexes 时,才会输出扫描器诊断文件索引字段:

scopeIntervals
structuralEvents
functionBodyRanges

为单个文件建立索引

在任意目录中:

python <indexer-root>\build_file_index.py `
  --file <project-root>\path\to\file.ixx `
  --project-root <project-root> `
  --output <project-root>\.mcp-cpp-project-indexer\diagnostic_file.json

包含扫描器诊断数据:

python <indexer-root>\build_file_index.py `
  --file <project-root>\path\to\file.ixx `
  --project-root <project-root> `
  --output <project-root>\.mcp-cpp-project-indexer\diagnostic_file.json `
  --emit-diagnostics

如果省略 --project-root,则使用该文件的父目录。


构建项目索引

建议在 C++ 项目根目录中使用:

cd <project-root>
python <indexer-root>\build_project_index.py

输出写入:

<project-root>/.mcp-cpp-project-indexer/

显式形式:

python <indexer-root>\build_project_index.py `
  --root <project-root> `
  --output-root <project-root>\.mcp-cpp-project-indexer

示例摘要:

Built cpp.project_index.v1
Root: <project-root>
Output: <project-root>/.mcp-cpp-project-indexer
Files: 7076
Symbols: 97583
Names: 95674
Modules: 3774
Diagnostics: 7
Total code lines: 1750000
Total tokens: 14200000
SQLite index: <project-root>/.mcp-cpp-project-indexer/index.sqlite

Total tokens 是索引器统计的索引源代码词法分析器令牌数,统计前已清空注释。它用于衡量项目规模,并非大模型计费令牌数。

如果项目根目录位于 Git 工作树中,且系统上有 git,文件发现会通过 git check-ignore --stdin 过滤候选文件,以遵循 Git 忽略规则。这会排除 .gitignore、.git/info/exclude 或用户全局 Git 忽略文件中匹配的路径。对于非 Git 项目或未安装 Git 的系统,则回退到内置的排除目录列表。默认排除 .git、.vs、.cache、.idea 或 .folder 等点目录。

项目发现配置

对于源代码布局混杂的大型项目,可将 indexer_config.json 放在项目根目录或任意子目录中。遍历目录树时会应用配置文件:根目录配置作为基础,子目录配置可针对其子树进行覆盖或扩展。

示例:

{
  "addExtensions": [".mm"],
  "addExcludeDirs": ["generated", "third_party"],
  "includeExtensionlessHeaders": true,
  "useGitIgnore": false
}

支持的字段:

{
  "extensions": [".cpp", ".cc", ".h"],
  "addExtensions": [".mm"],
  "removeExtensions": [".c"],
  "excludeDirs": ["out", "build"],
  "addExcludeDirs": ["generated"],
  "removeExcludeDirs": ["third_party"],
  "includeExtensionlessHeaders": true,
  "useGitIgnore": false
}

extensions 和 excludeDirs 会替换该子树继承的值。add* 和 remove* 字段会修改继承的值。无扩展名头文件的发现采用保守策略,且默认关闭;只有首行看起来像 C/C++ 头文件的无扩展名文件才会被接受。 对于 Git 忽略过滤的开销高于显式索引器配置的大型仓库,可设置 useGitIgnore:false,以禁用最后的 git check-ignore --stdin 筛选步骤。

增量更新

完成完整索引构建后,可以检测更改的文件并进行增量重新索引。

试运行:

python <indexer-root>\update_project_index.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --dry-run

对已索引文件快速更新:

python <indexer-root>\update_project_index.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --known-files-only

针对已知更改文件的监视器式更新:

python <indexer-root>\update_project_index.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --known-files-only `
  --changed-file path\to\changed.cpp

--known-files-only 会跳过新文件的完整发现流程。它非常适合保存/监视循环。 --changed-file 可重复指定,让监视器无需对未更改的文件进行哈希计算。

索引写入受索引根目录中的独占 .update.lock 文件保护。这可防止完整构建、增量更新和模块映射重建同时写入相同的索引文件。


监视项目索引

独立监视器会轮询源文件,对更改进行防抖处理,运行增量更新,并可选择重建 module_map.json。

python <indexer-root>\watch_project_index.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --jobs 20

对于纯文件修改,监视器会调用:

update_project_index.py --known-files-only --changed-file <path>

这只会对更改的候选文件进行哈希计算。如果内容哈希未更改,监视器会跳过模块映射重建和 MCP 缓存重新加载。

监视器也会检测方向文档的更改。仅文档发生更改时,只会刷新 orientation.json 及其 SQLite 节点,不会扫描 C++ 文件。仅 C++ 文件发生修改时,更新器会检查文档时间戳;若时间戳匹配,则复用现有的方向分析结果。新增/删除源文件路径以及 --force 仍会触发方向分析重建,因为文档链接可能发生变化。

每个索引根目录只能由一个监视器管理。监视器使用 .watcher.lock;如果同一索引已有其他监视器在运行,它就会退出。

诊断信息不会导致操作失败。它们表示针对个别文件尽力检测到的结构性警告。

输出诊断摘要:

python -c "import json; from collections import Counter; d=json.load(open(r'<project-root>\.mcp-cpp-project-indexer\diagnostics.json',encoding='utf-8')); print(len(d)); print(Counter(x.get('code') for x in d)); [print(x['relativePath'], x['code'], x['message'], x.get('range')) for x in d]"

构建模块映射

构建项目索引后:

python <indexer-root>\build_module_map.py `
  --index-root <project-root>\.mcp-cpp-project-indexer

输出:

<project-root>/.mcp-cpp-project-indexer/module_map.json

模块映射包含:

  • 模块名称
  • 主模块和分区
  • 定义各模块的文件
  • 导入项
  • importedBy
  • 模块树
  • 未解析的导入项

它仅包含元数据,不会分析实现行为。


控制中心

核心索引器没有第三方运行时依赖。日常操作有两个可选的终端控制界面:

  • indexer_tui.py:精致且支持鼠标操作的 Textual UI
  • indexer_control.py:无依赖的命令行备用方案

安装可选的 UI 依赖:

pip install -r <indexer-root>\requirements-ui.txt

启动 Textual UI:

python <indexer-root>\indexer_tui.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --jobs 20 `
  --http-url http://127.0.0.1:8765

Textual UI 提供真正的终端界面,包含按钮、鼠标支持、状态卡片、实时 HTTP /status 轮询、活动日志,以及对构建/更新/监视/服务操作的进程控制。

鼠标输入取决于终端模拟器。在 Windows 上,请使用 Windows Terminal 或其他能够将鼠标事件转发给终端应用的现代终端。Textual 可运行的所有环境都支持键盘快捷键。

退出时以及切换诊断文件分区时,UI 设置会保存到 <indexer-root>/.ui-settings/ 下。每个设置文件以项目名称和路径哈希为键,因此 UI 首选项不会写入项目根目录或生成的索引目录。保存的首选项包括 HTTP URL、jobs 值、诊断分区开关、管理 API 启动设置、当前 Textual 主题,以及项目/索引路径。

也可以直接编辑设置文件,以用于外部 Relay UI 设置:

{
  "httpUrl": "http://127.0.0.1:8765",
  "jobs": 20,
  "managementApiEnabled": true,
  "managementToken": "local-secret-token",
  "emitDiagnosticFileIndexes": true,
  "theme": "textual-dark"
}

Textual UI 有单独的 Start HTTP + management 操作。它会启动带有 watcher 和 --enable-management-api 的 HTTP MCP 服务,并在配置了 managementToken 时使用已保存的值。此操作特意仅供 TUI 使用,不会作为管理命令通过 HTTP API 提供。

备用控制中心:

python <indexer-root>\indexer_control.py `
  --root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --jobs 20 `
  --http-url http://127.0.0.1:8765

常用按键:

B  full build
U  incremental update
F  fast known-files update
M  rebuild module map
H  start HTTP server with watcher
G  start HTTP server with watcher and management API
W  start standalone watcher
S  toggle diagnostic file sections for launched commands
X  stop the currently running command
R  refresh
Q  quit

HTTP 服务运行时,两个控制中心都会轮询 /status,以获取服务、watcher、锁和索引统计信息。如果无法连接 HTTP 服务,它们会改为从磁盘读取 manifest.json 和 module_map.json。


转储模块树

文本树:

python <indexer-root>\dump_module_tree.py `
  --index-root <project-root>\.mcp-cpp-project-indexer

写入文件:

python <indexer-root>\dump_module_tree.py `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --output <project-root>\.mcp-cpp-project-indexer\module-tree.txt

导入单个模块的树:

python <indexer-root>\dump_module_tree.py `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --imports Example.Module:Partition `
  --max-depth 5

启动 MCP 服务

服务会读取已有索引,不会重建索引。

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer

该服务为只读服务,通过 MCP stdio 提供定位/读取工具。

为了让服务在编辑期间保持其内存缓存为最新状态,请使用内置 watcher 启动:

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --watch-index `
  --watch-jobs 20

服务 watcher 会将所有进度写入 stderr,以确保 stdout 保持有效的 MCP JSON-RPC。索引发生实际变化后,它会自动重新加载服务缓存。如果保存操作只更改了 mtime,而内容哈希未变,则会跳过模块映射重建和缓存重新加载。

如果同一索引根目录已由另一个 watcher 占用,MCP 服务会继续以只读模式运行,不会启动自己的 watcher。这样可避免多个 MCP 客户端启动各自的 stdio 服务实例时出现并发写入进程。

共享 HTTP 传输

对于多个 MCP 客户端原本会各自启动独立 stdio 服务进程的设置,服务也可以通过 HTTP 提供相同的 JSON-RPC MCP 接口:

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --transport http `
  --http-host 127.0.0.1 `
  --http-port 8765 `
  --watch-index `
  --watch-jobs 20

HTTP 端点:

POST http://127.0.0.1:8765/mcp

状态端点:

GET http://127.0.0.1:8765/health
GET http://127.0.0.1:8765/status

这样,索引根目录只需一个长期运行的服务进程、一个内存索引缓存和一个 watcher。仅支持 stdio 的客户端仍需要 stdio 配置,或一个连接到此 HTTP 端点的小型客户端桥接程序。

HTTP 管理 API

外部控制界面可以选择在同一 HTTP 服务上启用一个精简的管理界面。默认情况下,此功能处于禁用状态,因为它可以启动构建/更新进程。

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --transport http `
  --http-host 127.0.0.1 `
  --http-port 8765 `
  --enable-management-api `
  --management-token <token>

端点:

GET  /management/status
GET  /server/management/capabilities
POST /management/command
GET  /management/log?since=<eventId>&limit=<n>
GET  /management/log/stream
GET  /management/server-log?since=<eventId>&limit=<n>
GET  /management/server-log/stream

/server/management/capabilities 返回机器可读的意图/类别/工具约定,供外部中继/治理层使用。也接受旧别名 /management/capabilities。

/management/status 包含一个面向外部控制中心的 dashboard 对象。它包含 TUI 中显示的同一组高价值字段:

dashboard.project.text
dashboard.index.text
dashboard.server.url / pid / ramText / cpuTimeText / cpuText / uptimeText
dashboard.watcher.runningText / lockText / last
dashboard.counts.filesText / symbolsText / dataText / modulesText / diagnosticsText
dashboard.stats.codeLinesText / tokensText / cpuTimeText / threadsText
dashboard.locks.updateFile / watcherFile
dashboard.mode.diagnosticFileSectionsText / jobsText / theme

如果服务端能够提供原始数值,则会将其与格式化的 *Text 字段一同返回。dashboard.mode.theme 为外部界面保留;HTTP 服务本身不负责视觉主题。

通用的 server.process 和 management.runner.process 对象也会在可用时提供标准化的 CPU 字段:

cpuUserSeconds
cpuSystemSeconds
cpuTimeSeconds
cpuTimeText
cpuCoresAverage
cpuPercentMachine
cpuText

配置令牌后,它会保护共享的 HTTP MCP/状态界面以及管理端点。可通过以下任一方式传递令牌:

Authorization: Bearer <token>
x-api-key: <token>

命令是单个 JSON 对象:

{ "command": "build", "jobs": 20 }
{ "command": "update", "jobs": 20 }
{ "command": "fast_update", "jobs": 20 }
{ "command": "module_map" }
{ "command": "reload_index" }
{ "command": "start_watcher", "jobs": 20 }
{ "command": "stop_watcher" }
{ "command": "stop_command", "wait": true }

/management/log 返回管理命令输出。/management/log/stream 是对应的 SSE 流。构建和更新子进程的输出会异步读取,因此界面可以在大型项目编入索引期间持续轮询状态并流式接收日志。

/management/server-log 返回近期的 HTTP/MCP 流量日志事件,包括请求/响应字节数,以及可用时的 MCP 方法详情。/management/server-log/stream 是用于实时请求活动的对应 SSE 流。MCP tools/call 事件还会包含一个精简的结构化 mcp 对象,其中包含 toolName、argumentKeys 和有界的 arguments,供界面展开详情。在 JSON-RPC 响应确定后,事件会包含 mcp.outcome(success 或 error)和 mcp.errorCount,方便控制界面在不解析响应负载的情况下标示失败的工具调用。 HTTP keep-alive 请求会重置请求级日志元数据,因此状态轮询不会继承之前 MCP 调用的标签。

HTTP 安全配置

本地开发可以继续使用环回 HTTP:

--transport http --http-host 127.0.0.1 --http-port 8765

对于客户或局域网部署,请勿将服务作为纯 HTTP 暴露。除非启用了 TLS 和身份验证,否则服务拒绝在非环回绑定地址上启动。

安全配置:

配置用途要求
local-dev同一台机器上的开发允许环回 HTTP
trusted-lanRelay 和索引器运行在不同的可信主机上TLS 加令牌或 mTLS
production客户部署TLS 加令牌或 mTLS

令牌身份验证 TLS 示例:

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --transport http `
  --http-host 10.0.0.20 `
  --http-port 8765 `
  --management-security-profile trusted-lan `
  --management-tls cert `
  --management-cert security\indexer-server.crt `
  --management-key security\indexer-server.key `
  --management-token <token> `
  --management-cors-origin https://relay.customer.internal `
  --management-allow-ip 10.0.0.12

mTLS 示例:

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --transport http `
  --http-host 10.0.0.20 `
  --http-port 8765 `
  --management-security-profile production `
  --management-tls cert `
  --management-cert security\indexer-server.crt `
  --management-key security\indexer-server.key `
  --management-client-ca security\relay-clients-ca.crt `
  --management-require-client-cert `
  --management-cors-origin https://relay.customer.internal `
  --management-allow-ip 10.0.0.12

如需在没有客户证书的情况下进行本地加密测试,可以在首次启动时生成自签名证书:

python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer `
  --transport http `
  --http-host 127.0.0.1 `
  --http-port 8765 `
  --management-tls self-signed `
  --management-auto-cert

生成的文件存储在以下目录中:

<index-root>\certs\management-cert.pem
<index-root>\certs\management-key.pem

自签名 TLS 会加密流量,但浏览器或远程客户端不会自动信任它。客户部署应使用客户 CA、公有证书或显式的 mTLS 信任材料。


LM Studio MCP 配置

mcp.json 示例:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "command": "python",
      "args": [
        "<indexer-root>\\code_index_mcp_server.py",
        "--project-root",
        "<project-root>",
        "--index-root",
        "<project-root>\\.mcp-cpp-project-indexer"
      ]
    }
  }
}

对于未启用令牌身份验证的共享 HTTP 服务:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "url": "http://127.0.0.1:8765/mcp"
    }
  }
}

如果 HTTP 服务使用 --management-token <token> 启动,LM Studio 必须通过标头发送该令牌:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "url": "http://127.0.0.1:8765/mcp",
      "headers": {
        "Authorization": "Bearer <token>"
      }
    }
  }
}

服务也接受 X-API-Key:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "url": "http://127.0.0.1:8765/mcp",
      "headers": {
        "X-API-Key": "<token>"
      }
    }
  }
}

重新构建索引或模块映射后,重启 MCP 服务/LM Studio。


Codex 配置

对于 Codex,将此仓库配置为 MCP stdio 服务,并将 Agent 规则放在 Codex 会作为项目指令加载的位置。

MCP 服务条目示例:

[mcp_servers.mcp-cpp-project-indexer]
command = "python"

args = [
  "<indexer-root>\\code_index_mcp_server.py",
  "--project-root",
  "<project-root>",
  "--index-root",
  "<project-root>\\.mcp-cpp-project-indexer",
]

应将 prompt_template.md 中的提示词规则复制到 Codex 打开的项目根目录中的 AGENTS.md 文件,例如:

<project-root>\AGENTS.md

Codex 会将 AGENTS.md 作为当前工作树的仓库/项目指令读取。如果你通常从父级工作区启动 Codex,而不是从 C++ 项目根目录启动,请将该文件放在工作区根目录,或直接在 C++ 项目根目录中打开 Codex,以确保指令处于适用范围内。

请将 MCP 服务配置与提示词规则分开:

  • MCP 配置用于启动工具服务,并指向生成的索引。
  • AGENTS.md 用于告知 Agent 如何安全、简洁地使用这些工具。

更改 MCP 服务配置或重建索引后,请重启 MCP 服务/Codex 会话,以便加载更新后的工具架构。


Claude 设置

Claude Code 和 Claude Desktop 使用 MCP 的方式略有不同,因此请按客户端分别设置。

Claude Code

对于 Claude Code,如果希望设置随仓库一起移植,请在项目根目录的 .mcp.json 文件中配置项目级 MCP 服务:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "type": "stdio",
      "command": "python",
      "args": [
        "<indexer-root>\\code_index_mcp_server.py",
        "--project-root",
        "<project-root>",
        "--index-root",
        "<project-root>\\.mcp-cpp-project-indexer"
      ],
      "env": {}
    }
  }
}

等效的 CLI 设置:

claude mcp add mcp-cpp-project-indexer --scope project -- `
  python <indexer-root>\code_index_mcp_server.py `
  --project-root <project-root> `
  --index-root <project-root>\.mcp-cpp-project-indexer

将 prompt_template.md 中的规则复制到 Claude Code 的项目记忆文件中:

<project-root>\CLAUDE.md

Claude Code 也支持 .claude/CLAUDE.md;如果你希望将 Claude 专用文件放在 .claude/ 下,可以使用此路径。关键是该文件必须位于 Claude Code 打开的项目根目录中,否则可能不会加载工具使用规则。

Claude Desktop

Claude Desktop 使用其应用程序 MCP 配置文件。在 Windows 上,该文件通常是:

%APPDATA%\Claude\claude_desktop_config.json

在 mcpServers 下添加服务:

{
  "mcpServers": {
    "mcp-cpp-project-indexer": {
      "type": "stdio",
      "command": "python",
      "args": [
        "<indexer-root>\\code_index_mcp_server.py",
        "--project-root",
        "<project-root>",
        "--index-root",
        "<project-root>\\.mcp-cpp-project-indexer"
      ],
      "env": {}
    }
  }
}

Claude Desktop 不会自动读取任意聊天中仓库里的 CLAUDE.md 等指令文件。请将 prompt_template.md 中的相关规则粘贴到你与 Claude Desktop 一起使用的项目/聊天指令中;如果需要仓库级的持久指令,也可以使用 Claude Code。

更改 .mcp.json、claude_desktop_config.json 或重建索引后,请重启 Claude 客户端,以便加载更新后的工具架构。


可选工作流设置

基于源代码证据查找 Bug

一种实用的代码审查工作流是将 mcp-cpp-project-indexer 用作主要导航层,并让 AI 仅依据其读取过的确切源代码范围进行推理。

典型流程:

1. User asks:
     Review module X, file X, or function X for bugs.

2. AI uses mcp-cpp-project-indexer:
     find module/file/symbol
     read exact source ranges
     follow only relevant project-local calls
     avoid whole-file reads unless needed

3. AI reports findings:
     file path
     line range
     source-grounded explanation
     uncertainty where more context is needed

4. AI uses Visual Studio MCP only after analysis:
     open the file
     navigate to the exact finding location

这样可以保持模型上下文简洁。索引器负责定位和减少 token 使用量;AI 根据原始源代码行进行分析;Visual Studio 则作为面向开发者的编辑器交接工具。

与 Visual Studio MCP 配合使用时的工具优先级

在 C++20 模块较多的项目中,Visual Studio/IntelliSense/clangd 式工具可能无法可靠地解析模块符号,难以满足 AI 导航需求。

建议的职责分工:

mcp-cpp-project-indexer
  Primary navigation layer.
  Use for symbols, files, modules, source ranges, imports, imported-by metadata.

Visual Studio MCP
  Editor and project-state layer.
  Use for opening files, jumping to locations, looking at build/output/editor state.
  Do not use as the primary C++20 module symbol resolver.

IDAPro MCP
  Binary/decompiler layer.
  Use only when source evidence is insufficient, or for ABI, crash, reverse
  engineering, decompiled code, imports/exports, or binary-behavior questions.

提示词规则:

Use mcp-cpp-project-indexer first for C++ source navigation.
Use Visual Studio MCP only when IDE/editor/build state is needed.
Use IDAPro MCP only when the question requires binary or decompiler evidence.
为未文档化 API 提供源代码和二进制证据

对于与未文档化 Windows 组件交互的代码,仅有源代码证据可能不够。一种实用的设置是,在 IDAPro 中加载相关 DLL,并仅在源代码级证据无法明确行为时,让 AI 检查反编译/反汇编代码。

示例场景:

Project code uses wrappers around undocumented DirectUI behavior.
IDAPro has dui70.dll loaded.

1. AI uses mcp-cpp-project-indexer first:
     find the project wrapper/function
     read the exact source range
     follow only relevant local calls

2. If behavior is still unclear:
     use IDAPro MCP to inspect the corresponding function, import, export,
     vtable target, or decompiled implementation in dui70.dll

3. AI combines evidence:
     source callsite and wrapper behavior
     binary/decompiler evidence from the undocumented implementation
     final finding with source line ranges and binary evidence notes

4. AI uses Visual Studio MCP only for handoff:
     open the project source file
     navigate to the line that should be reviewed or changed

这样可以让逆向工程工作更有针对性。AI 不会盲目浏览二进制文件;它会带着基于源代码的问题进入 IDAPro。这能减少无关上下文,降低 token 使用量,并帮助模型保持源代码/二进制推理链条完整。

此设置为何有效

AI 代码审查中成本高昂的部分往往不是推理,而是定位真正重要的少量源代码。索引器将导航问题简化为精简的元数据和精确的源代码范围。这样,其他工具就能专注于各自擅长的领域:IDE 交互、构建状态或二进制事实。


命令行参考

build_file_index.py

为每个文件构建一个索引 JSON。

--file PATH                    C++ source/module file to index. Required.
--project-root PATH            Root used for normalized relative paths.
--output PATH                  Output JSON path.
--output-root PATH             Directory used when --output is omitted.
--case-insensitive-paths / --no-case-insensitive-paths
                               Case-fold relative paths before hashing. Default: true.
--blank-comments / --no-blank-comments
                               Blank comments before scanning while preserving lines.
--emit-diagnostics / --no-emit-diagnostics
                               Include scanner diagnostic data.
--print-summary-json           Print summary JSON.
build_project_index.py

构建完整的项目索引。

--root PATH                    Project/source root. Default: current directory.
--output-root PATH             Index output root. Default: <root>/.mcp-cpp-project-indexer.
--extensions EXT [EXT ...]     Source extensions, e.g. .cpp .cc .mm .h .ixx or cpp,h,ixx.
--include-extensionless-headers / --no-include-extensionless-headers
                               Also discover extensionless files that look like
                               C/C++ headers. Uses a conservative first-lines
                               heuristic. Default: false.
--git-ignore / --no-git-ignore Filter discovered files through git check-ignore
                               when available. Default: true.
--exclude-dir NAME             Extra excluded directory name. Repeatable or comma-separated.
--case-insensitive-paths / --no-case-insensitive-paths
                               Case-fold relative paths before hashing. Default: true.
--blank-comments / --no-blank-comments
                               Blank comments before scanning. Default: true.
--emit-diagnostic-file-indexes / --no-emit-diagnostic-file-indexes
                               Include scanner diagnostic fields in files/<fileId>.json.
                               Compatibility alias: --emit-debug-file-indexes.
                               Default: false.
--print-summary-json           Print summary JSON.
--list-defaults                Print default extensions and excluded directories.
--jobs N                       Worker processes. 1 = sequential, 0 = conservative auto.
--progress / --no-progress     Show progress on stderr. Default: true.
update_project_index.py

增量更新现有项目索引。

--root PATH                    Project/source root. Default: current directory.
--index-root PATH              Index root. Default: <root>/.mcp-cpp-project-indexer.
--extensions EXT [EXT ...]     Source extensions for discovery.
--include-extensionless-headers / --no-include-extensionless-headers
                               Also discover extensionless files that look like
                               C/C++ headers. Uses a conservative first-lines
                               heuristic. Default: false.
--git-ignore / --no-git-ignore Filter discovered files through git check-ignore
                               when available. Default: true.
--exclude-dir NAME             Extra excluded directory name. Repeatable or comma-separated.
--case-insensitive-paths / --no-case-insensitive-paths
                               Case-fold relative path keys. Default: true.
--blank-comments / --no-blank-comments
                               Blank comments before scanning changed files. Default: true.
--emit-diagnostic-file-indexes / --no-emit-diagnostic-file-indexes
                               Include scanner diagnostic fields in updated file indexes.
                               Compatibility alias: --emit-debug-file-indexes.
                               Default: false.
--dry-run                      Show added/modified/deleted files without writing.
--jobs N                       Worker processes for added/modified files.
--force                        Reindex all current files.
--known-files-only             Only consider files already present in manifest.json.
--changed-file PATH            Known changed file. Repeatable. Used by watchers to avoid
                               hashing unchanged files.
--progress / --no-progress     Show progress on stderr. Default: true.
--print-summary-json           Print summary JSON.
--summary-json-file PATH       Write summary JSON while keeping normal console output.
watch_project_index.py

轮询源文件,并在更改稳定后运行增量更新。

--root PATH                    Project/source root. Default: current directory.
--index-root PATH              Index root. Default: <root>/.mcp-cpp-project-indexer.
--indexer-root PATH            Directory containing the indexer scripts.
--extensions EXT [EXT ...]     Source extensions for snapshot scanning.
--include-extensionless-headers / --no-include-extensionless-headers
                               Also discover extensionless files that look like
                               C/C++ headers. Uses a conservative first-lines
                               heuristic. Default: false.
--git-ignore / --no-git-ignore Filter discovered files through git check-ignore
                               when available. Default: true.
--exclude-dir NAME             Extra excluded directory name. Repeatable or comma-separated.
--case-insensitive-paths / --no-case-insensitive-paths
                               Case-fold relative path keys. Default: true.
--jobs N                       Worker process count for update actions.
--poll-interval SECONDS        Poll interval. Default: 1.0.
--debounce SECONDS             Wait for changes to settle. Default: 1.5.
--module-map / --no-module-map Rebuild module_map.json after real index changes. Default: true.
--emit-diagnostic-file-indexes / --no-emit-diagnostic-file-indexes
                               Pass diagnostic emission to watcher-triggered updates.
                               Compatibility alias: --emit-debug-file-indexes.
                               Default: false.
build_module_map.py

根据项目索引构建模块关系元数据。

--index-root PATH              Project index root. Default: ./.mcp-cpp-project-indexer.
--output PATH                  Output JSON path. Default: <index-root>/module_map.json.
--print-summary-json           Print compact summary JSON.
dump_module_tree.py

导出可读的模块树和导入视图。

--index-root PATH              Project index root. Default: ./.mcp-cpp-project-indexer.
--imports MODULE               Dump import tree for one C++20 module name.
--max-depth N                  Maximum tree depth. For --imports, default is 4.
--max-files N                  Maximum file paths per module leaf. Default: 1.
--output PATH                  Optional output text file.
code_index_mcp_server.py

运行 MCP stdio 服务。

--project-root PATH            Project root used for read_range/read_symbol.
--index-root PATH              Directory containing the generated index.
--watch-index / --no-watch-index
                               Start server-managed background watcher. Default: false.
--watch-poll-interval SECONDS  Watcher poll interval. Default: 1.0.
--watch-debounce SECONDS       Watcher debounce delay. Default: 1.5.
--watch-jobs N                 Worker process count for watcher update actions.
--watch-module-map / --no-watch-module-map
                               Rebuild module_map.json after watcher updates. Default: true.
--watch-emit-diagnostic-file-indexes / --no-watch-emit-diagnostic-file-indexes
                               Pass diagnostic emission to server watcher updates.
                               Compatibility alias: --watch-emit-debug-file-indexes.
                               Default: false.
--watch-include-extensionless-headers / --no-watch-include-extensionless-headers
                               Let the server watcher discover extensionless files
                               that look like C/C++ headers. Default: false.
--watch-git-ignore / --no-watch-git-ignore
                               Filter watcher discovery through git check-ignore
                               when available. Default: true.
--transport stdio|http         Transport mode. Default: stdio.
--http-host HOST               HTTP bind host for --transport http. Default: 127.0.0.1.
--http-port PORT               HTTP bind port for --transport http. Default: 8765.
indexer_control.py

用于构建、更新、监视和服务工作流的终端控制中心。

--root PATH                    C++ project root. Default: current directory.
--index-root PATH              Index root. Default: <root>/.mcp-cpp-project-indexer.
--indexer-root PATH            Directory containing indexer scripts.
--jobs N                       Worker process count for launched commands.
--http-url URL                 HTTP server base URL for live status.
                               Default: http://127.0.0.1:8765.
--enable-management-api / --no-enable-management-api
                               Enable the TUI's HTTP + management launch mode.
--management-token TOKEN       Management API token used when launching
                               HTTP + management.
--emit-diagnostic-file-indexes / --no-emit-diagnostic-file-indexes
                               Initial diagnostic file section setting.
indexer_tui.py

可选的 Textual 终端 UI,支持鼠标操作和实时状态面板。需要运行 pip install -r requirements-ui.txt。

--root PATH                    C++ project root. Default: current directory.
--index-root PATH              Index root. Default: <root>/.mcp-cpp-project-indexer.
--indexer-root PATH            Directory containing indexer scripts.
--jobs N                       Worker process count for launched commands.
--http-url URL                 HTTP server base URL for live status.
                               Default: http://127.0.0.1:8765.
--emit-diagnostic-file-indexes / --no-emit-diagnostic-file-indexes
                               Initial diagnostic file section setting.
indexer_menu.py

旧版交互式菜单和非交互式命令包装器。日常操作建议使用 indexer_control.py。

--root PATH                    C++ project root. Default: current directory.
--index-root PATH              Index root. Default: <root>/.mcp-cpp-project-indexer.
--indexer-root PATH            Directory containing the indexer scripts.
--jobs N                       Worker process count for build/update actions.
--emit-diagnostic-file-indexes / --no-emit-diagnostic-file-indexes
                               Initial menu switch state for scanner diagnostic file sections.
                               Compatibility alias: --emit-debug-file-indexes.
                               Default: false.
--action NAME                  Run one action without the menu.

支持的 --action 值:

build-index
build-module-map
build-all
update-dry-run
update-known-dry-run
update-index
update-known
update-all
update-known-all
watch
summary
diagnostics
dump-module-tree
lmstudio-config
server
server-watch
server-http-watch

工具概览

项目摘要
get_project_summary
get_index_fingerprint
get_file_fingerprint(file)
get_symbol_fingerprint(symbolId)
get_data_fingerprint(dataId)
validate_fingerprints(items)

服务会公开索引 stateFingerprint:这是一个服务端计算的轻量指纹,基于当前索引产物(manifest.json、index.sqlite、模块/诊断/更新文件)。索引状态加载后发生变化时,该指纹也会变化,因此中继/编排层可以在重建、更新或重新加载缓存后,将较早的工具证据标记为过期。

每个 MCP 工具结果都会在结果 _meta 中携带该指纹:

{
  "_meta": {
    "stateFingerprint": "..."
  }
}

同一值也会通过 get_project_summary.stateFingerprint 和 HTTP 状态端点中的 index.stateFingerprint 公开。

若要细粒度地复用证据,请优先使用指纹工具。全局索引指纹仅用作警示信号。文件、符号和数据指纹可让中继验证有效事实,而不必在每次更新后丢弃整个证据缓存:

fileFingerprint =
  hash(fileId + relativePath + contentHash + line/token counts)

symbol/data fingerprint =
  hash(id + fileFingerprint + startLine + endLine + signature)

validate_fingerprints 是供中继/编排层使用的批量入口。它最多接受 500 个文件/符号/数据项,并且只返回精简的有效性和指纹元数据。这些调用不会读取或返回源代码文本。

更改跟踪工具

仅当 git.exe 可用且 project-root 位于工作树内时,才会提供这些工具。它们是只读的,不会暴露通用命令运行器。

list_changed_files
list_recent_revisions
get_revision_summary
get_file_change_hunks
resolve_hunk_to_indexed_range

可使用这些工具查看当前更改、近期修订、代码块检查、修改文件审查,以及提交消息建议。

当代码块元数据提供了更改后的新行范围,而中继需要有效的 symbolId/dataId 路由目标才能读取源代码时,请使用 resolve_hunk_to_indexed_range(file, line|startLine/endLine)。它会返回包含、更改范围重叠或最接近该范围的索引符号/数据范围。此工具仅提供元数据,不会解读差异,也不会声称结果正确。

当用户表示他们已修复、更改、保存、更新或提交内容,或希望审查当前工作时,Agent 应先检查这些工具,再进行常规源代码导航。在 watcher 设置中,索引可能已经是最新的,而更改工具能以最低成本定位受影响的文件/符号范围。

get_file_change_hunks 可以包含 indexedRanges,其中列出更改代码块的行范围与索引符号/数据范围的交集。这些内容仅是路由提示。在对实现作出判断前,请使用 read_symbol 或 read_range 读取相关源代码。

若要以较低的 token 开销进行审查路由,请调用 get_file_change_hunks,并设置 includeIndexedRangeSummary:true、includeIndexedRanges:false 和 includeSource:false。返回的 summaryByIndexedRange 会按受影响的索引符号/数据范围汇总更改代码块,而不会重复列出每个代码块的交集。

选定受影响范围后,将 symbolId 或 dataId 传回 get_file_change_hunks,即可仅返回与该符号/数据范围相交的代码块。这仍然是按行范围筛选,而非语义分析。

符号和源码工具
find_symbol(query)
find_declaration(query)
find_symbols_glob(pattern)
read_symbol(symbolId)
read_range(file, startLine, endLine)
read_range(file, line, beforeLines, afterLines)
get_nearest_symbol_for_line(file, line)
list_file_symbols(file)

get_nearest_symbol_for_line 可将诊断、代码块、构建输出、Visual Studio 或 IDA 注释中的文件/行号映射到包含该位置或距离最近的已索引符号/数据范围。它仅提供元数据;在对行为作出判断前,请先阅读所选源码范围。

read_symbol 接受可选的 startOffset/endOffset 或绝对行号 startLine/endLine,用于仅读取大型符号主体中的一段内容。

read_range 接受显式的 startLine/endLine,也接受简洁的围绕行形式,使用 line、beforeLines 和 afterLines。围绕行形式适用于诊断、代码块、搜索匹配、Visual Studio 移交和 IDA 注释等场景,此时调用方有一行相关源码。

find_symbol 仅搜索符号元数据:

  • 精确匹配 shortName
  • 精确匹配 qualifiedName / 别名
  • 回退为在 shortName、qualifiedName 和 signature 中进行子串匹配

可选路由控制项:

  • compact:仅返回精简路由字段
  • responseFormat:元数据响应的 JSON 格式,可选 pretty 或 minified
  • omitNulls:从元数据响应中省略 null 字段
  • omitEmpty:从元数据响应中省略空数组/对象
  • symbolTypes:按已索引的符号类型筛选,例如 method、function、type_alias
  • container:按包含该符号的类/结构体/命名空间名称或后缀筛选
  • file:按单个 fileId 或项目相对路径筛选
  • filePattern:按项目相对路径 glob 筛选
  • exactOnly:仅返回 short-name 或 qualified-name 的精确匹配,包括忽略大小写的精确匹配
  • hideNamespaces:在导航结果中隐藏命名空间重开符号

container 仅用于指定声明该符号的实际词法/索引容器。不要仅仅因为某个类调用了辅助自由函数,就将该类用作容器。如果带 container 的 find_symbol 查询未返回结果,请先移除 container 并重试精确符号名称,再回退到 search_source。

每个返回项都包含 matchKind,用于说明匹配原因。exact_qualified_name 和 exact_short_name 等强匹配通常最适合用于路由。子串、签名和元数据匹配是较弱的候选项,读取源码前应先加以区分。

不要同时使用 file 和 filePattern。这些控制项是定位筛选器;它们不会读取源码,也不会从语义上解析重载。

响应打包选项仅适用于元数据/路由工具。源码工具的带行号源码输出保持不变。

已知文件时,list_file_symbols 也可返回较小的文件级符号候选列表:

  • compact:仅返回精简路由字段
  • symbolTypes:按已索引的符号类型筛选
  • container:按包含该符号的类/结构体/命名空间名称或后缀筛选
  • hideNamespaces:隐藏命名空间重开符号
  • limit:限制结果数量

这仅是定位筛选器,不会解析继承、重载或类型语义。

已知文件,且类成员和局部辅助函数都可能相关时,请优先使用 list_file_symbols(file, compact:true, hideNamespaces:true),不要贸然猜测 container 筛选条件。匿名命名空间中的辅助函数仍是普通的已索引函数;它们的容器可能是外围的具名命名空间,而不是调用它们的类。

search_source 接受 symbolId,用于仅在一个已索引的符号范围内搜索。这是在已定位的函数或方法中进行词法检查的首选方式。它仍是词法源码搜索,不会进行语义调用/引用解析。

规范参数:

{ "query": "Editor::_OnScroll" }

name 可作为兼容性别名接受,但规范参数是 query。

文件工具
find_files(pattern)
list_file_includes(file)
get_file_structure(file)

仅针对相对于项目的路径执行 Glob。这不是源代码 grep。

list_file_includes 会返回某个文件中的词法 #include 指令。 它适用于 Chromium 等基于传统 include 的 C++ 代码库:

{
  "file": "chrome/app/chrome_main.cc",
  "compact": true,
  "includeResolved": true
}

include 元数据仅作为路由依据。索引器会记录源代码行、目标文本、include 类型(quote、angle 或 macro),以及在被包含文件可直接访问时尽力解析出的相对于项目的路径。它不会评估 #if/#ifdef、编译器 include 目录、生成的头文件或宏展开。

get_file_structure 会返回某个文件的仅含元数据的目录。对于大型文件,建议先使用 includeOutline:false。需要 include 元数据时,使用 includeIncludes:true。使用 symbolTypes、dataKinds、hideNamespaces、outlineLimit 和 compactOutline:true 来缩小响应。在确定相关目录条目后,先用 read_symbol 或 read_range 阅读源代码,再对实现作出判断。

如果文件索引是使用 --emit-diagnostic-file-indexes 构建的,get_file_structure 还可以包含可选的解析器/索引器诊断部分:

{
  "file": "...",
  "includeOutline": false,
  "includeIndexerDiagnostics": true,
  "diagnosticKinds": ["structuralEvents", "scopeIntervals", "functionBodyRanges"],
  "diagnosticStartLine": 120,
  "diagnosticEndLine": 180,
  "compactDiagnostics": true,
  "diagnosticLimit": 100
}

仅在调查解析器诊断、缺失符号、可疑源代码范围或意外的作用域/函数体检测时使用。索引器诊断输出是扫描器证据,不代表实现行为。

提示词的措辞在这里很重要。对于许多 AI Agent 来说,“调试信息”一词范围太广,容易与 C++ 调试构建代码混淆,例如 DEBUG、_DEBUG、#ifdef DEBUG、Visual Studio 调试或日志分支。对于索引器扫描器数据,请明确询问索引器/解析器诊断。

导览工具
get_project_orientation()
list_orientation_nodes()
get_orientation_node(path)
search_orientation(query)

如果项目包含带有标准导览区块的文件夹级 README.md / readme.md,或文件名中含有 topology 的 Markdown 文件,索引器会将其记录为可选的导览元数据。这让 AI Agent 在阅读实现源代码之前,就能以较低成本了解项目结构。文件夹 README 使用 kind: "folder_orientation";拓扑文档使用 kind: "topology"。

这些工具会动态公开。如果已加载的索引中没有导览/拓扑节点,tools/list 和管理能力元数据中就不会包含导览工具。

导览层仅从绑定的项目索引器导览 README 标题中提取结构化字段:

Purpose:
Use this folder when the question is about:
Do not use this folder first when the question is about:
## Map
## Start Here
## Boundaries

Responsibilities、Non-responsibilities、Use when、Current layout 或 Responsibility Boundaries 等旧式标题仍只是普通 Markdown 文本,不会填充结构化导览字段。## Map 条目会从代码围栏 text 区块中解析;条目名称与描述之间至少要有两个空格。已解析的条目会包含 targetRootRelativePath 和 pathStatus。

search_orientation 使用 BM25 路由搜索,并返回 schema: "cpp.project_orientation.search.v2.1"、algorithm: "bm25"、查询词诊断信息、分数、匹配字段和反匹配词。结果仅为路由提示。

可使用它回答架构和导航问题:

{
  "query": "MCP dispatch",
  "limit": 10
}

然后读取选定的导览节点:

{
  "path": "src/server/core/mcp"
}

导览元数据不是实现证据。它可以回答:

Where should I start?
Which subsystem owns this responsibility?
Which folder should I not inspect first?

但无法回答某个函数的作用、代码是否正确,或某种运行时行为是否有保证。对于这类判断,请使用 find_symbol、list_file_symbols、read_symbol 或 read_range 定位并阅读源代码。

好的提示词:

Show me which indexer diagnostics are present.
Show me the parser/indexer diagnostics from the index.
Show me indexerDiagnostics.diagnostics from get_file_structure(includeIndexerDiagnostics:true) for file X.
Which indexerDiagnostics.diagnostics are available in the index for file X?
Show me the source location for this indexer diagnostic.

避免使用含糊的提示词,例如:

Show me debug information.
Find the debug code.
Where is DEBUG used?

预期的工作流如下:

get_file_structure(includeIndexerDiagnostics:true, compactDiagnostics:true)
-> inspect indexerDiagnostics.diagnostics first
-> read_range around the reported line
-> optionally get_nearest_symbol_for_line for the containing symbol

示例:

*Editor*
*/TextEditor/*.ixx
*/Shell/Browser/*
模块工具
find_module(moduleName)
list_module_files(moduleName)
search_modules(pattern)
get_module_map_summary
get_module_info(moduleName)
list_module_imports(moduleName)
list_module_imported_by(moduleName)
get_module_tree(maxDepth)

使用 C++20 模块语法:

Example.Module:Partition
uiframework.Elements:ElementImpl

不要向模块工具传递 C++ 命名空间语法:

Example::Namespace
UIFramework::Elements

对于命名空间、类和函数,请使用 find_symbol 或 find_symbols_glob。

方向很重要:

What does module X import?       -> list_module_imports(X) or get_module_info(X)
Who imports/consumes module X?   -> list_module_imported_by(X) or get_module_info(X)

不要先搜索源文本来回答反向导入问题。模块映射已存储 importedBy 元数据。只有在调用方要求检查实际导入行或元数据看起来可疑时,才读取源代码。

模块元数据工具可在适当情况下接受 compact:true:

  • find_module / list_module_files:精简模块/文件路由字段
  • get_module_info:精简文件、导入和被导入元数据
  • list_module_imports:精简的导出导入记录
  • list_module_imported_by:精简的导入模块记录
数据/成员工具
find_data(query)
list_type_members(container)
read_data(dataId)
resolve_code_entity(query, file?, line?, container?)

对于字段、全局变量、命名空间常量、枚举值、变量模板和概念,请使用 find_data。如果已知所属类型或命名空间,请使用 list_type_members。这两个工具都仅提供元数据,并接受 compact:true 以缩小路由输出。

当源代码范围包含标识符,且 AI 需要在选择下一项读取工具前判断它可能是字段/数据声明、可调用符号、类型符号还是有歧义的候选项时,请使用 resolve_code_entity。它接受可选的文件、行和容器上下文,并返回经过排序的元数据候选项,以及建议的下一项工具,例如 read_data 或 read_symbol。

resolve_code_entity 仅用于确定方向。它不执行编译器名称查找、重载决议、宏展开、C++ 类型解析或语义引用解析。源代码层面的结论仍需使用 read_data、read_symbol 或 read_range。

typeText 是声明类型的原始源文本。它不是经过编译器解析的类型。请将其视为进一步查找符号/源代码的线索,而非语义类型标识的证明。

函数图工具
get_function_body_graph(symbolId, mode?)
get_call_xrefs_from(symbolId)
get_call_xrefs_to(symbolId)
get_symbol_neighborhood(symbolId)

定位可调用符号后,如果 AI 需要获取该函数体的直接源代码结构边,请使用 get_function_body_graph:项目内的调用候选项、未解析/外部调用、数据/成员访问和控制流标记。该工具按需运行且会感知缓存;它不会更改常规索引构建流程。

实用模式:

  • compute_if_missing:复用兼容的缓存图,或计算图。
  • cache_only:仅返回兼容的缓存图数据。
  • refresh:为该符号重新计算图,并替换已持久化的边。

交叉引用和邻域工具仅读取已持久化的图边:

  • get_call_xrefs_from:函数的出向已存储调用边。
  • get_call_xrefs_to:指向函数的入向已存储调用边。
  • get_symbol_neighborhood:精简的目标/调用方/被调用方邻域。

在依赖交叉引用完整性之前,请先为相关调用方计算或刷新 get_function_body_graph。函数图输出仅作为结构导航证据:claimStrength=source_structure_allowed,且 behaviorClaimsAllowed=false。它不是行为分析、外部 API 语义、动态派发证明或编译器精确重载决议。

更多详情请参阅 Function Graph MCP Tools。


AI 推荐使用规则

模型应遵循以下规则:

Use mcp-cpp-project-indexer as a deterministic source-range locator.
Read source before making implementation claims.
Use query as the canonical argument for symbol lookup tools.
Do not ask for analyze_symbol.
Use function graph tools only as structural navigation evidence.
Do not treat module metadata as implementation behavior.
工具暴露说明

大型 MCP 工具集在客户端仅保留与当前任务相关的活动工具时,效果最佳。如果每个请求都暴露所有工具,一些模型可能会过度探索、重复相似查询,或选择范围过大的工具。这是通用模型的正常表现,并不表示索引数据有问题。

通常,应从精简的元数据查询开始,仅在需要实现证据时读取源代码范围。

正确调用:

find_symbol({"query": "Editor::_OnScroll"})
find_declaration({"query": "OnNotifyReflect"})

避免:

find_symbol({"name": "Editor::_OnScroll"})

完整的系统提示词模板见 prompt_template.md。


示例工作流

查找声明和定义

用户:

Find the declaration and definition of OnNotifyReflect.

AI 工作流:

find_symbol({"query": "OnNotifyReflect"})
read_symbol(symbolId for declaration)
read_symbol(symbolId for definition)
按需分析单个函数

用户:

Show me Editor::_OnScroll.

AI 工作流:

find_symbol({"query": "Editor::_OnScroll"})
read_symbol(symbolId)

然后,AI 只会跟进相关的项目内调用:

GetHWND -> find_symbol/read_symbol
SendMessageW -> external Win32 API, do not query project index
MAKEWPARAM -> external Win32 macro, do not query project index
导入模块的使用方式

工作流:

1. get_module_info or list_module_imports/list_module_imported_by
2. use relativePath and sourceLine from import metadata
3. list_file_symbols(relativePath)
4. choose the likely entry point from symbol names/signatures
5. read_symbol(candidate)
6. inspect visible source usage
7. follow more project symbols only if needed

不要用 find_symbols_glob 代替源代码使用情况搜索。它搜索的是符号元数据,而不是调用位置。


设计规则

精确的行号是系统的核心
symbolId -> fileId -> startLine/endLine -> original source
保持运行时数据精简

运行时索引存储路由信息。扫描器诊断数据需通过 --emit-diagnostics 或 --emit-diagnostic-file-indexes 显式启用。

将搜索与浏览分开
index.sqlite               -> symbol/data search
module_map.json            -> module browsing
manifest.json              -> file browsing
保持诊断信息可见

不要为了让诊断数归零而隐藏真实的解析器或源代码问题。

不要扩大语义范围

不构建调用图。不构建引用图。不进行宏展开。不提供分析器工具。AI 会按需递归探索源代码。


重建步骤

cd <project-root>

python <indexer-root>\build_project_index.py

python <indexer-root>\build_module_map.py `
  --index-root .\.mcp-cpp-project-indexer

然后重启 MCP 服务 / LM Studio。


许可证

本项目采用 Apache License 2.0 许可。

SPDX-License-Identifier: Apache-2.0

在仓库中添加完整的 Apache-2.0 许可证文本,文件名如下:

LICENSE

可选的源文件头:

# SPDX-License-Identifier: Apache-2.0

版权

Copyright (c) 2026 Mike Walter

项目名称:

mcp-cpp-project-indexer

🤖 开发历程

本项目是在涉及 ChatGPT、Gemini 和 DeepSeek 的多模型 AI 辅助开发工作流中逐步成形的。目标并非让单个模型盲目构想一个宽泛的工具,而是利用多个模型和真实的生产反馈,就范围、约束和工作流中的阻碍展开讨论。

  1. 架构与范围讨论 使用 ChatGPT 和 Gemini 讨论工具的边界:它应该做什么、应该避免什么,以及为什么它应该保持为轻量级路由索引,而不是变成编译器或 clangd 的替代品。

  2. 渐进式实现 使用 AI 编码 Agent 逐步实现代码库,并针对真实的 C++20 模块密集型项目测试每项功能变更。

  3. 工作流结构分析与审查 在一个包含 7,000 个文件的代码库中进行生产使用时,将 DeepSeek 用作专门的工作流分析伙伴。它评估了工具调用序列、参数选择、输出大小、排序质量、导航阻碍和上下文管理,然后反馈了具体改进方案,以减少调用次数并提高令牌效率。

  4. 迭代优化 这些交流中的反馈推动了有针对性的改进:精简输出、符号 / 文件 / 容器筛选、变更块路由、监视器重新加载、按行读取以及更严格的提示词规则。

最终成果是一个由 AI 构建、用于 AI 辅助代码导航的工具,并围绕一条严格原则进行了优化:保持索引器诚实且精简,让 AI 只根据它明确读取的源代码范围进行推理。


冒烟测试

完成 MCP 集成后,进行测试:

  • 获取项目摘要

  • 显示 Example.Core.Direct2D 下的所有模块。

  • 哪些模块导入 Example.Shell.Browser:Impl?

  • 查找 ExampleClass::OnEvent 的声明和定义。

  • 读取 GetHandler 的所有重载。

  • 哪个文件定义了 Example.Elements:ElementImpl?

  • 查找 ExampleClass::operator= 的定义。

  • 列出 Example/Core/Renderer.cpp 中的所有符号。

  • Example.UI:ToggleSwitch 导入了哪些模块?

  • 显示 Example.Core 的模块树(最大深度为 3)。

  • 查找所有匹配 ExampleDialog* 的文件。

  • 读取 Example/Core/Main.ixx 的前 20 行。

  • 查找 ExampleClass::ExampleClass 的声明(构造函数)。

  • 查找 Example/Core/Renderer.cpp 中所有匹配 Paint 的符号。

  • 显示 Example.Shell:Impl 导入了哪些模块。

  • 获取模块映射摘要。

  • 查找 ExampleClass::OnKeyDown 的定义。

  • 读取 ExampleClass::OnPaint 的代码范围(第 150-200 行)。

  • 查找 Example.UI:Controls 模块中的所有文件。

  • 显示 Example.UI:ToggleSwitch 的导入树。

  • 查找符号 ExampleNamespace::ExampleClass::Method。

  • 列出所有导入 Example.Core.Service 的模块。

  • 查找模板函数 ExampleClass::Create 的声明。

  • 读取符号 ExampleClass::OnNotify。

  • 查找 Example/UI/Controls/ 下的所有文件。

  • 显示 Example.Core.Direct2D.Renderer 的模块信息。

  • 查找 ExampleClass::Initialize 的定义。

  • 列出 Example/Core/Service.cpp 中所有函数符号。

  • 查找属于 Example.UI 的所有模块。

  • 读取 ExampleClass::HandleInput 的源代码(第 50-120 行)。

  • 查找定义 Example.Core:ModuleImpl 的文件。

  • 显示 Example.UI:Controls.Button 导入的所有模块。

  • 查找枚举 ExampleClass::State 的声明。

  • 读取符号 ExampleClass::GetSize。

  • 查找 Example/ 下所有扩展名为 .ixx 的文件。

  • 显示 Example.Shell 的模块树(最大深度为 2)。

  • 查找 ExampleClass::_UpdateLayout 的定义。

  • 列出 Example/Core/Utils.cpp 中的所有符号。

  • 查找所有导入 Example.UI:Controls 的模块。

  • 读取 ExampleClass::Paint 的代码范围(第 200-250 行)。

  • 查找 ExampleClass::~ExampleClass 的声明(析构函数)。

  • 显示 Example.Shell.Browser:Impl 的模块信息。

  • 查找 Example/Core/ 中所有匹配 Handler 的符号。

  • 读取符号 ExampleClass::OnMouseMove。

  • 查找定义 Example.UI:Controls.Button 的文件。

  • 列出 Example.Core.Direct2D 导入的所有模块。

  • 查找 ExampleClass::SetValue 的定义。

  • 显示 Example.UI 的模块树(最大深度为 4)。

  • 查找 Example/Shell/Browser/ 下的所有文件。

  • 读取 Example/Core/Service.ixx 的前 30 行。

  • 查找 ExampleClass::GetAccessibleImpl 的声明。

  • 列出 Example/UI/Controls/Button.cpp 中的所有符号。

  • 查找 Example.Shell.Browser:Impl 导入的所有模块。

  • 显示 Example.Elements:ElementImpl 的模块信息。

  • 查找 ExampleClass::OnPropertyChanged 的定义。

  • 读取符号 ExampleClass::GetState。

  • 查找 Example/Core/ 下所有匹配 Service 的文件。

  • 显示 Example.Elements 的模块树(最大深度为 3)。

  • 查找 ExampleClass::Register 的声明。

  • 列出 Example/Shell/Browser/Impl.cpp 中的所有符号。

  • 查找所有导入 Example.Core.Direct2D.Renderer 的模块。

  • 读取 ExampleClass::OnInput 的代码范围(第 100-150 行)。

  • 查找 ExampleClass::_SelfLayoutDoLayout 的定义。

  • 显示 Example.UI:Controls.Dialog 的模块信息。

  • 查找 Example/Core/ 中所有匹配 Layout 的符号。

  • 读取符号 ExampleClass::GetSliderSize。

  • 查找定义 Example.Shell:Impl 的文件。

  • 列出属于 Example.Core 的所有模块。

  • 查找 ExampleClass::DefaultAction 的声明。

  • 读取 Example/UI/Controls/Dialog.ixx 的前 40 行。

  • 查找 ExampleClass::_FireClickEvent 的定义。

  • 显示 Example.Core.Direct2D 的模块树(最大深度为 5)。

  • 查找 Example/Elements/ 下的所有文件。

  • 读取符号 ExampleClass::GetCaptured。

  • 查找所有导入 Example.Private.Helper 的模块。

  • 显示 Example.UI:Controls.Dialog 的模块信息。

  • 查找 ExampleClass::SetCaptured 的声明。

  • 列出 Example/Elements/ElementImpl.cpp 中的所有符号。

  • 查找 ExampleClass::OnInput 的定义。

  • 读取 ExampleClass::_UpdateLabel 的代码范围(第 170-180 行)。

  • 查找 Example/Elements/ 下所有匹配 Element 的文件。

  • 显示 Example.Private 的模块树(最大深度为 2)。

  • 查找 ExampleClass::GetPressed 的声明。

  • 读取符号 ExampleClass::SetPressed。

  • 查找所有导入 Example.Elements:ElementImpl 的模块。

  • 显示 Example.Private.Helper 的模块信息。

  • 查找 ExampleClass::OnPropertyChanged 的定义。

  • 列出 Example/Core/Direct2D/Renderer.cpp 中的所有符号。

  • 查找 Example/UI/ 下所有扩展名为 .cpp 的文件。

  • 读取符号 ExampleClass::GetSliderBorderStrokeWidth。

  • 查找 ExampleClass::SliderBackgroundColorProp 的声明。

  • 显示 Example 的模块树(最大深度为 1)。

  • 查找所有以 Example.UI 开头的模块。

  • 读取 ExampleClass::_SelfLayoutUpdateDesiredSize 的代码范围(第 200-220 行)。

  • 查找 ExampleClass::SliderBorderColorProp 的定义。

  • 列出 Example/Private/Helper.cpp 中的所有符号。

  • 查找所有导入 Example.UI:Controls.Dialog 的模块。

  • 显示 Example.Elements:ElementWithTooltip 的模块信息。

  • 查找 ExampleClass::SliderForegroundColorProp 的声明。

  • 读取符号 ExampleClass::SliderSizeProp。

  • 查找 Example/Private/ 下的所有文件。

  • 查找 ExampleClass::StateProp 的定义。

  • 列出 Example/Core/Service.cpp 中的所有符号。

  • 查找 Example.Elements:ElementImpl 导入的所有模块。

  • 显示 Example.UI.Controls 的模块树(最大深度为 3)。

  • 查找 ExampleClass::CapturedProp 的声明。

  • 读取符号 ExampleClass::PressedProp。

  • 查找 Example/Private/ 下所有匹配 Helper 的文件。

  • 查找 ExampleClass::ClassInfoI::GetClassInfoPtr 的定义。

  • 列出 Example/UI/Controls/Dialog.cpp 中的所有符号。

  • 查找所有导入 Example.Private.TreeHelper 的模块。

  • 显示 Example.UI:Controls.Button 的模块信息。

  • 查找 ExampleClass::ElementWithPromptValueI::ElementWithPromptValueProperties 的声明。

  • 读取符号 ExampleClass::Initialize(包含 3 个参数的重载)。

  • 查找 Example/Core/Direct2D/ 下的所有文件。

  • 查找 ExampleClass::_Initialize 的定义。

  • 列出 Example/Elements/ElementWithTooltip.cpp 中的所有符号。

  • 查找所有导入 Example.Private.ValueHelper 的模块。

  • 显示 Example.Shell.Browser 的模块树(最大深度为 4)。

  • 查找 ExampleClass::Register 的声明。

  • 读取符号 ExampleClass::ToggleSwitch(构造函数)。

  • 查找 Example/Core/Direct2D/ 下所有匹配 Renderer 的文件。 预期行为:

  • 模型会使用工具

  • 不会读取整个文件

  • 不会混淆命名空间和模块

  • 仅在查询符号元数据后调用 read_symbol

  • 仅在需要时递归跟进项目调用

维护清单

更改工具行为、命令行开关、提示词或文档后, 请按照 MAINTENANCE_CHECKLIST.md 检查一遍。该清单涵盖 常见的同步事项:工具描述、提示词规则、README、菜单/CLI 标志、 索引数据兼容性、冒烟测试、中继假设和提交准备。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。