MCP server providing semantic analysis of C++ codebases using libclang
This server demonstrates strong foundational quality with well-structured tool definitions, comprehensive parameter documentation, and thoughtful descriptions that guide LLM usage. All 10 tools have explicit schemas with type information and detailed descriptions (averaging 250+ characters, well above the 194-character baseline). The naming convention is clear and action-oriented (find_, get_, set_, sync_, trace_). However, there are notable gaps: (1) output schemas are not documented in the tool definitions, responses are inferred from descriptions rather than formally specified; (2) error handling lacks actionable recovery guidance and categorization; (3) no explicit tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear intent differences; (4) some parameter constraints could be more explicit (e.g., regex patterns for file_path, numeric bounds for max_results/max_depth/max_nodes). The tool set is well-composed with minimal overlap and clear single responsibilities. Descriptions are exceptionally detailed with context on when NOT to use a tool (e.g., find_symbols_by_pattern), which is pattern-aligned guidance. Per-tool average: 72.
Find all C++ symbols (classes, functions, typedefs, enums, etc.) defined or declared within a specific file. Optionally filter by symbol name pattern.
Find all functions that call a specific function (call graph analysis). Returns the callers of the target function.
Find all functions called by a specific function (call graph analysis). Returns the functions that the target function calls, organized by call site.
Discover C++ classes, functions, and methods by name pattern; optional filters narrow results by symbol kind, namespace, and file path. Use this tool when you need to DISCOVER symbols by pattern or enumerate symbols matching certain criteria (e.g., 'all classes with Manager in name'). Do NOT use this tool when: - You already know the exact class name and need its hierarchy -> use get_class_hierarchy - You already know the exact class name and need its details -> use get_class_info - You already know the exact function name and need its callers -> use find_incoming_calls - You already know the exact function name and need its callees -> use find_outgoing_calls - You know the exact file name and want ALL symbols in it -> use find_in_file Pattern matching (case-insensitive): - 'DataRecord' — matches in any namespace - 'storage::DataRecord' — matches namespace suffix - '.*Manager.*' — regex, matches containing 'Manager' - '' (empty) — matches ALL symbols; combine with file_name or namespace for enumeration Enumeration via empty symbol_name + filters: - symbol_name='' + file_name='Helper' — all symbols in files with 'Helper' in path - symbol_name='' + namespace='project' — all symbols in that namespace Use symbol_name for C++ symbol names only; use file_name for file or directory prefixes; use namespace for namespace-scoped searches. Do not encode file paths or namespaces in the symbol_name when a dedicated filter exists. file_name semantics: - Substring match only (NOT glob/regex). 'Helper*.h' -> use file_name='Helper' - If a directory/subdirectory is known, preserve the narrowest path substring. - Examples: 'module/' for that subtree, 'module/tests/' for that exact tests dir - Examples: 'spec/' (files in spec dir), 'SAMPLE_' (files starting with SAMPLE_)
Output schemas are not formally documented. Tool descriptions infer response structure, but there is no explicit JSON Schema or structured documentation of what fields/types each tool returns. This forces LLMs to guess the output format and risks breaking chains when downstream tools expect specific fields.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear intent differences. set_project is a WRITE operation; all others are READ-ONLY. Current 'Risk' field in tool definitions is not a standard MCP field and may not be parsed by clients. Clients cannot programmatically distinguish safe tools from destructive ones.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | B | 73 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 13 | - | v1 |
Retrieve the inheritance hierarchy of a C++ class (base classes and derived classes). Returns a tree structure showing parent-child relationships.
Retrieve detailed information about a specific C++ class, including members (fields, methods), base classes, access specifiers, and documentation.
Retrieve information about a C++ type alias, typedef, or using declaration, including what it aliases to.
REQUIRED FIRST STEP: Set the C++ project to analyze using a configuration file. The configuration file MUST be a .json file that defines 'project_root' (absolute path or relative to the config file). This allows multiple analysis profiles without polluting the source tree. Indexes all C++ files and waits for completion (up to sync_timeout seconds). Returns 'ready' when finished, or 'indexing_in_progress' if timeout exceeded.
Check project status or refresh the index. Without arguments: returns current status (system_state enum: 'ready', 'not_ready', 'partially_ready', 'error'). With refresh_mode: triggers incremental or full re-indexing of changed files. Use after source files are modified.
Trace execution paths from one function to another through the call graph. Returns possible call chains connecting the two functions.
Error handling lacks actionable recovery guidance. No tool description specifies what errors are possible, how to recover, or what to try next. E.g., set_project could fail if config_file is invalid, project_root is unreachable, or clang indexing fails. No guidance on retryability or fallback steps.
Numeric parameter bounds are missing or incomplete. max_results defaults to 50 but no explicit bounds stated; max_depth and max_nodes have defaults but no stated minimums/maximums; sync_timeout has default 30 but no validation range. Unbounded or unclear numeric params can cause LLMs to pass unreasonable values.
Pattern parameter in find_in_file lacks explicit format documentation. Does it support regex? Glob? Substring only? Description says 'regex' but does not specify syntax (PCRE, Python re, POSIX ERE). LLMs will guess.
Some descriptions are vague or generic. get_type_alias_info ('information about'), get_class_info ('detailed information') lack concrete specifics. Does get_class_info return static members? Nested types? Access specifiers? LLMs need explicit field lists.