CallGraph MCP服务器
MCP服务器,用于使用ASM字节码分析分析Axelor项目中的调用图。
这是什么?
一个模型上下文协议(MCP)服务器,允许Claude Code智能地查询项目的调用图:
- 查找方法/类的使用位置
- 分析变更影响
- 导航依赖关系
- 跨Java字节码跟踪调用链
主要特点:
- ASM字节码分析 而不是源解析(100%准确)
- SQLite关系数据库 代替矢量数据库
- Gradle依赖关系发现 用于自动Axelor包裹检测
- 智能缓存 基于SHA256的失效
快速开始
1.安装依赖项
pip install -r requirements.txt2.配置克劳德代码
添加到您的 .claude/mcp.json 或 claude_desktop_config.json:
视窗: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sqlite-callgraph": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db-path", "C:/path/to/project/.callgraph.db"]
}
}
}3.提取项目的调用图
cd /path/to/your/axelor/project
# Incremental extraction (default, uses cache)
python /path/to/CallGraph/run_asm_extraction.py .
# Full reset (first time or after schema changes)
python /path/to/CallGraph/run_asm_extraction.py . --init
# Limit extraction for testing (requires --init)
python /path/to/CallGraph/run_asm_extraction.py . --init --limit 100这创造了 .callgraph.db 在您的项目目录中。
模式:
- 默认值(增量):智能缓存-仅重新提取修改过的包
- --init:完全重置-删除所有表并从头开始重建
4.重新启动克劳德桌面
MCP服务器提供对调用图数据库的直接SQLite访问。
架构概述
Project (.callgraph.db SQLite database)
↓ Extraction via
run_asm_extraction.py
├─> GradleDependencyManager # Auto-discover Axelor deps
└─> ASMExtractor # Python client
↓ REST API
ASMAnalysisService (Java) # Port 8766
↓ ASM ClassVisitor
Bytecode Analysis (.class files)
↓ Storage
SQLite Tables:
├─> symbol_index # FQN → URI → package
├─> nodes # classes, methods
└─> edges # calls, inheritance, member_of组件
1. run_asm_extraction.py
提取管道的CLI入口点。
用法:
# Incremental extraction (default, uses cache)
python run_asm_extraction.py /path/to/project
# Full reset (first time or after schema changes)
python run_asm_extraction.py /path/to/project --init
# Limit extraction for testing (requires --init to avoid partial data)
python run_asm_extraction.py /path/to/project --init --limit 100模式:
- 增量(默认):使用SHA256缓存-仅重新提取修改过的包
- --init:完全重置-删除所有表并从头开始重建
过程(始终运行两个步骤):
- 包发现 通过
GradleDependencyManager(Gradle) - 符号索引 通过
ASMExtractor.build_symbol_index()(FQN→类型) - 调用图提取 通过
ASMExtractor.extract()(节点+边)
______________________________________________________________________
2. GradleDependencyManager.py
通过Gradle发现和管理Axelor依赖关系。
特性:
- 查询Gradle以获取运行时JAR依赖关系(仅限Axelor)
- 提取JAR文件
axelor-repos/缓存目录 - 提供包元数据(组、工件、版本、jar、源代码、类)
缓存结构:
axelor-repos/
├── axelor-core-7.2.6/
│ ├── classes/ # .class files from JAR
│ └── sources/ # .java files from sources JAR
└── axelor-base-8.2.9/
├── classes/
└── sources/______________________________________________________________________
3. ASMExtractor.py
Python客户端 ASMAnalysisService 使用SQLite存储。
数据库模式:
-- Symbol index (FQN → URI → package)
CREATE TABLE symbol_index (
fqn TEXT PRIMARY KEY,
uri TEXT NOT NULL,
package TEXT NOT NULL,
line INTEGER -- Line number (methods only)
);
-- Nodes (classes and methods)
CREATE TABLE nodes (
fqn TEXT PRIMARY KEY,
type TEXT NOT NULL, -- 'class', 'interface', 'enum', 'method'
package TEXT NOT NULL,
line INTEGER,
visibility TEXT, -- 'public', 'private', 'protected', 'package'
has_override BOOLEAN, -- TRUE if @Override annotation present
is_transactional BOOLEAN -- TRUE if @Transactional annotation present
);
-- Edges (relationships)
CREATE TABLE edges (
id INTEGER PRIMARY KEY AUTOINCREMENT,
from_fqn TEXT NOT NULL,
edge_type TEXT NOT NULL, -- 'call', 'inheritance', 'member_of'
to_fqn TEXT NOT NULL,
kind TEXT, -- 'invoke', 'extends', 'implements', 'argument', 'return'
from_package TEXT NOT NULL,
to_package TEXT NOT NULL,
from_line INTEGER
);构造函数:
ASMExtractor(db_path=".callgraph.db", service_url="http://localhost:8766", init=False)init=True:完全重置-删除并重新创建所有表(INIT模式)init=False(默认):增量模式-如果表不存在,则创建表
关键方法:
init_database():完全重置-删除并重新创建所有表(当init=True时自动调用)clean_package_data(package_name):删除特定包的所有数据(在增量模式下自动使用)build_symbol_index():构建FQN→ 具有自动缓存无效的URI映射extract():从字节码中提取调用图
演出:
- 符号索引:39个包(107k个符号,9.4k个类别)约6分钟
- 调用图提取:9466.class文件约40秒(252个文件/秒)
- 总提取时间(--init):~6-7分钟完成项目
- 增量模式:仅重新提取修改过的包(后续运行速度提高70%以上)
优化:
- 批处理SQL查询(IN子句):数据库查询减少99.95%
- 之前:约65万次查询→ 之后:约220次查询
- 按5000行批量插入
______________________________________________________________________
4. ASMAnalysisService Java
使用ASM分析Java字节码的REST服务。
技术:
- ASM:字节码操作框架
- Spark Java:轻量级HTTP框架
- 杰克逊:JSON序列化
端点:
GET /health-健康检查POST /index-使用nodeType和line提取符号(类和方法)POST /analyze-使用元数据提取完整的调用图POST /shutdown-优雅地关闭了服务
提取的元数据:
- 类修饰符(public、abstract、final等)
- 方法修饰符和可见性
- 注释:
@Override,@Transactional(春季,雅加达,javax) - 方法的行号
- 继承关系
- 带有行号的方法调用
运行服务:
cd Extracteurs/ASMAnalysisService
./gradlew.bat run
# Service starts on port 8766
# Logs written to asm-service.log______________________________________________________________________
MCP工具(SQLite)
使用您配置的SQLite MCP服务器进行直接SQL查询。
查询示例
查找使用类X作为参数的方法:
SELECT DISTINCT e.to_fqn AS method_fqn, e.from_fqn AS argument_type
FROM edges e
WHERE e.edge_type = 'member_of' AND e.kind = 'argument'
AND e.from_fqn = 'com.axelor.apps.openauction.db.Lot'
ORDER BY e.to_fqn;查找对某个方法的所有调用:
SELECT e.from_fqn AS caller, e.to_fqn AS callee, e.from_line AS line, e.from_package
FROM edges e
WHERE e.edge_type = 'call' AND e.to_fqn LIKE '%setStatus%'
ORDER BY e.from_package;按包装计数符号:
SELECT package, COUNT(*) as symbol_count,
SUM(CASE WHEN type = 'class' THEN 1 ELSE 0 END) as class_count,
SUM(CASE WHEN type = 'method' THEN 1 ELSE 0 END) as method_count
FROM nodes
GROUP BY package ORDER BY symbol_count DESC;查找事务处理方法:
SELECT fqn, package, line
FROM nodes
WHERE type = 'method' AND is_transactional = 1
ORDER BY package, line;使用@Override查找公共方法:
SELECT fqn, package, line
FROM nodes
WHERE type = 'method' AND visibility = 'public' AND has_override = 1
ORDER BY package, line;______________________________________________________________________
比较:JavaParser与ASM
| 特性 | JavaParser(旧) | ASM(新) |
|---|---|---|
| 输入 | 源代码(.java) | 字节码(.class) |
| 需要来源 | 是 | 否(适用于JAR) |
| 分析速度 | 较慢(解析) | 较快(字节码) |
| 准确度 | 源代码级别 | 字节码级别(100%) |
| 依赖项 | 手动下载 | Gradle自动发现 |
| 存储 | ChromaDB(约150 MB) | SQLite(约50 MB) |
| 查询速度 | ~50ms | ~10ms |
______________________________________________________________________
ASM方法的好处
- 无需源代码:直接使用Maven/Gradle缓存中的JAR
- 自动依赖关系发现:Gradle集成
- 100%准确:字节码分析反映了实际编译
- 更快:无解析开销
- 较小的数据库:关系存储与向量嵌入
- 更好的缓存:基于SHA256的失效
- 更简单的查询:SQL与向量相似性搜索
______________________________________________________________________
演出
提取时间(实际项目-39个包)
完全提取(--init):总共约6-7分钟
- 第一步(Gradle发现):约10秒
- 第2步(符号索引):107k个符号约6分钟
- 步骤3(调用图提取):9466.class文件约40秒(252个文件/秒)
增量模式:仅重新提取修改过的包(速度提高70%以上)
数据库统计信息
实际项目示例:
- 尺寸:约292 MB
- 符号:107312(9466个类+97846个方法)
- 边缘:319272(调用、继承、member_of)
- 包裹:39个阿克塞尔包
- 实体:2089(占班级总数的22%)
数据库内容:
symbol_index:107312行(约60 MB)nodes:94267行(约52 MB)edges:319272行(约180 MB)
查询性能
- 简单查询(COUNT、SELECT WHERE):~10ms
- 复杂连接(调用链):~50-100ms
- 全文搜索(LIKE):约20-30ms
______________________________________________________________________
故障排除
ASMAnalysisService未启动
解决方案:
- 检查Java:
java -version(需要Java 11+) - 构建服务:
cd Extracteurs/ASMAnalysisService && gradlew.bat build - 手动启动:
gradlew.bat service:run
未检测到缓存
验证:
ls axelor-repos/axelor-core-7.2.6/classes/
# Should contain .class filesFQN解析失败或数据过时
解决方案:
- 完全重置:
python run_asm_extraction.py /path/to/project --init - 这将删除所有表并从头开始重建
杀死卡住的Java进程
# Windows
wmic process where "name='java.exe' and CommandLine like '%ASMAnalysisService%'" delete______________________________________________________________________
发展
项目结构
CallGraph/
├── run_asm_extraction.py # CLI entry point
├── mcp_callgraph_server.py # Legacy MCP server
├── mcp.json # MCP configuration
├── ASM_ARCHITECTURE.md # Detailed architecture
├── Extracteurs/
│ ├── GradleDependencyManager.py # Gradle integration
│ ├── ASMExtractor.py # Python client
│ └── ASMAnalysisService/ # Java service
│ └── service/ # Kotlin/Gradle implementation
└── axelor-repos/ # Cached Axelor packages文件命名约定
帕斯卡命名法 对于Python文件(匹配主类):
ASMExtractor.py→class ASMExtractorGradleDependencyManager.py→class GradleDependencyManager
______________________________________________________________________
许可证
麻省理工学院
资源
- ASM_建筑.md -详细的技术架构
- ASM文件
- Spark Java
- SQLite
- MCP协议
