CallGraph MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@CallGraph MCP Servershow all methods that call calculateTotal()"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
CallGraph MCP Server
MCP server for analyzing call graphs in Axelor projects using ASM bytecode analysis.
What is this?
A Model Context Protocol (MCP) server that lets Claude Code intelligently query your project's call graph:
Find where methods/classes are used
Analyze change impact
Navigate dependencies
Trace call chains across Java bytecode
Key Features:
ASM bytecode analysis instead of source parsing (100% accurate)
SQLite relational database instead of vector database
Gradle dependency discovery for automatic Axelor package detection
Smart caching with SHA256-based invalidation
Related MCP server: CodeGB
Quick Start
1. Install dependencies
pip install -r requirements.txt2. Configure Claude Code
Add to your .claude/mcp.json or claude_desktop_config.json:
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"sqlite-callgraph": {
"command": "uvx",
"args": ["mcp-server-sqlite", "--db-path", "C:/path/to/project/.callgraph.db"]
}
}
}3. Extract your project's call graph
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 100This creates .callgraph.db in your project directory.
Modes:
Default (Incremental): Smart caching - only re-extracts modified packages
--init: Full reset - drops all tables and rebuilds from scratch
4. Restart Claude Desktop
The MCP server provides direct SQLite access to the call graph database.
Architecture Overview
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_ofComponents
1. run_asm_extraction.py
CLI entry point for the extraction pipeline.
Usage:
# 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 100Modes:
Incremental (default): Uses SHA256 caching - only re-extracts modified packages
--init: Full reset - drops all tables and rebuilds from scratch
Process (always runs both steps):
Package Discovery via
GradleDependencyManager(Gradle)Symbol Indexing via
ASMExtractor.build_symbol_index()(FQN → URI)Call Graph Extraction via
ASMExtractor.extract()(Nodes + Edges)
2. GradleDependencyManager.py
Discovers and manages Axelor dependencies via Gradle.
Features:
Query Gradle for runtime JAR dependencies (Axelor only)
Extract JARs to
axelor-repos/cache directoryProvide package metadata (group, artifact, version, jar, sources, classes)
Cache Structure:
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 client for ASMAnalysisService with SQLite storage.
Database Schema:
-- 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
);Constructor:
ASMExtractor(db_path=".callgraph.db", service_url="http://localhost:8766", init=False)init=True: Full reset - drops and recreates all tables (INIT mode)init=False(default): Incremental mode - creates tables if they don't exist
Key Methods:
init_database(): Full reset - drops and recreates all tables (called automatically when init=True)clean_package_data(package_name): Removes all data for a specific package (used automatically in incremental mode)build_symbol_index(): Builds FQN → URI mapping with automatic cache invalidationextract(): Extracts call graph from bytecode
Performance:
Symbol indexing: ~6 minutes for 39 packages (107k symbols, 9.4k classes)
Call graph extraction: ~40 seconds for 9,466 .class files (252 files/sec)
Total extraction (--init): ~6-7 minutes complete project
Incremental mode: Only re-extracts modified packages (70%+ speedup on subsequent runs)
Optimizations:
Batch SQL queries (IN clauses): 99.95% reduction in database queries
Before: ~650k queries → After: ~220 queries
Insertions by batches of 5000 rows
4. ASMAnalysisService (Java)
REST service for analyzing Java bytecode using ASM.
Technology:
ASM: Bytecode manipulation framework
Spark Java: Lightweight HTTP framework
Jackson: JSON serialization
Endpoints:
GET /health- Health checkPOST /index- Extract symbols (classes AND methods) with nodeType and linePOST /analyze- Extract complete call graph with metadataPOST /shutdown- Gracefully shut down the service
Extracted Metadata:
Class modifiers (public, abstract, final, etc.)
Method modifiers and visibility
Annotations:
@Override,@Transactional(Spring, Jakarta, javax)Line numbers for methods
Inheritance relationships
Method calls with line numbers
Running the Service:
cd Extracteurs/ASMAnalysisService
./gradlew.bat run
# Service starts on port 8766
# Logs written to asm-service.logMCP Tools (SQLite)
Use your configured SQLite MCP server with direct SQL queries.
Query Examples
Find methods using class X as argument:
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;Find all calls to a method:
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;Count symbols by 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;Find transactional methods:
SELECT fqn, package, line
FROM nodes
WHERE type = 'method' AND is_transactional = 1
ORDER BY package, line;Find public methods with @Override:
SELECT fqn, package, line
FROM nodes
WHERE type = 'method' AND visibility = 'public' AND has_override = 1
ORDER BY package, line;Comparison: JavaParser vs ASM
Feature | JavaParser (Old) | ASM (New) |
Input | Source code (.java) | Bytecode (.class) |
Requires sources | Yes | No (works with JARs) |
Analysis speed | Slower (parsing) | Faster (bytecode) |
Accuracy | Source-level | Bytecode-level (100%) |
Dependencies | Manual download | Gradle auto-discovery |
Storage | ChromaDB (~150 MB) | SQLite (~50 MB) |
Query speed | ~50ms | ~10ms |
Benefits of ASM Approach
No source code required: Works directly with JARs from Maven/Gradle cache
Automatic dependency discovery: Gradle integration
100% accurate: Bytecode analysis reflects actual compilation
Faster: No parsing overhead
Smaller database: Relational storage vs vector embeddings
Better caching: SHA256-based invalidation
Simpler queries: SQL vs vector similarity search
Performance
Extraction Times (Real Project - 39 Packages)
Full Extraction (--init): ~6-7 minutes total
STEP 1 (Gradle discovery): ~10 seconds
STEP 2 (Symbol indexing): ~6 minutes for 107k symbols
STEP 3 (Call graph extraction): ~40 seconds for 9,466 .class files (252 files/sec)
Incremental Mode: Only re-extracts modified packages (70%+ speedup)
Database Stats
Real Project Example:
Size: ~292 MB
Symbols: 107,312 (9,466 classes + 97,846 methods)
Edges: 319,272 (calls, inheritance, member_of)
Packages: 39 Axelor packages
Entities: 2,089 (22% of classes)
Database Contents:
symbol_index: 107,312 rows (~60 MB)nodes: 94,267 rows (~52 MB)edges: 319,272 rows (~180 MB)
Query Performance
Simple queries (COUNT, SELECT WHERE): ~10ms
Complex joins (call chains): ~50-100ms
Full-text search (LIKE): ~20-30ms
Troubleshooting
ASMAnalysisService not starting
Solutions:
Check Java:
java -version(need Java 11+)Build service:
cd Extracteurs/ASMAnalysisService && gradlew.bat buildStart manually:
gradlew.bat service:run
Cache not detected
Verification:
ls axelor-repos/axelor-core-7.2.6/classes/
# Should contain .class filesFQN resolution fails or stale data
Solution:
Full reset:
python run_asm_extraction.py /path/to/project --initThis drops all tables and rebuilds from scratch
Kill stuck Java processes
# Windows
wmic process where "name='java.exe' and CommandLine like '%ASMAnalysisService%'" deleteDevelopment
Project Structure
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 packagesFile Naming Conventions
PascalCase for Python files (matches main class):
ASMExtractor.py→class ASMExtractorGradleDependencyManager.py→class GradleDependencyManager
License
MIT
Resources
ASM_ARCHITECTURE.md - Detailed technical architecture
This server cannot be deployed
Maintenance
Related MCP Connectors
Codebase graphs, caller impact analysis, and recorded project context for AI coding agents.
AI-powered codebase analysis — call graphs, security, dead code, complexity. 150+ tools.
AI Agent with Architectural Memory. Impact analysis (free), tests and code from the graph (pro).
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Related MCP Servers
- AlicenseAqualityDmaintenanceAnalyzes software projects to extract architecture, build dependency graphs, and predict the impact of code changes.241MIT
- FlicenseNot gradedqualityFmaintenanceProvides a local code knowledge graph for Java projects, enabling querying of classes, methods, fields, calls, inheritance, and imports via MCP tools like query, context, impact, and cypher.1-
- FlicenseNot gradedqualityBmaintenanceEnables querying a Neo4j-based code graph for Python projects, providing tools for code structure, call graph, and test coverage analysis.1-
- FlicenseNot gradedqualityCmaintenanceAnalyzes Java codebases using an internal Knowledge Graph stored in SQLite, enabling symbol search, endpoint tracing, and impact analysis without requiring AI APIs.-