什么是 CodeGraphCodeGraph 是一个开源的代码知识图谱 MCP 服务器34k Stars核心思路是提前把代码的符号关系建好索引让 AI 代理直接查询图谱而不是每次从头扫描文件。工作原理AI Agent (Reasonix Code) │ codegraph_context / codegraph_trace / codegraph_explore ▼ CodeGraph MCP Server │ SQLite 知识图谱符号 边 全文索引 ▼ Tree-sitter 解析 AST → 提取函数/类/方法/调用/继承关系 │ ▼ 项目源代码Java / Vue / JS / XML / YAML 等关键特性支持 20 语言包括 Java、JavaScript、TypeScript、Vue 等完整的调用图callers / callees / trace影响范围分析impact文件监听自动同步OS 原生事件2 秒去抖100% 本地运行无外部 API二、安装步骤2.1 全局安装# 使用 npx 零安装推荐 npx colbymchenry/codegraph安装器会交互式选择要配置的 AI 客户端。目前支持Claude Code、Cursor、Codex CLI、Gemini CLI、OpenCode、Hermes Agent 等。Reasonix Code 不在自动配置列表中需手动注册。2.2 在项目根目录创建索引cd your-project codegraph init -i-i参数表示初始化后立即建索引。执行后在项目根目录生成.codegraph/目录其中包含 SQLite 数据库codegraph.db。2.3 在 Reasonix Code 中手动注册 MCP 服务由于 Reasonix Code 未被自动配置工具识别需要手动添加 MCP 服务配置。Reasonix Code 的add_mcp_server工具可以自动完成此操作{ name: codegraph, transport: stdio, command: codegraph, args: [serve, --mcp] }注册成功后重启 Reasonix Code 即可生效。可通过codegraph_codegraph_status工具验证索引状态。三、CodeGraph 提供的工具集CodeGraph 注册后暴露以下 MCP 工具工具名用途对标传统操作codegraph_context首要调用— 输入任务描述返回入口点 相关符号 代码相当于search_contentread_file组合codegraph_trace追踪两个符号之间的调用路径需要手动逐层阅读代码推理codegraph_explore一次查询获取多个文件的源码内联返回行号精确单个read_file× Ncodegraph_search按符号名快速搜索search_filescodegraph_callers列出调用某个函数的所有调用者search_content搜方法名codegraph_callees列出某个函数调用的所有子函数逐行阅读代码codegraph_impact修改某个符号前分析影响范围手动 grep 推理codegraph_node获取单个符号的详细信息read_file定位codegraph_files展示项目文件树directory_treecodegraph_status查看索引健康状态—四、实测对比方案测试任务追踪PUT /system/colonelActivity/changeSyncProduct接口的完整后端调用链路。需要回答HTTP 请求从进入 Spring Boot 到最终响应经过了哪些拦截器/过滤器Controller → Service → Mapper 的每一层调用了什么方法当isSyncProductY时RocketMQ 消息是如何被发出的涉及哪些异常/校验逻辑操作日志如何被记录衡量指标工具调用次数实际文件读取数答案完整性与准确性基线流程未安装 CodeGraph阅读SysColonelActivityController.java→ 发现调用了colonelActivityService.changeSyncProduct()阅读ISysColonelActivityService.java→ 发现接口定义阅读SysColonelActivityServiceImpl.java→ 理解业务逻辑、事务、校验、分支路径发现调用productSyncService.sendNonPendingActivityProductSyncMessage()→ 阅读DoudianColonelActivityProductSyncService.java发现调用mqProducer.sendAsyncMessage()→ 阅读MqProducer.java查看MqTopicConstant.java→ 确认 Topic 名称查看SecurityConfig.java→ 理解过滤器链查看JwtAuthenticationTokenFilter.java→ JWT 认证流程查看PermissionService.java→PreAuthorize权限校验查看LogAspect.java→Log操作日志 AOP查看GlobalExceptionHandler.java→ 异常处理查看BaseController.java→getUsername()/toAjax()父类方法查看SysColonelActivityMapper.java→ MyBatis-Plus Mapper查看ColonelActivitySyncProductUpdateParam.java→ 参数校验注解手动整合各层调用关系CodeGraph 流程codegraph_context— 输入任务描述自动返回入口点 相关符号 代码片段覆盖 3 个文件源码codegraph_trace(changeSyncProduct, sendNonPendingActivityProductSyncMessage)— 自动输出完整调用路径codegraph_explore— 一次查询返回 8 个关键文件的完整源码SecurityConfig、PermissionService、MqProducer、BaseController 等codegraph_explore— 另一次查询补充 LogAspect、GlobalExceptionHandler、SysColonelActivityServiceImpl、SysColonelActivityMapper五、实测数据对比指标未安装 CodeGraph基线已安装 CodeGraph提升幅度工具调用总数16 次5 次↓69%read_file 调用12 次0 次↓100%search_content 调用1 次0 次↓ 100%search_files 调用3 次0 次↓ 100%codegraph_* 调用0 次5 次—文件读取数12 个0 个源码内联↓100%调用链串联方式手动逐层推理trace一键自动输出答案完整性覆盖 7 层覆盖 7 层持平 ✅文件行号准确性全部精确全部精确持平 ✅核心体验差异1. 零文件读取 — 从 12 次 read_file 降为 0基线时需要逐个文件打开阅读SysColonelActivityController.java → ISysColonelActivityService.java → SysColonelActivityServiceImpl.java → DoudianColonelActivityProductSyncService.java → MqProducer.java → SecurityConfig.java → JwtAuthenticationTokenFilter.java → PermissionService.java → LogAspect.java → GlobalExceptionHandler.java → BaseController.java → SysColonelActivityMapper.javaCodeGraph 通过codegraph_explore批量将源码内联到工具响应中无需手动 read_file。2. 调用链一键追踪基线时需手动推理每层的调用关系。codegraph_trace一个调用自动输出changeSyncProduct (Controller:62) ↓ 71 calls sendNonPendingActivityProductSyncMessage (Service:103) ↓ 105 calls sendActivityProductSyncMessage (Service:120) ↓ 123 calls MqProducer.sendAsyncMessage (MqProducer:58-81) ↓ calls RocketMQTemplate.asyncSend(topic, message, callback) → Topic: ruoyi-doudian-colonel-activity-product-sync-topic3. 调用关系一目了然codegraph_context自动列出changeSyncProduct调用的所有子方法路径无需逐行扫描。六、CodeGraph 完整的 7 层调用链路测试答案第 1 层Spring Security 过滤器链SecurityConfig.filterChain() [SecurityConfig.java:97] ├─ CorsFilter (跨域) [line 162-163] ├─ JwtAuthenticationTokenFilter (JWT 认证) [JwtAuthenticationTokenFilter.java:31] │ └─ TokenService.getLoginUser(request) → 解析 JWT Token │ └─ TokenService.verifyToken(loginUser) → 刷新 Token 有效期 │ └─ 设置 SecurityContextHolder → 注入 LoginUser └─ PreAuthorize 拦截 [SecurityConfig.java:29 EnableMethodSecurity]第 2 层权限校验PreAuthorize(ss.hasPermi(system:colonelActivity:edit)) └─ PermissionService.hasPermi() [PermissionService.java:27] └─ SecurityUtils.getLoginUser() → 从 SecurityContext 获取 └─ loginUser.getPermissions() → 获取用户权限集 └─ hasPermissions(permissions, permission) → 检查是否包含含 ALL_PERMISSION 超级权限 └─ 失败 → AccessDeniedException └─ GlobalExceptionHandler.handleAccessDeniedException() → 403第 3 层参数校验Validated RequestBody ColonelActivitySyncProductUpdateParam activityRecordId: NotNull(message 活动记录ID不能为空) isSyncProduct: NotBlank Pattern(regexp ^[YN]$) └─ 校验失败 → MethodArgumentNotValidException └─ GlobalExceptionHandler.handleMethodArgumentNotValidException() → 返回错误信息第 4 层Controller 入口SysColonelActivityController.changeSyncProduct() [Controller.java:62] ├─ PreAuthorize(ss.hasPermi(system:colonelActivity:edit)) ├─ Log(title 团长活动管理, businessType BusinessType.UPDATE) ├─ PutMapping(/changeSyncProduct) ├─ int rows colonelActivityService.changeSyncProduct(param, getUsername()) ├─ if (rows 0 YES.equals(param.getIsSyncProduct())) │ └─ productSyncService.sendNonPendingActivityProductSyncMessage(activityRecordId) └─ return toAjax(rows) → BaseController.toAjax() [BaseController.java:161]第 5 层Service 业务逻辑SysColonelActivityServiceImpl.changeSyncProduct() [ServiceImpl.java:64] ├─ Transactional(rollbackFor Exception.class) ├─ requireActivity(activityRecordId) → 校验活动记录存在 authId/activityId 非空 ├─ assertSelfOwnedColonel(activity) → [Y 路径] 校验授权未过期 自有团长 │ └─ colonelAuthService.getById(authId) ├─ updateById(activity) → 写入 DBupdate_time, update_by └─ [Y→N 转换路径] 清理关联数据 ├─ colonelActivityProductService.deleteByActivityRecordId() ├─ talentProductDetailService.deleteByActivityRecordId() ├─ productSkuService.clearProductSkus() └─ pendingProductService.deleteByActivityRecordId()第 6 层RocketMQ 消息发送Y 路径DoudianColonelActivityProductSyncService └─ sendNonPendingActivityProductSyncMessage(id) [SyncService.java:103] └─ sendActivityProductSyncMessage(id, NON_PENDING) [SyncService.java:120] └─ mqProducer.sendAsyncMessage(topic, jsonMsg) [SyncService.java:123] └─ MqProducer.sendAsyncMessage() [MqProducer.java:58] └─ rocketMQTemplate.asyncSend(topic, message, callback) └─ Topic: ruoyi-doudian-colonel-activity-product-sync-topic第 7 层操作日志AOP 切面LogAspect [LogAspect.java] ├─ Before: doBefore() → 记录开始时间 (ThreadLocal) ├─ AfterReturning: doAfterReturning() └─ handleLog() → 构建 SysOperLog ├─ 获取用户、IP、URL、方法名 ├─ 读取 Log 注解title团长活动管理, businessTypeUPDATE ├─ 序列化请求参数 / 返回值 └─ AsyncManager.me().execute(AsyncFactory.recordOper(operLog)) → 异步写入数据库