Lean LSP Server - Quick Reference
Quick reference for Lean LSP MCP tools. For detailed API documentation, see lean-lsp-tools-api.md.
The Lean LSP server provides instant feedback for interactive theorem development.
Key insight: LSP tools provide instant feedback (< 1 second) versus build cycles (10-30+ seconds). This 30x speedup transforms proof development from frustrating trial-and-error into smooth, interactive problem-solving.
Prerequisites
Before using LSP tools in a fresh clone or worktree:
Prime the cache in this worktree first. Use the project's cache command:
lake cache geton newer Lake versions, orlake exe cache getfor projects that still use the mathlib cache executable.
This avoids rebuilding dependencies from scratch after a fresh checkout or
lake clean.If the LSP server is cold or timing out, run one
lake build. The LSP server runs throughlake serveand can be slow on first startup if the workspace has not been built yet. Note: Lake's[N/M]denominator grows as dependencies are discovered — the counter and fraction are not reliable progress estimates.After bootstrap, use LSP for normal iteration. Day-to-day proof development should use LSP tools for discovery, search, and per-edit validation. Reserve
lake env lean <path/to/File.lean>(run from project root) for fast file-local checks — it elaborates against the built.oleans of the file's imports and does not rebuild them, so after editing an imported module runlake lean <path/to/File.lean>first (File Gate Scope) — andlake buildfor checkpoint/final verification.
Worktrees: prime cache separately per worktree. Do not symlink another worktree's .lake/build.
- Install ripgrep - Required for
lean_local_search(the most-used search tool):- macOS:
brew install ripgrep - Linux:
apt install ripgrepor https://github.com/BurntSushi/ripgrep#installation - Windows: https://github.com/BurntSushi/ripgrep#installation
- Verify:
rg --versionshould work
- macOS:
Without these: You may experience server timeouts or missing search functionality.
Version Notes
Covers lean-lsp-mcp v0.20+/v0.21+ (February 2026).
- v0.21.0: Widget support, improved multiline in lean_goal/lean_multi_attempt.
- v0.20.0:
lean_hammer_premiseadded (premise suggestions for simp/aesop/grind).lean_profile_proofswitched to line-based identification.
Additional tools exist upstream (lean_term_goal, lean_completions, lean_declaration_file, lean_build, lean_get_widgets) — see lean-lsp-mcp README for full list.
Tip: Capture build output with tee - Avoid building twice:
# Build once, capture AND view first 50 lines (or tail -50, or grep error)
lake build 2>&1 | tee /tmp/lean-build-$$.log | head -50
# Later: read from captured file - no rebuild needed
tail -100 /tmp/lean-build-$$.log
grep -i error /tmp/lean-build-$$.logWithout tee, piping to head/grep discards the rest. With tee, the full output is saved while you still see filtered results.
Minimum Workflow (5 Steps)
lean_goal(file, line)- See what to provelean_multi_attempt(file, line, snippets=["simp", "ring", "exact?"])- Test tacticslean_diagnostic_messages(file)- Verify no errors- If diagnostics show "Try this" →
lean_code_actions(file, line)→ apply edit →lean_diagnostic_messages(file)to re-verify lean_goal(file, line)- Confirm no remaining goals
Full Workflow Pattern
For thorough proof development:
1. lean_goal(file, line) # What to prove?
2. lean_local_search("keyword", limit=10) # Does it exist?
3. lean_multi_attempt(file, line, snippets=[ # Test tactics
" simp", " omega", " apply lemma"
])
4. [Edit file with winner]
5. lean_diagnostic_messages(file) # Verify — check for "Try this"
6. lean_code_actions(file, line) # If "Try this" appeared, resolve it
7. lean_diagnostic_messages(file) # Re-verify after applying code action
8. lean_goal(file, line) # Confirm no remaining goalsTotal time: < 10 seconds (LSP) vs 30+ seconds per iteration (build-only)
Measured improvements:
- Feedback: 30x faster (< 1s vs 30s)
- Tactic exploration: 4x fewer iterations (parallel testing)
- Lemma discovery: 10x faster (integrated search)
Critical Rules
- NEVER edit without checking goal state first (
lean_goal) - ALWAYS check diagnostics after edits (don't wait for build)
- Search before guessing - use
lean_local_searchFIRST (fast & unlimited!) - Check goals between tactics - see intermediate progress
- Use
lean_multi_attemptliberally - test multiple tactics at once - Respect rate limits -
lean_local_searchis unlimited;lean_loogleunlimited in local mode; others vary per tool (see table) - NEVER use
lean_file_contentson large files - wastes tokens, useReadtool instead (see warning below)
Tool Summary
Local tools (unlimited, instant):
- Direct LSP queries against your project files
- No rate limits, < 1 second response time
External tools (rate limits vary per tool):
- Remote API calls to leansearch.net, leanfinder, loogle.lean-lang.org
lean_loogleis remote by default; local mode available (--loogle-local/LEAN_LOOGLE_LOCAL)- Rate limits are per-tool (separate pools); managed by LSP server
Best practice: Always use local tools first (especially lean_local_search), then external tools only when local search doesn't find what you need.
| Tool | Type | Rate Limit | Speed | Use For |
|---|---|---|---|---|
lean_goal |
Local | None | Instant | See goals (always!) |
lean_local_search |
Local | None | Instant | Find lemmas (use first!) |
lean_multi_attempt |
Local | None | Instant | Test tactics in parallel |
lean_diagnostic_messages |
Local | None | Instant | Check errors |
lean_code_actions |
Local | None | Instant | Resolve "Try this" suggestions |
lean_hover_info |
Local | None | Instant | Check syntax/types |
lean_file_outline |
Local | None | Fast | File structure overview |
lean_run_code |
Local | None | Fast | Run standalone snippets |
lean_file_contents |
Local | None | Fast | DEPRECATED — use Read tool |
lean_profile_proof |
Local | None | Slow | Profile proof performance |
lean_leanfinder |
External | 10/30s | Fast | Semantic search (best for goals!) |
lean_loogle |
External | Remote default; unlimited if local | Fast | Type patterns |
lean_leansearch |
External | 3/30s | Slower | Natural language fallback |
lean_state_search |
External | 3/30s | Fast | Proof state |
lean_hammer_premise |
External | 3/30s | Fast | Premise suggestions for simp/aesop/grind |
See lean-lsp-tools-api.md for detailed API documentation.
⚠️ lean_file_contents — DEPRECATED
lean_file_contents is deprecated upstream. Do not use it — use the Read tool instead.
It wastes tokens and will error if file exceeds 25000 tokens:
Error: MCP tool "lean_file_contents" response (36863 tokens) exceeds
maximum allowed tokens (25000). Please use pagination, filtering, or
limit parameters to reduce the response size.Instead, use:
Readtool (Claude Code built-in) - optimized for large files, supports offset/limitlean_goal- for specific line's proof state (< 1% of file size)lean_hover_info- for specific term's typelean_diagnostic_messages- for errors onlylean_local_search- to find specific definitions without reading entire file
Why: lean_file_contents loads the entire file with annotations, consuming tokens proportional to file size. Most proof development tasks only need targeted information (goals, errors, specific definitions), not the whole file.
Rule of thumb: If you need to read a file, use Read tool. Only use lean_file_contents on small files (<100 lines) when you specifically need LSP annotations.
Common Usage Patterns
When stuck on a proof
1. lean_goal(file, line) # See exact state
2. lean_leanfinder("⊢ ... + hint") # Semantic search (paste goal!)
3. lean_loogle("pattern") # Type pattern search (unlimited if local mode)
4. lean_hammer_premise(file, l, col) # Premise suggestions for simp/aesop/grind
5. lean_leansearch("description") # Natural language search
6. lean_state_search(file, line, col) # Proof state searchEmergency debugging
1. lean_diagnostic_messages(file) # What errors?
2. lean_hover_info(file, line, col) # What's the type?
3. lean_goal(file, line) # What are goals?Testing multiple approaches
lean_multi_attempt(file, line, snippets=[
" simp [lemma1]",
" omega",
" apply lemma2"
])See which works, pick the best one!
Complete Example: End-to-End Proof
Task: Prove n + m = m + n
lemma test_add_comm (n m : ℕ) : n + m = m + n := by
sorryStep 1: Check goal (ALWAYS FIRST!)
lean_goal(file, line=12)
→ Output:
After:
n m : ℕ
⊢ n + m = m + nNow you know exactly what to prove!
Step 2: Search for lemmas
lean_local_search("add_comm", limit=5)
→ [{"name": "add_comm", "kind": "theorem", ...}]Found it! But let's test multiple approaches...
Step 3: Test tactics in parallel
lean_multi_attempt(file, line=13, snippets=[
" simp [Nat.add_comm]",
" omega",
" apply Nat.add_comm"
])
→ All three show "no goals" — confirm with lean_diagnostic_messages before committingPick simplest: omega
Step 4: Edit file
lemma test_add_comm (n m : ℕ) : n + m = m + n := by
omegaStep 5: Verify immediately
lean_diagnostic_messages(file)
→ [] ← No errors!Step 6: Confirm completion
lean_goal(file, line=13)
→ After:
no goalsSUCCESS! 🎉
Total time: < 10 seconds with absolute certainty
Build-only would take: 30+ seconds per try-and-rebuild cycle
Common Mistakes to Avoid
❌ DON'T:
- Edit → build → see error (too slow!)
- Guess lemma names without searching
- Apply tactics blind without checking goal
- Use rate-limited search when
lean_local_searchworks - Skip intermediate goal checks in multi-step proofs
✅ DO:
- Check goal → search (local first!) → test → apply → verify
- Use
lean_multi_attemptto explore tactics - Verify with
lean_diagnostic_messagesafter every edit - Check intermediate goals after each tactic
- Respect rate limits
Troubleshooting
"Unknown identifier" errors
Problem: add_comm not found
Solutions:
- Try qualified name:
Nat.add_comm - Use
lean_local_searchto find correct name - Try tactic instead:
omegaorsimp
"Function expected" with type classes
Problem: StrictMono Nat.succ fails
Solution: Add type annotation: StrictMono (Nat.succ : ℕ → ℕ)
Search finds nothing
Problem: lean_local_search returns empty
Solutions:
- Try partial matches:
"add"instead of"add_zero" - Use wildcards in loogle:
"_ + 0" - Try natural language:
lean_leansearch("addition with zero")
Multi-attempt shows all failures
Check:
- Proper indentation? Include leading spaces
- Correct line number? Point to tactic line
- Single-line only? Multi-line not supported
Empty diagnostics but proof incomplete
Problem: [] diagnostics but not done
Solution: Check lean_goal - if goals remain, need more tactics
Key insight: Empty diagnostics = no errors, but proof may be incomplete. Always verify goals.
Why This Matters
Without LSP: You're coding blind, relying on slow build cycles for feedback.
With LSP: You have the same interactive feedback loop as a human using Lean InfoView.
The transformation: From "guess and wait" to "see and verify" instantly.
Measured results:
- 30x faster feedback (< 1s vs 30s)
- 4x fewer iterations (parallel testing)
- 10x faster discovery (integrated search)
Bottom line: LSP tools fundamentally change how you develop proofs. Once you experience instant feedback, you'll never want to wait for builds again.