LSP Code Investigation
Use this skill when you need to understand code structure, trace bugs through call chains, find all usages of a symbol, or check compiler diagnostics across a codebase.
Prerequisites
karellen-lsp-mcpmust be installed and on PATH- An LSP server for the target language on PATH:
- C/C++:
clangd— install viapip install --user karellen-lsp-mcp[clangd]or system package manager - Java/Kotlin:
jdtls— install viapip install --user karellen-lsp-mcp[jdtls] - Python:
pyright— install viapip install --user karellen-lsp-mcp[pyright] - Rust:
rust-analyzer— install viarustup component add rust-analyzer - All servers:
pip install --user karellen-lsp-mcp[all]
- C/C++:
Workflow
1. Register the Project
Optionally scan first to see what languages are present:
lsp_scan_languages(project_path="/path/to/project")
Then register:
lsp_register_project(project_path="/path/to/project")
Auto-detection identifies the language, build system, and LSP server configuration.
See /karellen-lsp-mcp:lsp-register for detailed registration options.
2. Understand a Symbol
Start with hover to get the type signature without reading the file:
lsp_hover(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
Then jump to the definition, declaration, or type definition:
lsp_read_definition(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
lsp_read_declaration(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
lsp_read_type_definition(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
3. Trace Usage and Impact
Find all references or implementations:
lsp_find_references(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
lsp_find_implementations(project_id="<id>", file_path="/path/to/file.java", line=10, character=14)
Search for symbols by name across the project:
lsp_workspace_symbols(project_id="<id>", query="MyClassName")
Trace call chains — use the recursive tree tools to get the full hierarchy in one shot:
lsp_call_tree_incoming(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
lsp_call_tree_outgoing(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
Or use the single-level versions if you only need immediate callers/callees:
lsp_call_hierarchy_incoming(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
lsp_call_hierarchy_outgoing(project_id="<id>", file_path="/path/to/file.cpp", line=42, character=10)
4. Understand Type Hierarchies
Get the full recursive type tree in one shot:
lsp_type_tree_supertypes(project_id="<id>", file_path="/path/to/file.java", line=10, character=14)
lsp_type_tree_subtypes(project_id="<id>", file_path="/path/to/file.java", line=10, character=14)
Or single-level:
lsp_type_hierarchy_supertypes(project_id="<id>", file_path="/path/to/file.java", line=10, character=14)
lsp_type_hierarchy_subtypes(project_id="<id>", file_path="/path/to/file.java", line=10, character=14)
5. Get File Overview
List all symbols in a file to understand its structure:
lsp_document_symbols(project_id="<id>", file_path="/path/to/file.cpp")
6. Check Diagnostics
Get compiler errors and warnings for a specific file:
lsp_diagnostics(project_id="<id>", file_path="/path/to/file.cpp")
7. Clean Up
lsp_deregister_project(registration_id="<registration_id>")
Investigation Strategies
Understanding an Unfamiliar Function
lsp_hoverto get the signature and docslsp_read_definitionto see the implementationlsp_call_tree_incomingto get the full caller treelsp_call_tree_outgoingto get the full callee tree
Assessing Change Impact
lsp_find_referencesto find all usages of the symbol being changedlsp_call_tree_incomingto get the full caller tree- For each caller,
lsp_hoverto understand how it uses the symbol lsp_diagnosticson affected files after making changes
Tracing a Bug
- Start at the file where the bug manifests
lsp_document_symbolsto find relevant functionslsp_read_definitionto follow suspicious callslsp_call_tree_incomingto trace the data flow backwardslsp_hoveron variables to check types
Understanding a Class Hierarchy
lsp_type_tree_supertypesto get the full supertype treelsp_type_tree_subtypesto get the full subtype treelsp_document_symbolson key classes to compare their structurelsp_find_referenceson interface methods to see polymorphic usage
Key Rules
- NEVER run build system commands (
cmake,make,meson,cargo build,gradle,mvn,pip install, etc.) on the user's project. The LSP adapter handles build configuration automatically. Register the project and let the adapter handle it. - Register at the language-specific project root, not the repository root. In
monorepos or polyglot projects, use
lsp_detect_projectfirst to find the correct root for each language (whereCargo.toml,pyproject.toml,CMakeLists.txt, etc. lives). Registering at a parent directory that lacks the language's build system marker will fail or produce no results. - Hover before reading.
lsp_hoveris fast and often provides enough context (type signature, docs) without needing to read the full file. - Use LSP instead of grepping.
lsp_find_referencesis semantically aware; it finds actual references, not string matches. - Check indexing status on large codebases. Cross-file queries wait for indexing
automatically, but
lsp_indexing_statusshows progress. - All positions are 1-based.
- All tools accept
timeout. Optional timeout parameter (seconds) overrides the default readiness timeout. Use higher values for large codebases (e.g.timeout=300). - Use
lsp_regenerate_indexto rebuild. If the index is stale or corrupt, this cleans managed data and force-restarts the LSP server. - Always deregister when done using the
registration_idto release resources.