Lean LSP MCP
Lean LSP MCP lets LLM agents inspect, search, build, and experiment with Lean 4 projects via LSP/REPL and external theorem-search services.
Build Lean projects and restart the LSP, optionally cleaning or fetching cache.
Inspect files: imports/declarations, diagnostics, code actions, proof goals, expected types, hover docs, completions, declaration source, and references.
Search locally and remotely using LeanSearch, Loogle, Lean Finder, and Hammer premise suggestions.
Try multiple tactics without editing files, run self-contained Lean code, verify theorem axioms/source warnings, find removable hypotheses, and profile proof timing.
Inspect Lean panel widgets and widget JavaScript source.
Configure behavior via environment/CLI: tool disabling/overrides, logging, project path, output limits, REPL, local Loogle, stdio/streamable-http/SSE transports, and bearer auth.
Enables searching for theorems in Mathlib using natural language queries through leansearch.net, which is documented in an arXiv paper.
Provides integration with the Lean theorem prover and related tools including leanclient, LeanSearch, Loogle, Lean Finder, Lean Hammer, and Lean State Search hosted on GitHub repositories.
Distributes the lean-lsp-mcp package through PyPI for installation and management of the Lean theorem prover MCP server.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Lean LSP MCPsearch for theorems about natural number addition"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP server that allows agentic interaction with the Lean theorem prover via the Language Server Protocol using leanclient. This server provides a range of tools for LLM agents to understand, analyze and interact with Lean projects.
Key Features
Rich Lean Interaction: Access diagnostics, goal states, term information, hover documentation and more.
External Search Tools: Use
LeanSearch,Loogle,Lean FinderandLean Hammerto find relevant theorems and definitions.Easy Setup: Simple configuration for various clients, including VSCode, Cursor and Claude Code.
Related MCP server: lean-lsp-mcp
Setup
Overview
Install uv, a Python package manager.
Make sure your Lean project builds quickly by running
lake buildmanually.Configure your IDE/Setup
(Optional, highly recommended) Install ripgrep (
rg) for local search and source scanning (lean_verifywarnings).
1. Install uv
Install uv for your system. On Linux/MacOS: curl -LsSf https://astral.sh/uv/install.sh | sh
1b. Alternative: Install with Nix
If you use Nix, you can install the package directly from GitHub:
nix profile install github:oOo0oOo/lean-lsp-mcpOr run it without installing: nix run github:oOo0oOo/lean-lsp-mcp.
This provides the MCP server only. You still need a Lean toolchain (elan/lake) for your project, same as the uv setup below.
2. Run lake build
lean-lsp-mcp will run lake serve in the project root to use the language server (for most tools). Some clients (e.g. Cursor) might timeout during this process. Therefore, it is recommended to run lake build manually before starting the MCP. This ensures a faster build time and avoids timeouts.
3. Configure your IDE/Setup
OR using the setup wizard:
Ctrl+Shift+P > "MCP: Add Server..." > "Command (stdio)" > "uvx lean-lsp-mcp" > "lean-lsp" (or any name you like) > Global or Workspace
OR manually adding config by opening mcp.json with:
Ctrl+Shift+P > "MCP: Open User Configuration"
and adding the following
{
"servers": {
"lean-lsp": {
"type": "stdio",
"command": "uvx",
"args": [
"lean-lsp-mcp"
]
}
}
}If you installed VSCode on Windows and are using WSL2 as your development environment, you may need to use this config instead:
{
"servers": {
"lean-lsp": {
"type": "stdio",
"command": "wsl.exe",
"args": [
"uvx",
"lean-lsp-mcp"
]
}
}
}If that doesn't work, you can try cloning this repository and replace "lean-lsp-mcp" with "/path/to/cloned/lean-lsp-mcp".
"+ Add a new global MCP Server" > ("Create File")
Paste the server config into
mcp.jsonfile:
{
"mcpServers": {
"lean-lsp": {
"command": "uvx",
"args": ["lean-lsp-mcp"]
}
}
}# Local-scoped MCP server
claude mcp add lean-lsp uvx lean-lsp-mcp
# OR project-scoped MCP server
# (creates or updates a .mcp.json file in the current directory)
claude mcp add lean-lsp -s project uvx lean-lsp-mcpYou can find more details about MCP server configuration for Claude Code here.
Edit
~/.vibe/config.toml.Paste the following into the file (e.g. at the end):
[[mcp_servers]]
name = "lean-lsp"
transport = "stdio"
command = "uvx"
args = ["lean-lsp-mcp"]
tool_timeout_sec = 600If there are no existing MCP servers, you may have to remove mcp_servers = [].
4. Install ripgrep (optional but recommended)
For the local search tool lean_local_search, install ripgrep (rg) and make sure it is available in your PATH.
5. Install the Lean 4 skill (optional but recommended)
With any agentic coding platform such as Claude Code or Codex, you can install the Agentic Coding Skill: Lean 4 Theorem Proving. This skill provides additional prompts and templates for interacting with Lean 4 projects, including guidance on using lean-lsp-mcp.
MCP Tools
List of available tools
See Tools documentation for the full list of available tools.
Disabling Tools
Many clients allow the user to disable specific tools manually (e.g. lean_build).
VSCode: Click on the Wrench/Screwdriver icon in the chat.
Cursor: In "Cursor Settings" > "MCP" click on the name of a tool to disable it (strikethrough).
You can also disable tools at server startup:
LEAN_MCP_DISABLED_TOOLS: Comma-separated tool names (for examplelean_run_code,lean_build).LEAN_MCP_INSTRUCTIONS: Replacement server instructions string.LEAN_MCP_TOOL_DESCRIPTIONS: JSON object to override tool descriptions.
Example:
export LEAN_MCP_DISABLED_TOOLS="lean_run_code,lean_build"
export LEAN_MCP_INSTRUCTIONS="Prefer lean_local_search before remote search tools."
export LEAN_MCP_TOOL_DESCRIPTIONS='{"lean_goal":"Primary proof-state inspection tool."}'MCP Configuration
This MCP server works out-of-the-box without any configuration. However, a few optional settings are available.
Environment Variables
LEAN_LOG_LEVEL: Log level for the server. Options are "INFO", "WARNING", "ERROR", "NONE". Defaults to "INFO".LEAN_LOG_FILE_CONFIG: Config file path for logging, with priority overLEAN_LOG_LEVEL. If not set, logs are printed to stdout.LEAN_PROJECT_PATH: Path to your Lean project root. A valid Lean project root must containlean-toolchainand eitherlakefile.leanorlakefile.toml. Relativefile_patharguments resolve against this root. This variable is required forstreamable-httpandsse.LEAN_MCP_DISABLED_TOOLS: Comma-separated list of tool names to remove from MCP tool listing.LEAN_MCP_INSTRUCTIONS: Replacement server instructions string.LEAN_MCP_TOOL_DESCRIPTIONS: JSON object mapping tool names to replacement descriptions.LEAN_MCP_SCRATCH_SLOTS: Number of parallel scratch documents used for snippet trials. Defaults to1; increase it only when parallel attempts are worth the additional Lean process memory.LEAN_MCP_MAX_OUTPUT_CHARS: Per-field character budget for goal states and diagnostic messages. Defaults to6000; oversized text is elided from the middle so both the local context and the goal target survive. Set to0to return everything untruncated.LEAN_REPL: Set totrue,1, oryesto enable fast REPL-basedlean_run_codeand line-basedlean_multi_attempt(see REPL Setup).LEAN_REPL_PATH: Path to thereplbinary. Auto-detected from.lake/packages/repl/or.lake/packages/REPL/if not set.LEAN_REPL_TIMEOUT: Per-command timeout in seconds (default: 60).LEAN_REPL_MEM_MB: Memory budget per REPL in MiB (default: 16384). Linux uses a kernel address-space limit (respecting any lower inherited hard limit). macOS samples resident memory of the REPL process tree every 100 ms and kills the group on excess; brief overshoot between samples is possible. Windows does not enforce this budget.LEAN_LSP_MCP_TOKEN: Secret token for bearer authentication when usingstreamable-httporssetransport. If set, bearer auth is required for every request.LEAN_BUILD_CONCURRENCY: Build concurrency mode forlean_build. Options:allow(default),cancel,share.LEAN_HAMMER_URL: URL for a self-hosted Lean Hammer Premise Search instance. Rate limits are skipped when set to a custom backend.LEAN_LOOGLE_LOCAL: Set totrue,1, oryesto enable local loogle (see Local Loogle section).LEAN_LOOGLE_MODULE: Root module for local Loogle (default:Mathlib). Use a built module such asInitorMathlib.Data.Nat.Basicto search it and its imports with a smaller index. Indices are separated by project and module.LEAN_LOOGLE_LOCAL_ONLY: Set totrue,1, oryesto refuse remote Loogle fallback when local search is unavailable. Defaults to false; this does not disable other remote search tools.LEAN_LOOGLE_CACHE_DIR: Override the cache directory for local loogle (default:~/.cache/lean-lsp-mcp/loogle).LOOGLE_URL: URL for a self-hosted Loogle instance (default:https://loogle.lean-lang.org). Rate limits are skipped when set to a custom backend.LOOGLE_HEADERS: JSON object of extra HTTP headers for Loogle requests (e.g.'{"X-API-Key": "..."}').
You can also often set these environment variables in your MCP client configuration:
{
"servers": {
"lean-lsp": {
"type": "stdio",
"command": "uvx",
"args": [
"lean-lsp-mcp"
],
"env": {
"LEAN_PROJECT_PATH": "/path/to/your/lean/project",
"LEAN_LOG_LEVEL": "NONE"
}
}
}
}Transport Methods
The Lean LSP MCP server supports the following transport methods:
stdio: Standard input/output (default)streamable-http: HTTP streamingsse: Server-sent events (MCP legacy, usestreamable-httpif possible)
stdio supports project inference and switching as you move between Lean projects. streamable-http and sse are single-project deployments: they require LEAN_PROJECT_PATH at startup and reject tool-driven project switching.
You can specify the transport method using the --transport argument when running the server. For sse and streamable-http you can also optionally specify the host and port:
uvx lean-lsp-mcp --transport stdio # Default transport
uvx lean-lsp-mcp --transport streamable-http # Available at http://127.0.0.1:8000/mcp
uvx lean-lsp-mcp --transport sse --host localhost --port 12345 # Available at http://localhost:12345/sse
uvx lean-lsp-mcp --version # Print the installed versionProtocol compatibility and runtime
This release uses the official Python MCP SDK 2.2.0. The same server supports 2026-07-28 discovery and request metadata as well as legacy initialization; clients do not need a separate endpoint. Tool names, arguments, structured results, and text fallbacks are unchanged. Expected tool errors retain actionable messages; unexpected crash details stay in server logs. Tool configuration is read at startup (CLI options override environment variables); restart to change it. The tool catalog is sorted by name and carries a private 60-second cache hint for modern clients.
Streamable HTTP uses the SDK's bounded request-body and legacy-session defaults.
Expired sessions must reconnect; modern requests do not need session IDs. Keep
streaming responses enabled for long-running build progress. A modern request
must opt in before receiving MCP log notifications; stderr/file logging remains
controlled by LEAN_LOG_LEVEL and the logging configuration.
Build and analysis tools execute project or supplied Lean code, which can have I/O effects even when scratch documents leave source files unchanged. Their MCP annotations therefore make no read-only or idempotence promise. Use trusted projects and code.
OpenAI Secure MCP Tunnel
For ChatGPT, Codex, Responses API, or other OpenAI surfaces, use OpenAI Secure MCP Tunnel instead of exposing lean-lsp-mcp to the public internet. Create a tunnel in Platform tunnel settings, then run tunnel-client on a host that can reach your Lean project:
export CONTROL_PLANE_API_KEY="sk-..."
tunnel-client init \
--sample sample_mcp_stdio_local \
--profile lean-lsp-local \
--tunnel-id tunnel_0123456789abcdef0123456789abcdef \
--mcp-command "uvx lean-lsp-mcp --transport stdio --lean-project-path /path/to/lean/project"
tunnel-client doctor --profile lean-lsp-local --explain
tunnel-client run --profile lean-lsp-localUse --lean-project-path so relative file_path arguments resolve inside the intended Lean project. For HTTP, bind lean-lsp-mcp to loopback and use --mcp-server-url http://127.0.0.1:8000/mcp in the tunnel profile:
export LEAN_PROJECT_PATH="/path/to/lean/project"
uvx lean-lsp-mcp --transport streamable-http --host 127.0.0.1 --port 8000Keep tunnel-client run healthy while testing connector discovery or tool calls. In ChatGPT connector settings, choose Tunnel as the connection type.
Bearer Token Authentication
Transport via streamable-http and sse supports bearer token authentication. For private OpenAI access, prefer OpenAI Secure MCP Tunnel; bearer auth remains available for HTTP/SSE deployments that clients reach directly.
Set the LEAN_LSP_MCP_TOKEN environment variable (or see section 3 for setting env variables in MCP config) to a secret token before starting the server. If this variable is set, requests without a matching Authorization: Bearer ... header are rejected before tool dispatch.
Example Linux/MacOS setup:
export LEAN_LSP_MCP_TOKEN="your_secret_token"
uvx lean-lsp-mcp --transport streamable-httpClients should then include the token in the Authorization header. This is an
opaque secret checked by this server, not an OAuth access token. The compatibility
mode explicitly disables SDK OAuth resource/audience validation; it does not
provide an OAuth authorization server or per-user permissions.
REPL Setup
Enable fast REPL-based lean_run_code and line-based lean_multi_attempt. Uses leanprover-community/repl tactic mode. Exact column-based attempts still use the LSP path.
1. Add REPL to your Lean project's lakefile.toml:
[[require]]
name = "repl"
git = "https://github.com/leanprover-community/repl"
rev = "v4.35.0" # Use a REPL tag compatible with your Lean toolchain2. Build it:
lake build repl3. Enable via CLI or environment variable:
uvx lean-lsp-mcp --repl
# Or via environment variable
export LEAN_REPL=trueThe REPL binary is auto-detected from .lake/packages/repl/ or
.lake/packages/REPL/. Falls back to LSP if not found.
Path Policy
File-based tools only operate on files inside the active Lean project, resolved .lake/packages/* dependencies, and the Lean stdlib source tree. Returned file paths are sanitized to avoid leaking host absolute paths:
Project files are returned relative to the project root, for example
src/MyFile.lean.Dependency files are returned under
.lake/packages/<package>/....Stdlib files are returned under
.lean-stdlib/....
Symlink escapes outside those roots are rejected.
Local Loogle
Run Loogle locally to avoid the remote API's rate limit (3 req/30s). The binary is built once for the project's Lean toolchain. The first Mathlib index takes a few minutes; subsequent starts load it in seconds.
# Enable via CLI
uvx lean-lsp-mcp --loogle-local
# Or via environment variable
export LEAN_LOOGLE_LOCAL=trueRequirements: git, lake (elan), a built Mathlib project, and substantial memory for indexing. In measurements on current Mathlib, the initial index used ~13 GiB peak RSS and a warm load used ~7 GiB.
Note: Local loogle is currently only supported on Unix systems (Linux/macOS). Windows users should use WSL or the remote API.
Mathlib comes from your project: --lean-project-path must point at a built project that depends on Mathlib. The local binary is compiled for that project's Lean toolchain and runs through lake env, so Lake supplies the project's own dependency environment. Loogle's native dependency hash detects changed .olean files and rebuilds a stale index automatically.
Falls back to remote API if local loogle fails.
Notes on MCP Security
There are many valid security concerns with the Model Context Protocol (MCP) in general!
This MCP server is meant as a research tool and is currently in beta. While it does not handle any sensitive data such as passwords or API keys, it still includes various security risks:
Access to your local file system.
Powerful local build and analysis capabilities.
External network access for remote search tools unless disabled by the operator.
Please be aware of these risks. Feel free to audit the code and report security issues!
Containerized setup (recommended for stricter isolation)
Build image:
docker build -t lean-lsp-mcp:containerized .Run with a mounted project root (read-only source + writable Lake cache):
docker run --rm -i \
-v "$PWD":/workspace:ro \
-v lean-lsp-mcp-lake-cache:/workspace/.lake \
lean-lsp-mcp:containerizedThe included Docker image defaults to:
LEAN_PROJECT_PATH=/workspaceLEAN_MCP_DISABLED_TOOLS=lean_run_code
Notes:
LEAN_MCP_DISABLED_TOOLSis a startup default and can be overridden bydocker run -e.Using
--network nonecan break tools that require network access (leansearch,loogle,leanfinder,hammer_premise) and dependency downloads.The entrypoint exits immediately if
LEAN_PROJECT_PATHdoes not exist.
For more information, you can use Awesome MCP Security as a starting point.
Development
See Adding a new tool for a step-by-step guide to implementing a new MCP tool (return models, helper modules, registration, tests, and docs).
MCP Inspector
npx @modelcontextprotocol/inspector uvx --with-editable path/to/lean-lsp-mcp python -m lean_lsp_mcp.serverRun Tests
uv sync --all-extras
uv run pytest testsPublications and Formalization Projects using lean-lsp-mcp
Ax-Prover: A Deep Reasoning Agentic Framework for Theorem Proving in Mathematics and Quantum Physics arxiv
Numina-Lean-Agent: An Open and General Agentic Reasoning System for Formal Mathematics arxiv github
MerLean: An Agentic Framework for Autoformalization in Quantum Computation arxiv
M2F: Automated Formalization of Mathematical Literature at Scale arxiv
A Group-Theoretic Approach to Shannon Capacity of Graphs and a Limit Theorem from Lattice Packings github
Talks
lean-lsp-mcp: Tools for agentic interaction with Lean (Lean Together 2026) youtube
Related Projects
License & Citation
MIT licensed. See LICENSE for more information.
Citing this repository is highly appreciated but not required by the license.
@software{lean-lsp-mcp,
author = {Oliver Dressler},
title = {{Lean LSP MCP: Tools for agentic interaction with the Lean theorem prover}},
url = {https://github.com/oOo0oOo/lean-lsp-mcp},
month = {3},
year = {2025}
}Available Tools
22 toolslean_buildADestructive
Build the Lean project and restart LSP. Use only if needed (e.g. new imports).
| Name | Required | Description | Default |
|---|---|---|---|
| clean | No | Run lake clean first (slow) | |
| fetch_cache | No | Run lake exe cache get before building (slow) | |
| output_lines | No | Return last N lines of build log (0=none) | |
| lean_project_path | No | Path to Lean project |
Output Schema
| Name | Required | Description |
|---|---|---|
| errors | No | Build errors if any |
| output | Yes | Build output |
| success | Yes | Whether build succeeded |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=true, so the mutation risk profile is covered. The description adds information the annotations cannot express — that the LSP server is restarted as a side effect — which is important state-changing context for the agent. It does not mention build duration or failure behavior, which the schema only hints at via '(slow)'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero waste, with the action and its side effect front-loaded before the usage restriction. Nothing could be removed without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and all parameters are fully described, so the description only needs to convey purpose, side effects and gating — all of which it does. The only omission is the cost/blocking nature of the build, which is partially covered by the schema's 'slow' notes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with each of the four options (clean, fetch_cache, output_lines, lean_project_path) documented including cost warnings. The description adds no parameter-level meaning, so the schema does the work and a baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Build the Lean project') and adds the key side effect ('restart LSP'). It implicitly separates itself from siblings like lean_run_code or lean_verify, but never names an alternative explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear gating condition ('Use only if needed') with a concrete triggering example ('new imports'), which steers the agent away from habitual rebuilding. It stops short of naming the alternative tools to use when a build is not needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_code_actionsARead-onlyIdempotent
Get LSP code actions for a line. Returns resolved edits for TryThis suggestions (simp?, exact?, apply?) and other quick fixes.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| file_path | Yes | Absolute path to Lean file |
Output Schema
| Name | Required | Description |
|---|---|---|
| actions | No | List of available code actions |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and idempotentHint=true, matching the read-only nature. Description adds specifics about returning resolved edits for TryThis suggestions, which goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences that front-load the purpose. Every word earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given output schema exists, description sufficiently covers what the tool returns. Mentions specific types of suggestions. Could elaborate on return format but still adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers both parameters with descriptions (100% coverage). Description does not add any extra detail beyond what schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'Get', resource 'LSP code actions for a line', and specifies it returns resolved edits for TryThis suggestions and other quick fixes. Distinct from siblings like lean_build, lean_completions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implicit: it returns code actions for a line. No explicit when-to-use/when-not-to-use or alternative tools mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_completionsARead-onlyIdempotent
Get IDE autocompletions. Use on INCOMPLETE code (after . or partial name).
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | Yes | Column number (1-indexed characters) | |
| file_path | Yes | Absolute or project-root-relative path to Lean file | |
| max_completions | No | Max completions | |
| resolve_details | No | Fetch type signatures for the top N results |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of completion items |
| prefix | Yes | Source prefix completed at the requested position |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and openWorldHint=false, so the safety profile is covered structurally. The description adds nothing beyond that – it does not say what happens on an empty result, whether the file must be part of the open project, or how resolve_details affects cost. Useful but thin given annotations carry most of the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler, and the core action is front-loaded before the usage caveat. Nothing could be removed without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the input schema is fully documented; the description covers purpose and trigger condition adequately for a simple LSP-backed lookup. Minor gaps remain around preconditions (file must be opened/known to the project) and empty-result behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so line/column indexing, path form, max_completions and resolve_details are all fully documented in the schema. The description adds no positional or formatting guidance beyond it, which matches the baseline for a high-coverage schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Get IDE autocompletions" names a concrete verb and resource, so an agent immediately knows this returns candidate completions rather than diagnostics or goals. It does not explicitly name the sibling it is contrasted with (e.g. lean_hover_info for complete identifiers or lean_local_search for name search), so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence gives a real usage condition – call it on incomplete code, specifically after `.` or a partial name – which is the key discriminator versus hover/goal tools. There are no explicit exclusions or named alternatives, so it is clear context without routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_declaration_fileARead-onlyIdempotent
Get declaration source with the source-line range and surrounding context.
Generated declarations include their source declaration when it is clear.
Set full_file=True for the whole file (can be very large).| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes | Case-sensitive Lean name in the file or project environment | |
| file_path | Yes | Absolute or project-root-relative path to Lean file | |
| full_file | No | Return the entire declaration file (large!) | |
| context_lines | No | Lines of context around the declaration |
Output Schema
| Name | Required | Description |
|---|---|---|
| content | Yes | Declaration source (sliced unless full_file=True) |
| end_line | No | Last line of the returned slice (1-indexed) |
| file_path | Yes | Path to declaration file |
| start_line | No | First line of the returned slice (1-indexed) |
| total_lines | No | Total lines in the declaration file |
| source_declaration | No | Source declaration for a generated declaration such as one created by @[to_additive], when it can be determined reliably |
| declaration_end_line | No | Declaration end line (1-indexed), when known |
| declaration_start_line | No | Declaration start line (1-indexed) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this as a readOnly, idempotent, closed-world lookup, so the description only needs to add behavior beyond that. It does add two useful facts: generated declarations conditionally include their source declaration, and full_file can return a very large payload. It does not say what happens when the symbol is missing or not found in the given file, which is the main remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying a distinct point (what is returned, generated-declaration behavior, the large-file escape hatch), with the core purpose front-loaded. Nothing is wasted or restated from the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-shape explanation is properly omitted, and for a simple read tool the description covers purpose, one behavioral nuance, and a size caveat. The only meaningful omission is how this differs from adjacent lookup siblings, which would help an agent pick correctly in a crowded toolset.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so symbol, file_path, full_file, and context_lines are already documented in structured form and the baseline is 3. The description slightly reinforces full_file with a size warning and implicitly links context_lines to 'surrounding context', but adds no format or edge-case meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: retrieve a declaration's source along with its source-line range and surrounding context. That is far more specific than the title alone and distinguishes it from listing tools like lean_file_outline. It stops short of naming a sibling such as lean_hover_info, so the differentiation from related lookup tools is left implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the stated output (declaration source with line range), but there is no explicit when-to-use versus lean_hover_info, lean_file_outline, or lean_local_search, and no stated preconditions beyond the schema's path/symbol requirements. The one behavioral caveat given is the full_file escape hatch, which guides usage but is not an alternative-selection rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_diagnostic_messagesBRead-onlyIdempotent
Get compiler diagnostics (errors, warnings, infos) for a Lean file.
| Name | Required | Description | Default |
|---|---|---|---|
| end_line | No | Filter to line | |
| severity | No | Filter by severity level. Returns all levels when omitted. | |
| file_path | Yes | Absolute or project-root-relative path to Lean file | |
| timeout_s | No | Max seconds to wait for elaboration. On timeout returns partial=true with still_elaborating_lines - poll again. Omit to wait for full elaboration. | |
| start_line | No | Filter from line | |
| interactive | No | Returns verbose nested TaggedText with embedded widgets. Only use when plain text is insufficient. For 'Try This' suggestions, prefer lean_code_actions. | |
| declaration_name | No | Filter to declaration (slow) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, so the safety profile is covered. The description adds the diagnostic categories (errors, warnings, infos) but says nothing about elaboration behavior, timeouts, or polling, which is where the real behavioral nuance lives (and is carried by the schema instead).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the core action front-loaded and no wasted words. Nothing redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the schema covers all parameters. However, for a tool with 7 parameters and non-trivial elaboration/polling behavior, the description is thin on the when-and-why, leaving the agent to reconstruct context from structured fields alone.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every one of the 7 parameters is already documented (severity enum, timeout polling behavior, line filters, interactive widget caveat). The description adds no parameter detail beyond the schema, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (Get) and resource (compiler diagnostics) scoped to a Lean file, which is clear on its own. It does not distinguish this tool from siblings like lean_goal, lean_hover_info, or lean_code_actions, which also surface Lean analysis.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus the many sibling diagnostics/analysis tools, nor any prerequisite or exclusion stated. The agent must infer usage entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_file_outlineARead-onlyIdempotent
Get imports and declarations with type signatures. Token-efficient.
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute or project-root-relative path to Lean file | |
| max_declarations | No | Max declarations to return |
Output Schema
| Name | Required | Description |
|---|---|---|
| imports | No | Import statements |
| declarations | No | Top-level declarations |
| total_declarations | No | Total count (set when truncated) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, which cover key behavioral traits. The description adds 'token-efficient', which provides additional context about the output format, but does not disclose any other behaviors like required permissions or side effects. Given the annotations, this is adequate but not exceptional.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description consists of two terse sentences (7 words total) that front-load the key action and a performance hint. Every word serves a purpose, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, full parameter descriptions in the schema, comprehensive annotations, and the presence of an output schema, the description provides sufficient context for invocation. It could be slightly more explicit about the output structure, but that is handled by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already documents both parameters thoroughly. The description adds no new parameter-specific information beyond the schema's descriptions, earning the baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns imports and declarations with type signatures, which directly matches the name 'file_outline'. It distinguishes from siblings like 'lean_declaration_file' which focuses on a single declaration, and 'lean_hover_info' which provides information on specific locations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention prerequisites, limitations, or when not to use it, leaving the agent to infer usage from the name and purpose alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_get_widgetsARead-onlyIdempotent
Get panel widgets at a position (proof visualizations, #html, custom widgets). Returns raw widget data - may be large.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | Yes | Column number (1-indexed) | |
| file_path | Yes | Absolute path to Lean file |
Output Schema
| Name | Required | Description |
|---|---|---|
| widgets | No | Widget instances (id, name, range, props) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, making the tool's safety profile clear. The description adds extra value by warning that 'data may be large', which is important behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the main purpose, and a second sentence providing a critical warning. No unnecessary words or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema (handling return format), 100% parameter coverage, and the description providing examples and a size warning, the description is complete for a simple retrieval tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema itself documents all three parameters. The description adds no additional meaning to the parameters, thus baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves panel widgets at a position, listing examples (proof visualizations, #html, custom widgets). It distinguishes from sibling lean_get_widget_source by noting it returns raw widget data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use (need panel widgets at a position) but does not explicitly mention when not to use or list alternatives. With many sibling tools, explicit exclusions would be helpful, but the context is still clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_get_widget_sourceARead-onlyIdempotent
Get JavaScript source of a widget by hash. Useful for understanding custom widget rendering logic. Returns full JS module - may be large.
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to Lean file | |
| javascript_hash | Yes | javascriptHash from a widget instance |
Output Schema
| Name | Required | Description |
|---|---|---|
| source | Yes | Widget source data including JavaScript module |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so safe read. Description adds that 'Returns full JS module - may be large', warning about size, going beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded key action, no redundant words. Each sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, usage, and size warning. Output schema exists so return values not needed. Could mention dependency on lean_get_widgets for hash, but not required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 100% description coverage with clear parameter descriptions. The tool description adds no extra meaning beyond the schema, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states verb 'Get', resource 'JavaScript source of a widget', and method 'by hash'. Distinguishes from siblings like lean_get_widgets which likely returns widget instances.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly mentions 'Useful for understanding custom widget rendering logic', providing when to use. No explicit when-not or alternatives, but context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_goalARead-onlyIdempotent
Get proof goals at a position. MOST IMPORTANT tool - use often!
Omit column to see goals_before (line start) and goals_after (line end),
showing how the tactic transforms the state. status='complete' means the
proof is finished at this point; status='no_goal_at_position' means the
position carries no proof state (e.g. outside a proof).
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | No | Column (1-indexed). Omit for before/after | |
| format | No | Output format: 'text' (default) or 'structured' | text |
| file_path | Yes | Absolute or project-root-relative path to Lean file | |
| timeout_s | No | Max seconds to wait for elaboration. On timeout returns status='still_elaborating' - poll again. |
Output Schema
| Name | Required | Description |
|---|---|---|
| goals | No | Goal list at specified column position |
| status | No | Goal status: 'goals' (open goals), 'complete' (no goals left - proof finished here), 'no_goal_at_position' (position carries no proof state), or 'still_elaborating' (timeout_s hit - poll again) |
| goals_after | No | Goals at line end (when column omitted) |
| goals_before | No | Goals at line start (when column omitted) |
| line_context | Yes | Source line where goals were queried |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint and idempotentHint, and the description adds crucial behavior: column omission reveals before/after states, timeout handling with 'still_elaborating' status, and possible statuses. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences plus a status explanation. Front-loaded with 'MOST IMPORTANT tool - use often!' which is slightly verbose but adds emphasis. No extraneous information; each sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of a proof goal tool with 5 parameters and an output schema (not shown), the description adequately covers behavior, status outcomes, and column handling. No missing critical information for using the tool effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters with descriptions. The description adds value by explaining the effect of omitting column (goals_before/goals_after) and the meaning of format enum options, which go beyond the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get proof goals at a position' with a specific verb and resource. It also labels itself as the 'MOST IMPORTANT tool', distinguishing it from siblings like lean_term_goal, lean_state_search, etc., which query different aspects.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to omit column for before/after views, and defines status values like 'complete' and 'no_goal_at_position'. It does not explicitly list when to use this vs. other tools, but the context of proof goals and the 'most important' emphasis provides implicit guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_hammer_premiseARead-onlyIdempotent
Limit: 6req/30s. Get premise suggestions for automation tactics at a goal position.
Returns lemma names to try with `simp only [...]`, `aesop`, or as hints.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | Yes | Column number (1-indexed) | |
| file_path | Yes | Absolute or project-root-relative path to Lean file | |
| num_results | No | Max results |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of premise results |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint, openWorldHint, and idempotentHint. The description adds a rate limit (6req/30s) and specifies the return format (lemma names). No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences plus a rate limit. The purpose is front-loaded, every word adds value, and there is no verbosity. Ideal conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 4 parameters, full annotation coverage, and presence of an output schema (implied), the description covers purpose, return type, and rate limit. It lacks examples but is adequate for a straightforward suggestion tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for all 4 parameters. The description adds minimal value beyond the schema, only linking line/column to 'goal position'. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it provides premise suggestions for automation tactics at a goal position, listing specific uses like `simp only [...]`, `aesop`, or hints. This distinguishes it from sibling tools like lean_leansearch or lean_loogle, which are general search tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for getting premise suggestions during automated proof attempts, but does not explicitly state when to use this tool versus alternatives like lean_leansearch or lean_loogle. The rate limit is mentioned but not a usage guideline.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_hover_infoBRead-onlyIdempotent
Get type signature and docs for a symbol. Essential for understanding APIs.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | Yes | Column at START of identifier (1-indexed characters) | |
| file_path | Yes | Absolute or project-root-relative path to Lean file |
Output Schema
| Name | Required | Description |
|---|---|---|
| info | Yes | Type signature and documentation |
| symbol | Yes | The symbol being hovered |
| diagnostics | No | Diagnostics at this position |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, so the safety profile is covered. The description adds no behavioral context beyond that – no mention of build-state dependency or empty results on non-symbols. With annotations carrying the burden, this is minimally adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the action front-loaded. The second sentence is somewhat generic ('Essential for understanding APIs') but costs little and stays brief.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and annotations cover safety. Still, the description omits operational context such as needing an up-to-date build or what happens at non-symbol positions, leaving gaps for a tool whose results depend on file state.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with line and column clearly documented as 1-indexed and column defined as the START of the identifier. The description adds no parameter meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Get type signature and docs for a symbol.' An agent can tell what it returns. However, it does not distinguish itself from closely related siblings like lean_completions, lean_goal, or lean_references, which also surface symbol information.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The only guidance is 'Essential for understanding APIs,' which is a generic value claim rather than a when-to-use condition. It never says when to prefer this over siblings such as lean_completions or lean_references, nor any prerequisite (e.g. file must be built/loaded).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_leanfinderARead-onlyIdempotent
Limit: 10req/30s. Semantic search by mathematical meaning via Lean Finder.
Examples: "commutativity of addition on natural numbers",
"I have h : n < m and need n + 1 < m + 1", proof state text.
The `version` argument selects which mathlib snapshot to query
(v4.19.0, v4.24.0, or v4.28.0). Default: v4.28.0.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Mathematical concept or proof state | |
| version | No | Mathlib version index to search | v4.28.0 |
| num_results | No | Max results |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of Lean Finder results |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnly, openWorld, idempotent), description adds rate limit, version behavior (default and options), and that it performs semantic search. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise: two short paragraphs with rate limit, purpose, examples, and parameter explanation. No wasted sentences, information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, description covers purpose, usage constraints, parameter details, and examples. Output schema exists, so return values are covered. No gaps for an agent to select or invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so minimal extra needed. Description adds example queries for the 'query' parameter and explains version options, but adds no new semantic info for 'num_results'. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'semantic search by mathematical meaning via Lean Finder' with examples. Purpose is specific and distinguishable from siblings, but does not explicitly differentiate from similar tools like lean_leansearch or lean_state_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides rate limit (10req/30s) and examples of queries, implying usage for semantic search. However, no explicit guidance on when to use this tool versus alternatives among the many sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_leansearchARead-onlyIdempotent
Limit: 90req/30s. Search Mathlib via leansearch.net using natural language.
Examples: "sum of two even numbers is even", "Cauchy-Schwarz inequality",
"{f : A → B} (hf : Injective f) : ∃ g, LeftInverse g f"
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Natural language or Lean term query | |
| num_results | No | Max results |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of LeanSearch results |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds rate limit information beyond annotations (readOnlyHint, idempotentHint, openWorldHint). No contradictions. However, does not describe response behavior or error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Very concise, front-loaded with rate limit, then purpose, then examples. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple search tool with output schema, the description covers purpose, parameters, examples, and rate limit. No gaps given the context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%. Description provides example queries for the 'query' parameter, adding practical meaning. No additional detail for 'num_results' but schema is clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Explicitly states it searches Mathlib via leansearch.net using natural language. Provides concrete examples distinguishing it from sibling search tools like lean_loogle or lean_local_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Mentions rate limit (90req/30s) but does not clarify when to use this tool vs alternatives like lean_leanfinder or lean_loogle. No explicit exclusions or selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_local_searchARead-onlyIdempotent
Fast local search to verify declarations exist. Use BEFORE trying a lemma name.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max matches | |
| query | Yes | Declaration name or prefix | |
| project_root | No | Project root (inferred if omitted) |
Output Schema
| Name | Required | Description |
|---|---|---|
| index | No | Whether the language server's symbol index contributed. Only 'consulted' makes an empty result mean the declaration does not exist. Declarations generated by attributes such as @[to_additive] exist only in the index, never in source text. |
| items | No | List of local search results |
| sources_searched | No | Search sources that returned results or were searched successfully. Source text is always searched; the symbol index is listed when workspace/symbol returned, including while its index is warming. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=false, so the safety profile is covered. The description adds "Fast" as a performance trait, but says nothing about search semantics (exact vs. prefix matching, whether it covers dependencies), which is the information annotations cannot supply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler, and the timing instruction is placed after the purpose so the agent reads what the tool is before when to call it. Nothing could be cut without losing content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter, read-only search tool with an output schema and full annotation coverage, the description carries everything the agent needs to decide to call it. Return values are handled by the output schema, so no description of results is required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with all three parameters documented in the schema itself (query as name-or-prefix, limit, inferred project_root). The description adds no meaning beyond that — it does not clarify matching behavior or the effect of limit — so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Fast local search" gives a specific verb and a resource scope, and "to verify declarations exist" states the intent. The word "local" implicitly separates it from the external-search siblings (lean_leansearch, lean_loogle, lean_leanfinder), but none of those are named, so differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use BEFORE trying a lemma name" is a real sequencing hint that tells the agent when in a workflow to reach for this tool. However, it never says when NOT to use it, nor does it point to the sibling search tools that cover non-local/external lookup, which the agent must figure out from names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_loogleARead-onlyIdempotent
Search Mathlib by type signature via loogle.lean-lang.org.
Examples: `Real.sin`, `"comm"`, `(?a → ?b) → List ?a → List ?b`,
`_ * (_ ^ _)`, `|- _ < _ → _ + 1 < _ + 1`
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Type pattern, constant, or name substring | |
| num_results | No | Max results |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of Loogle results |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=true, which cover the tool's behavioral safety and consistency. The description adds no new behavioral traits beyond stating it searches via an external source (loogle.lean-lang.org), which is consistent with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise: two sentences of purpose and one line of examples. Every part earns its place. The purpose is front-loaded, and the examples are directly helpful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (search by type signature), the presence of an output schema (not shown but confirmed), and comprehensive annotations, the description is complete. It explains the source, provides examples, and does not need to detail return values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds value by providing concrete examples of valid query strings, which go beyond the schema's generic description ('Type pattern, constant, or name substring'). The num_results parameter is briefly described in the schema but not elaborated in the description, which is fine given its simplicity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search Mathlib by type signature via loogle.lean-lang.org.' This is a specific verb+resource combination that distinguishes it from sibling tools like lean_leansearch (general search) or lean_leanfinder (name search). Examples further clarify the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides concrete examples of valid queries (e.g., `Real.sin`, `?a → ?b → List ?a → List ?b`), which strongly imply when to use this tool—namely for type-based or pattern-based searches. However, it does not explicitly state when not to use it or name alternatives among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_minimal_hypothesesADestructive
For each explicit (h : T) hypothesis of a theorem, drop it and re-elaborate
a scratch copy of the file. Reports which hypotheses are load-bearing and which
are actually unused. Skips implicit {x : α} and instance [inst : C] binders
(those are usually inferable / always load-bearing). Does not rewrite the proof
body — a body that names h will fail to elaborate without the binder, which
is the truthful answer (load-bearing).
Variants are checked in parallel on scratch documents; the file is never edited.| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to Lean file | |
| theorem_name | Yes | Theorem name. Either bare (e.g. `add_comm`) or fully qualified (e.g. `Namespace.add_comm`); only the trailing segment is used for source matching. | |
| inactivity_timeout | No | Per-hypothesis elaboration timeout (seconds) |
Output Schema
| Name | Required | Description |
|---|---|---|
| file | Yes | Relative file path |
| verdicts | No | One verdict per explicit (h : T) binder, in source order |
| theorem_name | Yes | Theorem analyzed |
| skipped_implicit | No | Count of implicit {x : α} / instance [inst] binders not probed |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond annotations: work happens on scratch copies in parallel, the target file is never edited, and the proof body is not rewritten, so elaboration failure is reported as load-bearing rather than patched. There is mild tension with `destructiveHint: true` / `readOnlyHint: false`, which the description does not explain (likely scratch-document creation/teardown), but the description does not deny a write — it scopes it to the source file.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the skip rules, then the non-rewriting semantics, then the parallelism guarantee. Each of the four sentences carries distinct information and nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value shape need not be described, and the description covers the non-obvious semantics an agent needs: skip rules, failure interpretation, and non-mutation of the file. Only the mismatch between the stated no-edit behavior and the destructive annotation is left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so `file_path`, `theorem_name` (bare vs qualified, trailing-segment matching), and `inactivity_timeout` are already documented. The description adds no parameter-level detail of its own; its 'explicit hypothesis' scoping is about what gets tested, not about any input field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource pair: for each explicit `(h : T)` hypothesis, drop it and re-elaborate a scratch copy, reporting load-bearing vs unused. No sibling (`lean_multi_attempt`, `lean_verify`, `lean_goal`) does hypothesis minimization, and the scoping to explicit binders makes the tool unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear selection context: it only touches explicit `(h : T)` hypotheses and deliberately skips implicit `{x : α}` and instance `[inst : C]` binders, with a rationale. It stops short of naming an alternative tool or stating when not to use it at all (e.g., for theorems with no explicit hypotheses).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_multi_attemptCDestructive
Try multiple tactics without modifying file. Returns goal state for each.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | No | Column (1-indexed). Omit to target the tactic line | |
| snippets | Yes | Tactics to try (3+ recommended) | |
| file_path | Yes | Absolute or project-root-relative path to Lean file |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of attempt results |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description claims the operation happens 'without modifying file', yet annotations declare readOnlyHint=false and destructiveHint=true. If attempts touch editor/buffer state or are reverted afterward, that should be stated; if truly read-only, the annotations are at odds with the text. Either way the agent is left without a reliable side-effect picture.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and followed by the return shape; no filler. It is terse to the point of under-specification, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, but for an openWorld, destructive-hinted tool the description should cover side effects on file state, whether attempts are reverted, or cost/rate considerations. Those are absent, and the 'without modifying file' claim leaves the safety profile unresolved.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so line, column, snippets, and file_path are already documented in structured fields. The description adds no extra meaning (e.g., what a 'tactic' snippet should look like, whether snippets are full proofs or single tactics), so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: try multiple tactics at a position in a Lean file, and returns the resulting goal state for each. This is distinguishable from siblings like lean_goal or lean_run_code, though it never names those alternatives to sharpen the distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance: no mention of when to prefer this over lean_run_code, lean_hammer_premise, or lean_code_actions, and no prerequisites (e.g., file must be open/elaborated). The only hint, '3+ recommended', lives in the schema, not the description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_profile_proofADestructive
Run lean --profile on a theorem. Returns per-line timing and categories. SLOW - avoid on theorems that already hit heartbeat limits.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line where theorem starts (1-indexed) | |
| top_n | No | Number of slowest lines to return | |
| timeout | No | Max seconds to wait | |
| file_path | Yes | Absolute or project-root-relative path to Lean file |
Output Schema
| Name | Required | Description |
|---|---|---|
| ms | Yes | Total elaboration time in ms |
| lines | No | Time per source line (>1% of total) |
| categories | No | Cumulative time by category in ms |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, openWorldHint=true, non-idempotent, so the safety burden is partly carried structurally. The description adds real value with the performance warning ('SLOW'), but it never explains why the tool is flagged destructive, how long it may hold resources, or what the timeout actually aborts — all relevant for an annotated-destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action, then the return value, then the caveat. Nothing is redundant and the warning is placed where an agent will see it before invoking.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-format detail is not required, and the description still summarizes it in one line. The only shortfall is that a destructive-flagged, long-running tool would benefit from a note on what it mutates or whether it requires a prior build.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with line, top_n, timeout, and file_path each documented in the schema itself. The description adds no parameter-level meaning beyond that, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the concrete mechanism (`lean --profile`) and the resource (a theorem at a given file/line), plus what comes back (per-line timing and categories). It is clearly distinct from sibling tools like lean_verify or lean_diagnostic_messages, though it never names an alternative explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is one genuine exclusion: 'avoid on theorems that already hit heartbeat limits.' That tells the agent a negative condition, but there is no positive routing guidance such as 'run lean_verify first' or when to prefer this over a plain build, so usage is only partially implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_referencesARead-onlyIdempotent
Find all references to a symbol (including the declaration). Position cursor at the symbol.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | Yes | Column at START of identifier (1-indexed) | |
| file_path | Yes | Absolute path to Lean file | |
| max_results | No | Max locations to return (default 50) |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | No | List of reference locations |
| total | No | Total matches (> len(items) when truncated by max_results) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint. The description adds that it includes the declaration, which is a behavioral detail beyond annotations. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, clear, no fluff. Every word is necessary and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values are covered. The description explains the core function and a key prerequisite. Could mention that it returns locations including declaration, but overall adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description does not add any additional meaning beyond the schema; it only mentions cursor positioning which relates to line/column but not in detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Find' with a clear resource 'all references to a symbol', explicitly includes 'including the declaration', and distinguishes from siblings like hover or goal tools by mentioning cursor positioning.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a condition ('Position cursor at the symbol') but does not explicitly state when to use this tool versus alternatives like lean_local_search or lean_loogle, leaving the differentiation implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_run_codeBDestructive
Run a code snippet and return diagnostics. Must include all imports.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Self-contained Lean code with imports |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes | Whether code compiled successfully |
| timed_out | No | True if elaboration timed out (results are partial) |
| diagnostics | No | Compiler diagnostics |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations flag this as destructive, non-idempotent, and open-world, but the description says nothing about side effects, what state the snippet can affect, or why execution is considered destructive. The only added constraint is the self-contained imports requirement, which is already carried by the schema. For a code-execution tool with a destructive hint, this leaves the risk profile unexplained.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no wasted words, and the core action is front-loaded before the input constraint. It is efficient, though extremely terse for a destructive operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the single parameter is fully documented in the schema. However, for a destructive code-execution tool, the definition omits where the code runs, what 'diagnostics' covers, and how it relates to sibling diagnostic tools, leaving meaningful gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage, so the schema already explains that code must be self-contained Lean with imports. The description restates that requirement rather than adding format, size, or content constraints beyond it. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a concrete verb and resource: run a Lean code snippet and return diagnostics. It is distinguishable from most siblings by the 'snippet in, diagnostics out' framing, though it does not explicitly contrast itself with lean_build or lean_multi_attempt.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The prerequisite 'Must include all imports' tells the agent how the input must be formed, but there is no explicit guidance on when to choose this over lean_build, lean_multi_attempt, or lean_diagnostic_messages. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_term_goalBRead-onlyIdempotent
Get the expected type at a position.
| Name | Required | Description | Default |
|---|---|---|---|
| line | Yes | Line number (1-indexed) | |
| column | No | Column (defaults to end of line) | |
| file_path | Yes | Absolute or project-root-relative path to Lean file |
Output Schema
| Name | Required | Description |
|---|---|---|
| line_context | Yes | Source line where term goal was queried |
| expected_type | No | Expected type at this position |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and idempotent behavior. The description adds minimal context beyond that (e.g., 'expected type' vs full goal). No contradictions, but little extra value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise single sentence with no wasted words. Information is front-loaded and easily parsed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While annotations and output schema exist, the description is minimal. It does not explain what the returned 'expected type' looks like or how it relates to the position, leaving some ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameters are already documented. The description does not add any extra meaning or context about parameters, but given coverage, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves the expected type at a given position, using a specific verb and resource. However, it does not differentiate itself from the sibling tool 'lean_goal', which likely has a similar purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives like 'lean_goal'. The description lacks context on scenarios or limitations, leaving the agent to guess.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lean_verifyADestructive
Check theorem axioms + optional source scan. Only scans the given file, not imports.
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to Lean file | |
| scan_source | No | Scan source file for suspicious patterns | |
| theorem_name | Yes | Fully qualified name (e.g. `Namespace.theorem`) |
Output Schema
| Name | Required | Description |
|---|---|---|
| trust | No | Worst case in `axioms`. 'standard' is the ordinary Mathlib basis; 'incomplete' means sorryAx, so it is not a proof; 'native' means native_decide, trusting the compiler rather than the kernel; 'custom' means other axioms are in play. |
| axioms | No | Axioms used. Standard 3: propext, Classical.choice, Quot.sound |
| warnings | No | Suspicious source patterns (if enabled) |
| non_standard_axioms | No | Axioms outside the standard 3 — the reason for `trust` |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description usefully discloses scan scope (only the given file, not imports), which is behavior not visible in the schema. However, the annotations declare destructiveHint=true, readOnlyHint=false and idempotentHint=false for what reads like a pure verification operation, and the description never explains what is mutated or destroyed or what permissions are needed, leaving a notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero waste and the core action front-loaded, followed immediately by the scope caveat. The telegraphic phrasing ('Check theorem axioms') is slightly compressed but not ambiguous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the three parameters are fully documented in the schema. What is missing is any reconciliation of the destructive, non-idempotent annotation profile with a verification action, which matters for an agent deciding whether to call it casually.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description adds a bit by framing scan_source as an optional source scan and by stating the scan is limited to the given file. It does not clarify the absolute-path or fully-qualified-name requirements, but the schema already carries those.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and object: 'Check theorem axioms' plus an optional source scan. This is clearly not a build, search, or diagnostic tool, so it separates reasonably from siblings, though it never names an alternative or explicitly says it is the axiom/sorry-check tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The clause 'Only scans the given file, not imports' implies a scoping rule and hints that callers wanting dependency coverage must look elsewhere, but there is no explicit when-to-use or when-not-to-use guidance relative to lean_diagnostic_messages, lean_build, or other verification-adjacent siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.33.0- Changed
lean_completions2 fields changed- added
Output schema / properties / prefixAdded value: +{ + "description": "Source prefix completed at the requested position", + "title": "Prefix", + "type": "string" +} - added
Output schema / requiredAdded value: +[ + "prefix" +]
- Changed
lean_declaration_file4 fields changed- changed
Input schema / properties / symbol / descriptionPrevious value: -"Symbol (case sensitive, must be in file)"New value: +"Case-sensitive Lean name in the file or project environment" - added
Output schema / properties / declaration_end_lineAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Declaration end line (1-indexed), when known", + "title": "Declaration End Line" +} - added
Output schema / properties / declaration_start_lineAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Declaration start line (1-indexed)", + "title": "Declaration Start Line" +} - added
Output schema / properties / source_declarationAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Source declaration for a generated declaration such as one created by @[to_additive], when it can be determined reliably", + "title": "Source Declaration" +}
- Changed
lean_local_search1 field changed- added
Output schema / properties / sources_searchedAdded value: +{ + "default": [ + "source_text" + ], + "description": "Search sources that returned results or were searched successfully. Source text is always searched; the symbol index is listed when workspace/symbol returned, including while its index is warming.", + "items": { + "enum": [ + "source_text", + "symbol_index" + ], + "type": "string" + }, + "title": "Sources Searched", + "type": "array" +}
8 tool updates
v0.31.0- Changed
lean_diagnostic_messages3 fields changed- added
Output schema / $defs / DiagnosticCategoryAdded value: +{ + "enum": [ + "diagnostic", + "linter", + "sorry", + "suggestion" + ], + "title": "DiagnosticCategory", + "type": "string" +} - added
Output schema / $defs / DiagnosticMessage / properties / categoryAdded value: +{ + "$ref": "#/$defs/DiagnosticCategory", + "default": "diagnostic", + "description": "'linter' is style noise (unused variables and the like) that does not block compilation; 'sorry' marks an unproved declaration and is never noise; 'suggestion' carries a `Try this:` replacement; 'diagnostic' is everything else." +} - added
Output schema / $defs / DiagnosticMessage / properties / hintAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Guidance for a recognised failure mode, when one applies", + "title": "Hint" +}
- Changed
lean_hover_info3 fields changed- added
Output schema / $defs / DiagnosticCategoryAdded value: +{ + "enum": [ + "diagnostic", + "linter", + "sorry", + "suggestion" + ], + "title": "DiagnosticCategory", + "type": "string" +} - added
Output schema / $defs / DiagnosticMessage / properties / categoryAdded value: +{ + "$ref": "#/$defs/DiagnosticCategory", + "default": "diagnostic", + "description": "'linter' is style noise (unused variables and the like) that does not block compilation; 'sorry' marks an unproved declaration and is never noise; 'suggestion' carries a `Try this:` replacement; 'diagnostic' is everything else." +} - added
Output schema / $defs / DiagnosticMessage / properties / hintAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Guidance for a recognised failure mode, when one applies", + "title": "Hint" +}
- Changed
lean_local_search2 fields changed- added
Output schema / $defs / IndexStatusAdded value: +{ + "description": "Whether a local search could consult the language server's symbol index.\n\nOnly ``consulted`` makes an empty result mean the declaration is absent.", + "enum": [ + "consulted", + "warming", + "unavailable", + "error" + ], + "title": "IndexStatus", + "type": "string" +} - added
Output schema / properties / indexAdded value: +{ + "$ref": "#/$defs/IndexStatus", + "default": "unavailable", + "description": "Whether the language server's symbol index contributed. Only 'consulted' makes an empty result mean the declaration does not exist. Declarations generated by attributes such as @[to_additive] exist only in the index, never in source text." +}
- Changed
lean_minimal_hypotheses3 fields changed- added
Output schema / $defs / DiagnosticCategoryAdded value: +{ + "enum": [ + "diagnostic", + "linter", + "sorry", + "suggestion" + ], + "title": "DiagnosticCategory", + "type": "string" +} - added
Output schema / $defs / DiagnosticMessage / properties / categoryAdded value: +{ + "$ref": "#/$defs/DiagnosticCategory", + "default": "diagnostic", + "description": "'linter' is style noise (unused variables and the like) that does not block compilation; 'sorry' marks an unproved declaration and is never noise; 'suggestion' carries a `Try this:` replacement; 'diagnostic' is everything else." +} - added
Output schema / $defs / DiagnosticMessage / properties / hintAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Guidance for a recognised failure mode, when one applies", + "title": "Hint" +}
- Changed
lean_multi_attempt3 fields changed- added
Output schema / $defs / DiagnosticCategoryAdded value: +{ + "enum": [ + "diagnostic", + "linter", + "sorry", + "suggestion" + ], + "title": "DiagnosticCategory", + "type": "string" +} - added
Output schema / $defs / DiagnosticMessage / properties / categoryAdded value: +{ + "$ref": "#/$defs/DiagnosticCategory", + "default": "diagnostic", + "description": "'linter' is style noise (unused variables and the like) that does not block compilation; 'sorry' marks an unproved declaration and is never noise; 'suggestion' carries a `Try this:` replacement; 'diagnostic' is everything else." +} - added
Output schema / $defs / DiagnosticMessage / properties / hintAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Guidance for a recognised failure mode, when one applies", + "title": "Hint" +}
- Changed
lean_run_code3 fields changed- added
Output schema / $defs / DiagnosticCategoryAdded value: +{ + "enum": [ + "diagnostic", + "linter", + "sorry", + "suggestion" + ], + "title": "DiagnosticCategory", + "type": "string" +} - added
Output schema / $defs / DiagnosticMessage / properties / categoryAdded value: +{ + "$ref": "#/$defs/DiagnosticCategory", + "default": "diagnostic", + "description": "'linter' is style noise (unused variables and the like) that does not block compilation; 'sorry' marks an unproved declaration and is never noise; 'suggestion' carries a `Try this:` replacement; 'diagnostic' is everything else." +} - added
Output schema / $defs / DiagnosticMessage / properties / hintAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Guidance for a recognised failure mode, when one applies", + "title": "Hint" +}
- Removed
lean_state_search - Changed
lean_verify3 fields changed- added
Output schema / $defs / AxiomTrustAdded value: +{ + "enum": [ + "standard", + "incomplete", + "native", + "custom" + ], + "title": "AxiomTrust", + "type": "string" +} - added
Output schema / properties / non_standard_axiomsAdded value: +{ + "description": "Axioms outside the standard 3 — the reason for `trust`", + "items": { + "type": "string" + }, + "title": "Non Standard Axioms", + "type": "array" +} - added
Output schema / properties / trustAdded value: +{ + "$ref": "#/$defs/AxiomTrust", + "default": "standard", + "description": "Worst case in `axioms`. 'standard' is the ordinary Mathlib basis; 'incomplete' means sorryAx, so it is not a proof; 'native' means native_decide, trusting the compiler rather than the kernel; 'custom' means other axioms are in play." +}
1 tool update
v0.29.0- Changed
lean_diagnostic_messages2 fields changed- removed
Input schema / properties / severity / anyOfRemoved value: -[ - { - "enum": [ - "error", - "warning", - "info", - "hint" - ], - "type": "string" - }, - { - "type": "null" - } -] - added
Input schema / properties / severity / enumAdded value: +[ + "error", + "warning", + "info", + "hint" +]
11 tool updates
v0.28.0- Changed
lean_build1 field changed- added
Input schema / properties / fetch_cacheAdded value: +{ + "default": false, + "description": "Run lake exe cache get before building (slow)", + "title": "Fetch Cache", + "type": "boolean" +}
- Changed
lean_completions2 fields changed- changed
Input schema / properties / column / descriptionPrevious value: -"Column number (1-indexed)"New value: +"Column number (1-indexed characters)" - added
Input schema / properties / resolve_detailsAdded value: +{ + "default": 8, + "description": "Fetch type signatures for the top N results", + "minimum": 0, + "title": "Resolve Details", + "type": "integer" +}
- Changed
lean_declaration_file6 fields changed- added
Input schema / properties / context_linesAdded value: +{ + "default": 20, + "description": "Lines of context around the declaration", + "minimum": 0, + "title": "Context Lines", + "type": "integer" +} - added
Input schema / properties / full_fileAdded value: +{ + "default": false, + "description": "Return the entire declaration file (large!)", + "title": "Full File", + "type": "boolean" +} - changed
Output schema / properties / content / descriptionPrevious value: -"File content"New value: +"Declaration source (sliced unless full_file=True)" - added
Output schema / properties / end_lineAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Last line of the returned slice (1-indexed)", + "title": "End Line" +} - added
Output schema / properties / start_lineAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "First line of the returned slice (1-indexed)", + "title": "Start Line" +} - added
Output schema / properties / total_linesAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Total lines in the declaration file", + "title": "Total Lines" +}
- Changed
lean_diagnostic_messages8 fields changed- removed
Input schema / $defsRemoved value: -{ - "DiagnosticSeverity": { - "enum": [ - "error", - "warning", - "info", - "hint" - ], - "title": "DiagnosticSeverity", - "type": "string" - } -} - changed
Input schema / properties / severity / anyOfPrevious value: -[ - { - "$ref": "#/$defs/DiagnosticSeverity" - }, - { - "type": "null" - } -]New value: +[ + { + "enum": [ + "error", + "warning", + "info", + "hint" + ], + "type": "string" + }, + { + "type": "null" + } +] - added
Input schema / properties / severity / titleAdded value: +"Severity" - added
Input schema / properties / severity / typeAdded value: +"string" - added
Input schema / properties / timeout_sAdded value: +{ + "anyOf": [ + { + "minimum": 1, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Max seconds to wait for elaboration. On timeout returns partial=true with still_elaborating_lines - poll again. Omit to wait for full elaboration.", + "title": "Timeout S" +} - added
Output schema / $defs / DiagnosticMessage / properties / lean_tagsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Lean-specific tags: 'unsolvedGoals' (proof incomplete here) or 'goalsAccomplished' (proof finished). Machine-readable proof status - prefer over string-matching the message.", + "title": "Lean Tags" +} - added
Output schema / $defs / DiagnosticsResult / properties / partialAdded value: +{ + "default": false, + "description": "True when elaboration was still running at timeout: items may be incomplete and still_elaborating_lines shows the pending region. Poll again instead of treating this as failure.", + "title": "Partial", + "type": "boolean" +} - added
Output schema / $defs / DiagnosticsResult / properties / still_elaborating_linesAdded value: +{ + "anyOf": [ + { + "items": { + "items": { + "type": "integer" + }, + "type": "array" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Line ranges [start, end] (1-indexed) still being elaborated", + "title": "Still Elaborating Lines" +}
- Changed
lean_goal7 fields changed- added
Input schema / properties / formatAdded value: +{ + "default": "text", + "description": "Output format: 'text' (default) or 'structured'", + "enum": [ + "text", + "structured" + ], + "title": "Format", + "type": "string" +} - added
Input schema / properties / timeout_sAdded value: +{ + "anyOf": [ + { + "minimum": 1, + "type": "number" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Max seconds to wait for elaboration. On timeout returns status='still_elaborating' - poll again.", + "title": "Timeout S" +} - added
Output schema / $defsAdded value: +{ + "GoalContextEntry": { + "properties": { + "name": { + "description": "Local hypothesis or variable name", + "title": "Name", + "type": "string" + }, + "type": { + "description": "Lean type", + "title": "Type", + "type": "string" + } + }, + "required": [ + "name", + "type" + ], + "title": "GoalContextEntry", + "type": "object" + }, + "StructuredGoal": { + "properties": { + "context": { + "description": "Local context entries", + "items": { + "$ref": "#/$defs/GoalContextEntry" + }, + "title": "Context", + "type": "array" + }, + "goal": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Target goal", + "title": "Goal" + }, + "pretty": { + "description": "Original pretty-printed goal", + "title": "Pretty", + "type": "string" + }, + "status": { + "description": "Goal status: open, complete, or unknown", + "title": "Status", + "type": "string" + } + }, + "required": [ + "status", + "pretty" + ], + "title": "StructuredGoal", + "type": "object" + } +} - changed
Output schema / properties / goals / anyOfPrevious value: -[ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -]New value: +[ + { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/StructuredGoal" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } +] - changed
Output schema / properties / goals_after / anyOfPrevious value: -[ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -]New value: +[ + { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/StructuredGoal" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } +] - changed
Output schema / properties / goals_before / anyOfPrevious value: -[ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } -]New value: +[ + { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/$defs/StructuredGoal" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } +] - added
Output schema / properties / statusAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Goal status: 'goals' (open goals), 'complete' (no goals left - proof finished here), 'no_goal_at_position' (position carries no proof state), or 'still_elaborating' (timeout_s hit - poll again)", + "title": "Status" +}
- Changed
lean_hover_info2 fields changed- changed
Input schema / properties / column / descriptionPrevious value: -"Column at START of identifier"New value: +"Column at START of identifier (1-indexed characters)" - added
Output schema / $defs / DiagnosticMessage / properties / lean_tagsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Lean-specific tags: 'unsolvedGoals' (proof incomplete here) or 'goalsAccomplished' (proof finished). Machine-readable proof status - prefer over string-matching the message.", + "title": "Lean Tags" +}
- Changed
lean_leanfinder11 fields changed- added
Input schema / properties / versionAdded value: +{ + "default": "v4.28.0", + "description": "Mathlib version index to search", + "enum": [ + "v4.19.0", + "v4.24.0", + "v4.28.0" + ], + "title": "Version", + "type": "string" +} - added
Output schema / $defs / LeanFinderResult / properties / formal_nameAdded value: +{ + "description": "Fully qualified Lean declaration name", + "title": "Formal Name", + "type": "string" +} - removed
Output schema / $defs / LeanFinderResult / properties / formal_statementRemoved value: -{ - "description": "Lean type signature", - "title": "Formal Statement", - "type": "string" -} - removed
Output schema / $defs / LeanFinderResult / properties / full_nameRemoved value: -{ - "description": "Full qualified name", - "title": "Full Name", - "type": "string" -} - added
Output schema / $defs / LeanFinderResult / properties / informal_descriptionAdded value: +{ + "description": "Natural-language description of the statement", + "title": "Informal Description", + "type": "string" +} - added
Output schema / $defs / LeanFinderResult / properties / informal_nameAdded value: +{ + "description": "Short natural-language name for the statement", + "title": "Informal Name", + "type": "string" +} - removed
Output schema / $defs / LeanFinderResult / properties / informal_statementRemoved value: -{ - "description": "Natural language description", - "title": "Informal Statement", - "type": "string" -} - added
Output schema / $defs / LeanFinderResult / properties / kindAdded value: +{ + "description": "Declaration kind (theorem, def, instance, etc.)", + "title": "Kind", + "type": "string" +} - added
Output schema / $defs / LeanFinderResult / properties / pathAdded value: +{ + "description": "Mathlib module path, dot-separated (e.g. Mathlib.Data.Nat.Basic)", + "title": "Path", + "type": "string" +} - added
Output schema / $defs / LeanFinderResult / properties / typeAdded value: +{ + "description": "Lean type signature / formal statement", + "title": "Type", + "type": "string" +} - changed
Output schema / $defs / LeanFinderResult / requiredPrevious value: -[ - "full_name", - "formal_statement", - "informal_statement" -]New value: +[ + "formal_name", + "informal_name", + "kind", + "type", + "informal_description", + "path" +]
- Added
lean_minimal_hypotheses - Changed
lean_multi_attempt2 fields changed- added
Output schema / $defs / AttemptResult / properties / proof_statusAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "REPL proof status when available (e.g. 'Completed', 'Incomplete: contains sorry')", + "title": "Proof Status" +} - added
Output schema / $defs / DiagnosticMessage / properties / lean_tagsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Lean-specific tags: 'unsolvedGoals' (proof incomplete here) or 'goalsAccomplished' (proof finished). Machine-readable proof status - prefer over string-matching the message.", + "title": "Lean Tags" +}
- Changed
lean_references2 fields changed- added
Input schema / properties / max_resultsAdded value: +{ + "anyOf": [ + { + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } + ], + "default": 50, + "description": "Max locations to return (default 50)", + "title": "Max Results" +} - added
Output schema / properties / totalAdded value: +{ + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Total matches (> len(items) when truncated by max_results)", + "title": "Total" +}
- Changed
lean_run_code1 field changed- added
Output schema / $defs / DiagnosticMessage / properties / lean_tagsAdded value: +{ + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Lean-specific tags: 'unsolvedGoals' (proof incomplete here) or 'goalsAccomplished' (proof finished). Machine-readable proof status - prefer over string-matching the message.", + "title": "Lean Tags" +}
22 tool updates
v0.10.0- Added
lean_build - Added
lean_code_actions - Added
lean_completions - Added
lean_declaration_file - Added
lean_diagnostic_messages - Added
lean_file_outline - Added
lean_get_widget_source - Added
lean_get_widgets - Added
lean_goal - Added
lean_hammer_premise - Added
lean_hover_info - Added
lean_leanfinder - Added
lean_leansearch - Added
lean_local_search - Added
lean_loogle - Added
lean_multi_attempt - Added
lean_profile_proof - Added
lean_references - Added
lean_run_code - Added
lean_state_search - Added
lean_term_goal - Added
lean_verify
TDQS
Scored across 22 tools
Most tools target distinct Lean/LSP operations, but there are four search-related tools (local_search, leanfinder, leansearch, loogle) plus related position-inspection tools (goal, term_goal, hover_info, declaration_file). Descriptions help distinguish them, but the overlap creates real misselection risk for an agent.
All tool names use a consistent lean_ snake_case prefix. The underlying pattern is mostly noun/feature-based rather than strictly verb_noun, with minor awkwardness in lean_leanfinder and lean_leansearch, but overall naming is predictable.
The domain is broad enough to justify many capabilities, but 22 tools is a heavy surface for an MCP server. It sits in the borderline 16-25 range and could likely be consolidated or grouped without losing much functionality.
The tool set covers the main Lean proof workflow: inspection, search, diagnostics, goal state, code actions, verification, profiling, and widgets. Gaps remain for full LSP coverage, such as rename/formatting operations, but core proof-development needs are well supported.
Maintenance
Related MCP Connectors
Ingest and search LogsLoom logs from coding agents.
Search arXiv/Semantic Scholar/OpenAlex + medical evidence (PubMed/Europe PMC) + LaTeX/PDF tools.
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Search GitHub, npm, PyPI, StackOverflow, ArXiv from one MCP — built for coding agents.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceProvides AI agents with language-aware code analysis through the Language Server Protocol, enabling tasks like getting code insights and diagnostics.3 npm192MIT
- AlicenseBqualityDmaintenanceMCP server for agentic interaction with the Lean theorem prover via LSP, providing tools for understanding, analyzing, and interacting with Lean projects.2122MIT
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to access Language Server Protocol operations such as hover, definitions, references, and rename through typed MCP tools.2Apache 2.0
- AlicenseAqualityAmaintenanceEnables AI coding agents to perform Lean 4 formal verification, navigate project symbols offline, and inspect C FFI bindings.51Apache 2.0