cpp-semantic-graph
Provides tools for semantic analysis of C++ codebases, enabling AI to search class definitions, inheritance hierarchies, call chains, function overrides, file symbols, and traverse the code graph, with support for incremental updates and documentation linking.
Click on "Install 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., "@cpp-semantic-graphWhere is class SocUpdate defined?"
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.
cpp-semantic-graph
A C++ semantic knowledge graph — let AI understand your C++ codebase precisely
Builds a semantic knowledge graph of a C++ codebase for AI coding assistants (Claude Code, Cursor, Windsurf, etc.) and exposes it through 9 query tools over the MCP protocol. The AI can then search class definitions, look up inheritance, trace call chains, and analyze the blast radius of a change — no file hopping, no grep.
Why this project exists: clang, not tree-sitter
Most general-purpose code-graph tooling parses source with tree-sitter — a fast, incremental syntax parser. That choice is fine for many languages, but it is the wrong tool for a C++ semantic graph.
The distinction is syntax vs. semantics:
A syntax parser answers "do these tokens form a valid C++ program, and what does the tree look like?" — it does not resolve what a name refers to.
Semantic analysis (what a compiler front-end does) answers "which entity does this symbol denote, what is its type, and how does it relate to others?" — this requires type resolution and name lookup.
C++ is a language where a great deal of information lives in the type system, not on the page. Consider:
namespace nv {
struct Base { virtual void PerformUpgrade() = 0; };
template<typename T> struct Middle : virtual Base { // virtual inheritance + template
void PerformUpgrade() override {}
};
struct SoCUpdate : Middle<SoC>, NonCopyable, public Logger {}; // multiple inheritance
}A syntax parser (tree-sitter) can see that SoCUpdate is a class followed by
three base-specifier text fragments. It cannot determine:
That
Middle<SoC>is the specializationnv::Middle<SoC>— requires template instantiation.Which namespace
Loggerlives in — requires name lookup.That the root of the chain is
virtual Base— requires expanding the template and following the referenced declaration.Which base-class method
PerformUpgrade() overrideactually overrides — requires cross-class virtual-function matching.
These all require type resolution, which is exactly what a compiler front-end (clang) provides and what a syntax parser structurally cannot. This is not tree-sitter being "bad" — it is intentionally type-free, single-file, and fast, designed for syntax highlighting and code folding. Using it to build a C++ semantic graph is simply the wrong tool for the job.
This project uses clang/libclang's semantic AST instead. The difference is visible in the parser:
base_spec.referenced— resolves a base class to its real declaration cursor across files and namespaces (parser/ast_visitor.py).clang_isVirtualBase— detects virtual inheritance, the C++-specific diamond-inheritance semantics that syntax trees have no notion of.cursor.is_virtual_method()/is_pure_virtual_method()— virtual-function semantics.access_specifier— distinguishes public/protected/private inheritance.Cross-TU override matching — base and derived classes often live in different files; clang's
referencedcursor links them, which a per-file syntax parse cannot.
Related MCP server: CodeGraph
Why do you need it?
Common pain points when an AI assistant tries to understand C++ code:
Pain point | cpp-semantic-graph's answer |
"Where is this class defined?" |
|
"Who calls this function?" |
|
"What does changing this header affect?" | Incremental update recursively walks include deps, re-parses only affected TUs |
"Which overrides exist for this virtual?" |
|
"What does this module's architecture look like?" |
|
✨ Core features
9 MCP tools: class search, function search, inheritance, call chains (caller/callee), overrides, file symbols, multi-hop traversal, doc search
Incremental updates: based on the include-dependency graph, a single
.cppchange refreshes in seconds (16× faster than a full rebuild)Doc fusion: bidirectional linking between project docs and code; searching docs auto-locates related code
Plug-and-play: one YAML config +
compile_commands.jsonto start; the MCP server auto-registers with AI toolsProject-agnostic: no project-specific hardcoding in the schema or tool definitions — portable to any C++ project
🚀 Quick start
Prerequisites
Python 3.10+
libclang (matching your LLVM version)
compile_commands.json(generated by CMake/Bear)
1. Install
git clone https://github.com/FS-Yuao/cpp-semantic-graph.git
cd cpp-semantic-graph
# 一键创建 venv 并安装核心依赖 (推荐)
./setup_env.sh
# 默认在项目内创建 .venv;可选:
# ./setup_env.sh /path/to/venv 指定 venv 路径
# ./setup_env.sh --with-docs 同时装 doc embedding 依赖 (含 torch,体积大)
# 或手动创建:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt前置: 系统 libclang (匹配 LLVM 版本;Ubuntu:
apt install libclang-18-dev)。 clang bindings 版本须与系统 libclang 一致 (本机 libclang-18 对应clang>=18,<19,换 LLVM 版本时同步改requirements.txt)。
2. Prepare compile_commands.json
If your project builds with CMake:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...Without CMake, use Bear to intercept build commands:
bear -- make3. Write the config file
Create cpp_semantic_graph.yaml (the only file you need to edit):
project:
name: "your_project"
compile_commands: "/path/to/your/project/compile_commands.json"
# Source scope — decides what counts as "project code"
source_paths:
- "src"
- "include"
# Generated-code paths (e.g. ARA COM src-gen, protobuf)
generated_paths:
- "src-gen"
# Paths to ignore entirely
exclude_paths:
- "thirdparty"
- "build"
- "test/mock"
# libclang path (adjust for your system)
libclang_path: "/usr/lib/llvm-18/lib/libclang.so.1"
parse_options:
skip_function_bodies: false # must be false to extract call relations
max_workers: 4 # parallel parse processes4. Full parse
⚠️ Important: stop the MCP server before a full parse, or the DB connection it holds will cause write failures (
disk I/O error). Stop withpkill -f "run_server.py", or disable the MCP server in Claude Code settings and restart.
# 1. Stop the MCP server (required!)
pkill -f "run_server.py"
# 2. Full parse
python3 -m cpp_semantic_graph full-parse \
--config cpp_semantic_graph.yaml \
--db semantic_graph_full.db
# 3. Restart the MCP server (after parsing finishes)After parsing, the database contains:
Nodes: classes, structs, functions (with signature, namespace, file location)
Edges: inheritance, calls, overrides, belongs_to, type aliases (
type_alias), using-declarations (using_decl), friends (friend_of), etc. (theinstantiatestemplate-instantiation edge is not yet enabled due to libclang AST shape — see Complex scenarios)Include dependencies: the include graph between translation units
Doc associations: doc sections ↔ code entities (optional)
5. Start the MCP server
# Set the database path
export CPP_GRAPH_DB=/path/to/semantic_graph_full.db
# Start the MCP server (stdio transport)
python3 -m cpp_semantic_graph.mcp_server.server6. Register with AI tools
Claude Code
Edit ~/.claude.json, add under mcpServers:
{
"mcpServers": {
"cpp-semantic-graph": {
"type": "stdio",
"command": "python3",
"args": ["/absolute/path/to/cpp-semantic-graph/mcp_server/run_server.py"],
"env": {
"CPP_GRAPH_DB": "/absolute/path/to/semantic_graph_full.db"
}
}
}
}Cursor
Edit .cursor/mcp.json:
{
"mcpServers": {
"cpp-semantic-graph": {
"command": "python3",
"args": ["/absolute/path/to/cpp-semantic-graph/mcp_server/run_server.py"],
"env": {
"CPP_GRAPH_DB": "/absolute/path/to/semantic_graph_full.db"
}
}
}
}Windsurf / other MCP clients
Configuration is similar; refer to each tool's MCP docs. The core parameters:
command:
python3args:
["/path/to/mcp_server/run_server.py"]env.CPP_GRAPH_DB: absolute path to the database
💡 Tip: the
CPP_GRAPH_PROJECTenv var sets the project name (used in MCP instructions); if unset it is inferred from the DB path.
🛠️ 11 MCP tools
# | Tool | Purpose | Typical scenario |
1 |
| Search class definitions by name | "Where is SocUpdate defined?" |
2 |
| Search function definitions by name | "What's the signature of PerformUpgrade?" |
3 |
| Query a class's inheritance | "Which classes derive from BasePeriUpdate?" |
4 |
| Who calls a given function | "Who calls GetSocBootChain?" |
5 |
| What a given function calls | "What does PerformUpgrade call internally?" |
6 |
| All overrides of a virtual function | "Which overrides exist for PerformUpgrade?" |
7 |
| All symbols in a file | "What's in soc_update.cpp?" |
8 |
| Multi-hop graph traversal | "What does changing SocUpdate affect?" |
9 |
| Search project docs (-> related code) | "The OTA upgrade-flow design doc" |
10 |
| Blast radius of a change (recursive callers + override expansion + file aggregation) | "I'm changing PerformUpgrade — which files must I review?" |
11 |
| Reverse: code symbol -> docs describing it | "What design docs describe PerformUpgrade?" |
Tool details
cpp_search_class(name, exact=False)
Search C++ class definitions by name. Supports fuzzy matching.
cpp_search_class("SocUpdate")
-> ## Search results: class "SocUpdate" (1)
### update::SocUpdate
- File: soc_update.h:15-120cpp_search_function(name, class_name="")
Search function definitions by name. Optionally restrict by owning class.
cpp_search_function("PerformUpgrade", class_name="SocUpdate")
-> ## Search results: function "PerformUpgrade" (1)
### SocUpdate::PerformUpgrade [virtual, override]
- Signature: void PerformUpgrade() override
- File: soc_update.cpp:45cpp_get_inheritance(class_name, direction="down", depth=1)
Query inheritance. direction="down" for subclasses, "up" for base classes. depth=-1 recurses fully.
cpp_get_inheritance("BasePeriUpdate", direction="down", depth=-1)
-> ## Subclasses of BasePeriUpdate (4)
- update::SocUpdate --public--> BasePeriUpdate
- update::McuUpdate --public--> BasePeriUpdate
- ...cpp_get_callers(function_name, class_name="")
Who calls a given function (impact analysis).
cpp_get_callers("GetSocBootChain")
-> ## Code that calls "GetSocBootChain" (3)
### OtaManager::CheckBootChain
- File: ota_manager.cpp:128
- Call type: calls_directcpp_get_callees(function_name, class_name="")
What a given function calls (call-chain analysis).
cpp_get_callees("PerformUpgrade", class_name="SocUpdate")
-> ## Code called by "PerformUpgrade" (8)
...cpp_get_overrides(function_name, class_name)
All override implementations of a virtual function. class_name is the base class that declares the virtual (required).
cpp_get_overrides("PerformUpgrade", class_name="BasePeriUpdate")
-> ## Overrides of "PerformUpgrade" (4)
### update::SocUpdate::PerformUpgrade
- Signature: void PerformUpgrade() override
- File: soc_update.cpp:45
- Overrides base: BasePeriUpdatecpp_get_file_symbols(file_path)
All class and function symbols in a file. file_path supports partial matching.
cpp_get_file_symbols("soc_update.h")
-> ## File symbols: soc_update.h (12 total)
### Classes/structs (2)
1. ### [class] update::SocUpdate
### Functions (10)
...cpp_traverse_graph(start, relation_types=None, direction="outgoing", depth=3, max_results=50)
Multi-hop graph traversal — the most flexible query. Walks related nodes along specified relation types.
Common relation types: inherits_public, inherits_protected, overrides, belongs_to, calls_direct, calls_virtual, calls_callback, doc_describes_code, code_refers_to_doc
cpp_traverse_graph("SocUpdate", depth=2, max_results=30)
-> ## Traversal results: from "SocUpdate" (18 nodes)
Depth: 2, edges traversed: 22
### Related nodes
- [class] update::SocUpdate (soc_update.h)
- [class] update::BasePeriUpdate (base_peri_update.h)
- [function] update::SocUpdate::PerformUpgrade (soc_update.cpp)
...cpp_search_docs(keyword, tag="", max_results=10, min_confidence=0.7)
Search project docs, returns doc sections + associated code.
cpp_search_docs("升级", tag="架构设计")
-> ## Doc search: "升级" (3 results)
### OTA complete upgrade flow
- File: docs/OTA_flow/OTA_COMPLETE_FLOW.md
- Word count: 2450
- Tags: 架构设计, OTA
Associated code:
- [class] BasePeriUpdate confidence=0.92
- [class] SocUpdate confidence=0.88Note: default min_confidence=0.7 filters low-quality co-occurrence associations
(confidence=0.6 makes up 63%, mostly noise like "刷写" matching Data/Response).
Pass 0.0 to see all associations.
cpp_get_code_docs(symbol, min_confidence=0.0, max_results=10)
Reverse lookup: given a code symbol, returns doc sections describing it (design
docs / HLD / architecture docs). Complement of cpp_search_docs — pass a code
symbol directly without thinking of keywords.
cpp_get_code_docs("PerformUpgrade")
-> ## Docs describing "PerformUpgrade" (6 sections)
### 3. Current flow
- Doc: SOC A/B partition switch design
- File: AB_Switch/AB_PARTITION_SWITCH_DESIGN.md:62-81
- Tags: 架构设计, A/B分区
### 4.3 Components
- File: ADC4.0_System_architecture/ADC4.0_OTA_SW_HLD.md:342-578
- Tags: 系统架构Note: reverse associations are mostly content_scan (confidence=0.6). Unlike
forward, code symbols appearing in docs are usually genuinely about them, so
0.6 is typically valid. Default returns all, rely on max_results to bound.
📖 CLI usage
Besides MCP tools, a CLI is provided for direct queries:
# Search a class
python3 -m cpp_semantic_graph search-class "SocUpdate"
# Query inheritance
python3 -m cpp_semantic_graph inheritance "BasePeriUpdate" --direction down --depth -1
# Search a function
python3 -m cpp_semantic_graph search-func "PerformUpgrade"
# File symbols
python3 -m cpp_semantic_graph file-symbols "soc_update.cpp"
# Include dependencies
python3 -m cpp_semantic_graph include "base_peri_update.h" --mode all
# DB stats
python3 -m cpp_semantic_graph statsIncremental update
After a code change, the incremental update re-parses only affected translation units:
# Based on git diff (default HEAD~1)
python3 -m cpp_semantic_graph incremental --base HEAD~1
# Specify files manually
python3 -m cpp_semantic_graph incremental --files soc_update.cpp,base_peri_update.h
# Detect only, don't execute
python3 -m cpp_semantic_graph incremental --files soc_update.cpp --dry-run
# Skip doc-association rebuild (faster)
python3 -m cpp_semantic_graph incremental --files soc_update.cpp --skip-associations📐 Architecture
┌─────────────────────────────────────────────────┐
│ AI tool layer │
│ Claude Code / Cursor / Windsurf / other MCP │
└────────────────────┬────────────────────────────┘
│ MCP protocol (stdio)
┌────────────────────▼────────────────────────────┐
│ MCP Server (9 tools) │
│ FastMCP + Lazy-init DB connection + Markdown │
└────────────────────┬────────────────────────────┘
│ Python API
┌────────────────────▼────────────────────────────┐
│ Query layer (query/) │
│ GraphQuery │ CallQuery │ PolymorphismQuery │
│ TraverseQuery │ DocQuery │ IncludeQuery │
└────────────────────┬────────────────────────────┘
│
┌────────────────────▼────────────────────────────┐
│ Data layer (db/) │
│ SQLite + 9 indexes + CASCADE constraints │
│ node │ edge │ include_dep │ parse_status │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Parser layer (parser/) │
│ AST Visitor (libclang) │ CompileDB │ Config │
│ ChangeDetector │ ImpactAnalyzer │
└─────────────────────────────────────────────────┘Core data model
Nodes (node table): classes, structs, functions — with namespace, file location, signature, etc.
Edges (edge table): relations between nodes; direction convention:
inherits: from=subclass → to=base classcalls: from=caller → to=calleebelongs_to: from=function → to=owning classoverrides: from=derived function → to=base function
include_dep table: include dependencies between translation units — the core basis for incremental updates.
🧩 Complex scenarios (template/alias/friend)
Feature | Relation edge | Status | Notes |
Type alias |
| ✅ Enabled | Alias node stored + edge links to target; when the target comes from an external library the edge may be dropped as dangling, but the alias node keeps |
using-declaration |
| ✅ Enabled | Subclass function → base function; this project's source has no ordinary using-declarations, only 1 literal operator not extracted |
Friend |
| ✅ Enabled | friend → host class; this project's source has no friend declarations, 0 edges as expected |
Template instantiation |
| ⏸️ Not yet enabled | libclang does not produce a standalone CLASS_DECL node for template specializations (the specialization name only appears in the spelling of CONSTRUCTOR/TYPE_REF), so |
This area previously had "extractors written but not wired into the pipeline" (dead code). AliasExtractor/FriendExtractor are now integrated into
SemanticExtractor.parse(), and output was verified against clangd.
🔄 Incremental-update mechanism
1. ChangeDetector ──-> detect file changes (git diff / manual)
2. ImpactAnalyzer ──-> analyze blast radius (.h -> recursive includers)
3. Delete stale data ──-> delete out-edges (not shared nodes) + include_dep + parse_status
4. Re-parse ──-> SemanticExtractor.parse() × affected TUs
5. Upsert new data ──-> node update / edge dedup
6. Cleanup remnants ──-> delete functions/classes no longer in the file
7. Rebuild doc links ──-> content_scan (optional embedding)Core deletion strategy: only out-edges (edges whose from_id is in that file) are deleted; in-edges are kept; nodes are updated via upsert. This ensures classes/functions shared in headers are never mistakenly deleted.
Scenario | Affected TUs | Update time |
Single .cpp change | 1 | ~11s |
Single .h change | recursive includers | depends on TU count (7 TUs ~76s) |
Idempotency (second run) | unchanged | edge count stable ✅ |
Note: the git-diff auto-detect mode (
--base HEAD~1) may not work under Android repo-tool-managed repos (_ensure_repo_rootfinds the repo top-level.gitrather than the sub-repo's). Using--filesto specify changed files manually is more reliable.
📚 Doc fusion
Bidirectionally links project docs (Markdown) with code entities, so searching docs auto-locates related code.
This project has doc fusion configured: 58 docs → 546 sections → 1,756 association edges (doc_describes_code + code_refers_to_doc). cpp_search_docs works out of the box.
Configuration
Create config/doc_config.yaml:
doc_dirs:
- "docs/"
exclude_patterns:
- "*.html"
- "*/build/*"
# Auto-tag by directory
tag_rules:
- path_pattern: "architecture/**"
tags: ["架构设计"]
- path_pattern: "api/**"
tags: ["接口规约"]
section_split:
min_level: 2 # split on ##
min_word_count: 20 # sections under 20 words are merged
# Manual precise links (no intrusion into doc text)
manual_links:
- doc: "architecture/OTA_FLOW.md"
heading: "升级流程"
code:
- "BasePeriUpdate"
- "SocUpdate"
- "PerformUpgrade"Embedding association (optional, experimental)
⚠️ Experimental — not validated. The embedding pipeline has not been tested end-to-end. It is retained from the design phase but excluded from the default association strategy. Results and accuracy are unknown.
After installing sentence-transformers, docs and code can be auto-associated by semantic similarity. This is not enabled by default — pass --rebuild-embeddings to incremental or call ingest_embedding_associations() explicitly:
pip install sentence-transformersDefaults to all-MiniLM-L6-v2. For Chinese projects, bge-small-zh-v1.5 or multilingual-e5-small is recommended.
🧪 Validation
After a full parse, you can run correctness validation (cross-checked against clangd):
python3 -m cpp_semantic_graph full-parse \
--config cpp_semantic_graph.yaml \
--validate \
--baseline validation/clangd_baseline.json📋 Dependencies
Core (required)
Package | Version | Purpose |
| ≥18 | libclang Python bindings, AST parsing |
| ≥6.0 | Config file parsing |
| ≥1.0 | MCP protocol implementation (FastMCP) |
Doc fusion (optional)
Package | Version | Purpose |
| ≥2.0 | doc-code semantic association |
| ≥2.0 | sentence-transformers dependency |
Install
# Core
pip install clang PyYAML mcp
# Doc fusion (optional)
pip install sentence-transformersOr with requirements files:
pip install -r requirements.txt # core
pip install -r requirements-docs.txt # doc fusion (optional)🗂️ Project structure
cpp_semantic_graph/
├── __init__.py # package declaration
├── __main__.py # python -m entry point
├── cli.py # CLI tools (search/inheritance/incremental/...)
├── pipeline.py # full-parse pipeline
├── incremental_updater.py # incremental-update orchestrator
│
├── parser/ # parser layer
│ ├── ast_visitor.py # AST extractor (libclang)
│ ├── config.py # project config loading
│ ├── compile_db.py # compile_commands.json parsing
│ ├── change_detector.py # file-change detection (git diff)
│ ├── impact_analyzer.py # blast-radius analysis
│ ├── doc_parser.py # doc parser
│ ├── doc_association.py # doc-code association
│ ├── association_ingester.py # association-edge ingestion
│ └── models.py # data models
│
├── query/ # query layer
│ ├── graph_query.py # class/function/file-symbol queries
│ ├── call_query.py # call-relation queries
│ ├── polymorphism_query.py # polymorphism queries
│ ├── traverse.py # multi-hop traversal
│ ├── doc_query.py # doc-fusion queries
│ ├── include_query.py # include-dependency queries
│ ├── architecture_query.py # architecture-overview queries
│ └── fusion_query.py # fusion queries
│
├── db/ # data layer
│ ├── graph_db.py # SQLite operations
│ ├── importer.py # JSON->SQLite import
│ ├── schema.sql # schema + indexes
│ └── relation_types.py # relation-type enum
│
├── mcp_server/ # MCP server
│ ├── server.py # FastMCP server + 9 tools
│ └── run_server.py # launch script
│
├── validation/ # correctness validation
│ ├── accuracy_validator.py # accuracy validator
│ └── clangd_baseline.py # clangd baseline
│
├── config/ # config templates
│ ├── doc_config.yaml # doc-config example
│ └── template_whitelist.yaml # template whitelist
│
└── cpp_semantic_graph.yaml # project config (user-authored)❓ FAQ
Q: Which LLVM/libclang version do I need?
One matching the LLVM used to compile your project. How to check:
# clang version
clang --version
# corresponding libclang path
ls /usr/lib/llvm-*/lib/libclang.so*Specify it via libclang_path in the config.
Q: How do I generate compile_commands.json?
CMake project:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...Make project:
bear -- makeNinja project:
bear -- ninjaBazel project: use bazel-compile-commands
Q: Are incremental updates safe?
Yes. The deletion strategy only removes out-edges (edges whose from_id is in that file), not nodes. Classes/functions shared in headers are updated via upsert and never mistakenly deleted. For extreme cases (e.g. renaming a class), a full rebuild is recommended.
Q: Which AI tools are supported?
Any AI tool that supports the MCP protocol: Claude Code, Cursor, Windsurf, Continue, etc. The MCP server uses stdio transport, the most broadly supported transport.
Q: How big is the database?
A typical C++ project (~100 translation units): about 1500 nodes / 5000 edges / 20000 include relations, SQLite file ~5-10 MB. With doc fusion, node and edge counts roughly double, DB ~5-15 MB.
Q: How does this differ from clangd?
cpp-semantic-graph | clangd | |
Data storage | offline SQLite graph | real-time AST |
Query scope | cross-file, cross-module | single file + index |
Call chains | full call graph + multi-hop traversal | single-hop references |
Doc association | supported | not supported |
Incremental update | based on include-dependency graph | real-time |
Best for | architecture understanding, blast-radius analysis | real-time editing, signature lookup |
They complement each other: use clangd for day-to-day editing, cpp-semantic-graph for architecture understanding and impact analysis.
Q: Why are some call edges missing? (conditional compilation)
cpp-semantic-graph builds its AST from the preprocessed translation unit of a single compile configuration — the one recorded in compile_commands.json. The C preprocessor drops every #if / #ifdef / #else branch not selected by the current -D flags before libclang sees the code, so any function call inside a non-selected branch is invisible to the graph. get_callers / get_callees return empty for such a call even though it clearly exists in the source.
This is an inherent limitation of the libclang single-config method, not a bug — clangd has the same blind spot, since it also parses one configuration.
Typical shape. A function whose signature sits outside the #if still gets a node, but calls inside the non-selected #else body are missing. The node therefore exists yet appears to have no callers / no callees for those calls:
bool Foo::CompareVersion(const char* path) { // signature -> node exists
#if SKIP_CHECK // current config: SKIP_CHECK == 1, this branch kept
LogWarning("skipped"); // -> call edge extracted (Logger::Warning)
#else // dead branch, removed by preprocessor
ExtractVersion(path); // -> NO call edge (invisible to libclang)
CompareVersions(...); // -> NO call edge
#endif
}How to tell a blind spot from a real omission. If get_callers is empty for a function you can see called in source, first check whether the call site is inside a #if/#else block, and whether the controlling macro's current value selects that branch. The graph only reflects the configuration that was compiled; it is correct for that configuration.
Mitigation. To analyze another configuration, regenerate compile_commands.json with the corresponding -D flags and rebuild the graph. A single preprocessed AST cannot show all configurations at once; there is no way to union them from one parse.
📄 License
MIT License
📋 Test reports
Report | Description |
Comprehensive test report (functionality/accuracy/efficiency/bug-fix) | |
Test-case table (62 cases, 98.4% pass) | |
Three-layer tests (question→tool call→code verification, 25 real questions) | |
Doc-fusion tests (27 cases, 89% pass) | |
Overall project evaluation (six-dimension scoring + comparison + conclusion) |
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityDmaintenanceProvides AI assistants with a structured, token-efficient map of a codebase's symbols, dependencies, and relationships via MCP tools like overview, query, and impact analysis.Last updated8MIT
- Alicense-qualityCmaintenanceEnables AI agents to search code by meaning, explore codebase structure, store and query knowledge with temporal facts, and read source code through a set of MCP tools.Last updated6016MIT
- Alicense-qualityAmaintenanceProvides code intelligence for AI coding agents by indexing repositories into a hybrid knowledge graph, enabling agents to query dependencies, impact, and context through 28 MCP tools.Last updated2Apache 2.0
- Alicense-qualityAmaintenanceProvides AI agents with a function-level dependency graph of the codebase through 30 MCP tools, enabling structural queries about code dependencies, callers, and impact analysis.Last updated1,37585Apache 2.0
Related MCP Connectors
Give your AI agent a persistent map of your project's structure, dependencies, and bugs.
AI Agent with Architectural Memory. Impact analysis (free), tests and code from the graph (pro).
User-owned memory for AI agents, Copilot, Claude, IDEs, CLIs, and chat apps over remote MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/FS-Yuao/cpp-semantic-graph'
If you have feedback or need assistance with the MCP directory API, please join our Discord server