code-analysis · v1.0 · 2026-03-21 · sha256 ff6b12ee2a2beab0

code-analysis v1.0A

Immutable. This exact content is served forever at /api/v1/blob/ff6b12ee2a2beab0.

---
name: code-analysis
description: >-
  LSP-based code analysis via mcpls MCP server. Use for compiler-accurate type
  inspection, go-to-definition, find-all-references, diagnostics, call hierarchy,
  workspace symbol search, code actions, rename refactoring, and document formatting.
  Provides real compiler errors — not guesses. Keywords: LSP, language server,
  type, definition, references, diagnostics, hover, symbol, call hierarchy,
  rename, refactor, code actions, rust-analyzer, pyright, gopls, clangd.
license: MIT
compatibility: Requires mcpls MCP server (https://github.com/bug-ops/mcpls) configured as an MCP server. Works with any LSP 3.17+ compliant language server (rust-analyzer, pyright, typescript-language-server, gopls, clangd, zls).
metadata:
  author: zeph
  version: "1.0"
---
# Code Analysis with LSP

Use LSP tools for accurate, compiler-verified code understanding. These tools require the `mcpls`
MCP server to be configured.

## Positions

Positions are **1-based**: line 1, column 1 is the first character. If you read a file and see
line numbers in the output, use those directly — no conversion needed (mcpls translates to 0-based
LSP positions internally).

File paths must be absolute. Relative paths will not resolve correctly.

## Tool Reference

### Code Intelligence

| Tool | Purpose | When to use |
|---|---|---|
| `get_hover` | Type signature, inferred type, and documentation at a position | "What type is X?", "What does this function do?" |
| `get_definition` | Navigate to where a symbol is defined | Read a function/type implementation before reasoning about it |
| `get_references` | Find all usages of a symbol across the workspace | Before renaming, deleting, or changing a symbol's signature |
| `get_completions` | Context-aware suggestions respecting types and scope | Exploring unknown APIs, discovering available methods |
| `get_document_symbols` | Structured outline of a file (functions, types, constants, fields) | Understanding file structure without reading every line |
| `workspace_symbol_search` | Search for a symbol by name across the entire workspace | Know a name but not which file defines it |

### Diagnostics and Correctness

| Tool | Purpose | When to use |
|---|---|---|
| `get_diagnostics` | Real compiler errors and warnings for a file | After editing code — always call to verify correctness |
| `get_cached_diagnostics` | Previously cached diagnostics (no fresh check) | Quick check when file has not changed recently |
| `get_code_actions` | Quick fixes, refactorings, source actions at a position | Fix diagnostics automatically, add missing imports |

### Refactoring

| Tool | Purpose | When to use |
|---|---|---|
| `rename_symbol` | Workspace-wide rename with full reference tracking | Always prefer over manual find-and-replace |
| `format_document` | Apply language-specific formatting rules | After editing, before committing |

### Call Hierarchy

| Tool | Purpose | When to use |
|---|---|---|
| `prepare_call_hierarchy` | Get callable items at a position | First step before incoming/outgoing calls |
| `get_incoming_calls` | Find all callers of a function | "Who calls this?" — impact analysis |
| `get_outgoing_calls` | Find all callees of a function | "What does this call?" — dependency analysis |

### Server Monitoring

| Tool | Purpose | When to use |
|---|---|---|
| `get_server_logs` | Internal log messages from the language server | Debug "no results" issues, server startup failures |
| `get_server_messages` | User-facing messages from the language server | Check for server notifications, progress, errors |

## Workflow Patterns

### Diagnostic-Driven Editing

After editing a file:

1. Save the file to disk (diagnostics reflect the file on disk, not in-memory).
2. Call `get_diagnostics` on the changed file.
3. For each error, call `get_code_actions` to find available fixes.
4. Apply fixes or edit manually.
5. Repeat until `get_diagnostics` returns an empty list.

### Impact Analysis Before Refactoring

1. Call `get_references` on the symbol you intend to change.
2. Review all usage sites to understand the blast radius.
3. Make the change (or use `rename_symbol` for renames).
4. Call `get_diagnostics` on all affected files.

### Type Exploration

1. Call `get_hover` on an unknown symbol to see its type and documentation.
2. Call `get_definition` to read the implementation.
3. Call `get_references` to understand how other code uses it.

### Call Graph Analysis

1. Call `prepare_call_hierarchy` on a function — this returns a call hierarchy item.
2. Pass the item to `get_incoming_calls` to see what calls it (consumers).
3. Pass the item to `get_outgoing_calls` to see what it calls (dependencies).
4. Repeat recursively to trace deeper call chains.

### Workspace Navigation

1. Call `workspace_symbol_search` with a partial name to find symbols across the project.
2. Call `get_definition` on the result to jump to the source.
3. Call `get_document_symbols` on the target file to understand its full structure.

## Configuration

mcpls auto-detects language servers based on project markers:

| Language | Server | Markers |
|---|---|---|
| Rust | rust-analyzer | `Cargo.toml`, `rust-toolchain.toml` |
| Python | pyright | `pyproject.toml`, `setup.py`, `requirements.txt` |
| TypeScript | typescript-language-server | `package.json`, `tsconfig.json` |
| Go | gopls | `go.mod`, `go.sum` |
| C/C++ | clangd | `CMakeLists.txt`, `compile_commands.json`, `Makefile` |
| Zig | zls | `build.zig`, `build.zig.zon` |

Custom servers can be added in `~/.config/mcpls/mcpls.toml`:

```toml
[[lsp_servers]]
language_id = "rust"
command = "rust-analyzer"
args = []
file_patterns = ["*.rs"]
timeout_seconds = 30

[lsp_servers.initialization_options]
check.command = "clippy"
```

Environment variables:

| Variable | Description | Default |
|---|---|---|
| `MCPLS_CONFIG` | Path to config file | `~/.config/mcpls/mcpls.toml` |
| `MCPLS_LOG` | Log level (trace/debug/info/warn/error) | `info` |
| `MCPLS_LOG_JSON` | Output logs as JSON | `false` |

## Troubleshooting

### No results from get_hover or get_definition

1. The file may not be indexed yet. mcpls opens files lazily — the first access to a file
   triggers indexing, which may take a few seconds for large projects.
2. Call `get_server_logs` to check if the language server is running and has finished indexing.
3. Verify the language server is installed and in `$PATH` (e.g., `which rust-analyzer`).
4. Check that the project has the expected marker files (e.g., `Cargo.toml` for Rust).

### get_diagnostics returns stale results

- Diagnostics reflect the file **on disk**. If you edited the file but did not save, the
  diagnostics will be for the old content. Always save before calling `get_diagnostics`.
- After a save, the language server needs time to re-analyze. Wait briefly and retry.
- Use `get_cached_diagnostics` only when you know the file has not changed — it returns
  push-based diagnostics from the server's last notification, which may be outdated.

### Language server not starting

1. Check `get_server_logs` for startup errors.
2. Verify the server binary is installed: `which rust-analyzer`, `which pyright`, etc.
3. Check the config file (`~/.config/mcpls/mcpls.toml`) for misconfigured `command` or `args`.
4. Ensure the project root contains the expected marker files for auto-detection.
5. For non-standard setups, add an explicit `[[lsp_servers]]` entry in the config.

### Slow responses

- Initial indexing can take 10-30 seconds for large Rust workspaces. Subsequent calls are fast.
- Set `timeout_seconds` higher in the config for large projects.
- Check `get_server_logs` for memory or CPU warnings from the language server.
- For rust-analyzer, ensure `rust-analyzer.cargo.buildScripts.enable` is not causing excessive
  build script evaluation.

### rename_symbol fails or misses references

- `rename_symbol` only works on symbols the language server can resolve. If a symbol is in a
  macro expansion or generated code, the rename may be partial.
- Always call `get_references` first to verify the server can see all usage sites.
- After rename, call `get_diagnostics` on affected files to catch any breakage.

## Edge Cases

- **Macro-generated code**: `get_hover` and `get_definition` may not resolve symbols inside
  procedural macro expansions. Use `get_references` on the macro invocation site instead.
- **Conditional compilation**: Symbols behind `#[cfg(...)]` may not be visible depending on the
  active feature set. Configure the language server's feature flags accordingly.
- **Multi-root workspaces**: mcpls supports multiple roots via the `roots` config option. Each
  root gets its own language server instance.
- **Large files**: `get_document_symbols` on very large files (10k+ lines) may be slow. Prefer
  targeted `get_hover` or `workspace_symbol_search` instead.
- **Cross-crate navigation**: `get_definition` may jump into dependency source code
  (e.g., `~/.cargo/registry/`). This is expected behavior — the language server resolves through
  the full dependency graph.