CPG-powered Language Server Protocol (LSP) implementation that provides real-time code intelligence from the CodeGraph Code Property Graph database.
Table of Contents¶
- Overview
- Installation
- Quick Start
- Diagnostics
- Hover
- CodeLens
- CodeAction (Autofix)
- OpenCode Integration
- Connection Pool
- Configuration
- Troubleshooting
Overview¶
The CodeGraph LSP Server connects any LSP-compatible editor to the CodeGraph CPG (Code Property Graph) managed by GoCPG. At runtime the LSP server is a gRPC client: it does not open DuckDB directly and only issues read-only queries through GoCPG. It provides:
- Security diagnostics – findings from 190+ pattern rules (CWE-mapped)
- Dead code detection – methods with no callers (fan_in=0)
- Complexity warnings – cyclomatic complexity above configurable threshold
- Pattern violations – structural code quality issues
- Method metrics on hover – complexity, fan-in/fan-out, callers, security findings
- CodeLens indicators – caller/callee counts and taint flow info above each method
- Autofix actions – quick-fix for 22 autofix rules (SQL injection, buffer overflow, shell injection)
Supports 11 languages: C, C++, C#, Go, Java, JavaScript, Kotlin, PHP, Python, Ruby, TypeScript.
Installation¶
The LSP server is included in the CodeGraph package:
pip install -e .
This registers the codegraph-lsp CLI entry point. You can also run directly:
python -m codegraph_lsp --db <path-to-duckdb>
--db identifies the target CPG database managed by GoCPG. The LSP process itself does not own or open the DuckDB file directly.
Dependencies¶
pygls>=2.0.0– Python LSP frameworklsprotocol– LSP type definitions- Running GoCPG gRPC server with access to the target CPG database
Quick Start¶
- Build the CPG for your project (if not already done):
gocpg parse --input=. --output=project.duckdb --lang=python
- Start GoCPG so the CPG is available over gRPC:
gocpg serve --data-dir .
- Start the LSP server:
python -m codegraph_lsp --db project.duckdb
- Configure your editor to use the server (see editor-specific sections below).
Diagnostics¶
The server publishes diagnostics on file open and file save.
Security Findings (severity: Error)¶
Findings from cpg_pattern_results where category = 'security'. Each diagnostic includes:
- CWE-mapped rule ID as the diagnostic code
- Exact line and column from CPG analysis
- Message describing the vulnerability
Example in editor:
Error [CWE-89]: SQL injection — user input concatenated into query (line 42)
Dead Methods (severity: Hint, tag: Unnecessary)¶
Methods where fan_in = 0 AND is_entry_point = false AND is_external = false AND is_test = false. Shown with strikethrough styling in editors that support the Unnecessary tag.
Example:
Hint [dead-method]: Dead method: 'unused_helper' has no callers (fan_in=0) (line 25)
Complexity Warnings¶
Methods where cyclomatic_complexity exceeds the configured threshold:
| Complexity | Severity |
|---|---|
| threshold–19 | Information |
| 20–49 | Warning |
| ≥50 | Error |
Example:
Warning [high-complexity]: Cyclomatic complexity of 'process_data' is 25 (threshold: 10) (line 100)
Pattern Violations¶
Non-security findings from cpg_pattern_results. Severity is mapped from the pattern rule’s severity field.
Hover¶
Hovering over a method shows a markdown table with:
| Metric | Description |
|---|---|
| Cyclomatic complexity | Method complexity score |
| Fan-in (callers) | Number of distinct caller methods |
| Fan-out (callees) | Number of distinct called methods |
| Callers | Callers from edges_call |
| LOC | Lines of code |
| Parameters | Number of parameters |
| Security findings | Count of security findings in the file |
| Flags | entry point, external, test, dead code |
CodeLens¶
Each method gets a CodeLens indicator showing:
3 callers | 5 callees | taint: read_input→execute_query
- Callers/callees from
fan_in/fan_outinnodes_method - Taint flow shown when the method participates in a data flow path (via
edges_reaching_def)
CodeAction (Autofix)¶
For pattern violations with available autofix rules, the server provides Quick Fix code actions. The 22 autofix rules include:
| Rule | Language | Description |
|---|---|---|
autofix-py-format-sql |
Python | Replace %-format SQL with parameterized query |
autofix-py-concat-sql |
Python | Replace string concat SQL with parameterized query |
autofix-py-fstring-sql |
Python | Replace f-string SQL with parameterized query |
autofix-py-ctypes-string-at |
Python | Replace ctypes.string_at with safer alternative |
autofix-py-subprocess-shell |
Python | Replace shell=True with direct command |
autofix-go-concat-sql |
Go | Replace string concat SQL with parameterized query |
autofix-go-sprintf-sql |
Go | Replace fmt.Sprintf SQL with parameterized query |
autofix-go-exec-shell |
Go | Replace shell execution with direct command |
autofix-go-cgo-strcpy |
Go | Replace CGO strcpy with safer buffer copy |
autofix-c-strcpy-to-strncpy |
C | Replace strcpy with strncpy |
autofix-c-sprintf-to-snprintf |
C | Replace sprintf with snprintf |
autofix-c-null-assert |
C | Add NULL check after function call |
| … | … | Plus hardcoded-string rules for 10 languages |
Autofix applies when match_data in cpg_pattern_results contains a fix field with the replacement code.
OpenCode Integration¶
Add the LSP server to opencode.json (example configuration):
{
"lsp": {
"codegraph": {
"command": ["python", "-m", "codegraph_lsp", "--db", "project.duckdb"],
"languages": ["python", "go", "javascript", "typescript", "java", "c", "cpp"]
}
}
}
OpenCode will automatically:
- Start the LSP server when opening files in supported languages
- Show diagnostics inline and in the problems panel
- Include diagnostics in LLM context via experimental.chat.system.transform
- Provide quick-fix suggestions for autofix-capable patterns
Connection Pool¶
The LSP server uses a read-only GoCPG-backed query pool:
- Max logical connections: 3 (configurable)
- gRPC-only: the LSP process does not open DuckDB directly
- Read-only workload: all diagnostics, hover, CodeLens, and code actions go through GoCPG query RPCs
- Thread-safe: uses
threading.Lockfor pool access - Snapshot change detection: the pool checks the database file modification time (
mtime) and reconnects idle handles after the CPG snapshot changes
DuckDB ownership stays inside GoCPG. When GoCPG updates or rebuilds the CPG, the LSP client sees the new snapshot through subsequent RPC calls.
Configuration¶
CLI Options¶
| Option | Default | Description |
|---|---|---|
--db |
(required) | Target CPG database path used by GoCPG |
--complexity-threshold |
10 | Cyclomatic complexity warning threshold |
--transport |
stdio | Transport: stdio or tcp |
--host |
127.0.0.1 | TCP host (only for --transport tcp) |
--port |
2087 | TCP port (only for --transport tcp) |
--log-level |
info | Log level: debug, info, warning, error |
Transport Modes¶
stdio (default): Editor starts the server as a subprocess and communicates via stdin/stdout. Best for local usage.
python -m codegraph_lsp --db project.duckdb
tcp: Server listens on a TCP port. Useful for remote LSP connections or shared instances.
python -m codegraph_lsp --db project.duckdb --transport tcp --port 2087
Troubleshooting¶
No Diagnostics Appearing¶
- Verify GoCPG gRPC is reachable and serving the target database.
- Verify the target DuckDB file exists and contains CPG data by checking GoCPG lifecycle/query endpoints or
gocpg stats --db project.duckdb. - Verify file paths in the database match the workspace paths (forward slashes, relative paths).
“Connection Pool Exhausted” Error¶
This means 3 concurrent read requests are active. This can happen if: - GoCPG queries are slow because the CPG is very large - Multiple files were opened simultaneously
Solution: close some files or increase the pool size (requires code change).
Stale Diagnostics After CPG Update¶
If diagnostics seem stale:
- Close and reopen the file
- Verify GoCPG finished the update/reparse and reports read_available=true
- Re-check lifecycle status with the CodeGraph /status or dogfood status workflow
Server Fails to Start¶
- Verify
pyglsis installed:python -c "import pygls; print(pygls.__version__)" - Verify GoCPG gRPC server is running and reachable from the LSP process
- Check logs on stderr for error messages
Windows Path Issues¶
The server normalizes paths from file URIs (file:///C:/... → C:/...) and uses forward slashes internally. If your CPG database has backslash paths, diagnostics may not match. Rebuild the CPG to ensure consistent paths.