leanback 0.1.2__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {leanback-0.1.2 → leanback-0.1.3}/PKG-INFO +2 -2
- {leanback-0.1.2 → leanback-0.1.3}/pyproject.toml +10 -7
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/common/env.py +25 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/mcp_server.py +24 -0
- {leanback-0.1.2 → leanback-0.1.3}/.gitignore +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/LICENSE +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/README.md +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/README.md +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/__init__.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/check.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/common/__init__.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/common/errors.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/common/path_manager.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/common/project_context.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/common/util.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/goals.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/mathlib_search.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/mathlib_search_simple.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/mcp_test.py +0 -0
- {leanback-0.1.2 → leanback-0.1.3}/src/leanback/prove.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: leanback
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: MCP server for Lean 4 theorem proving — check, prove, goals, eval, search
|
|
5
5
|
Author: Stefan Szeider
|
|
6
6
|
License: Apache-2.0
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
15
15
|
Requires-Python: >=3.11
|
|
16
|
-
Requires-Dist: mcp>=1.
|
|
16
|
+
Requires-Dist: mcp>=1.26.0
|
|
17
17
|
Requires-Dist: rich>=14.0.0
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "leanback"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.3"
|
|
8
8
|
description = "MCP server for Lean 4 theorem proving — check, prove, goals, eval, search"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Apache-2.0" }
|
|
@@ -21,15 +21,15 @@ classifiers = [
|
|
|
21
21
|
]
|
|
22
22
|
dependencies = [
|
|
23
23
|
"rich>=14.0.0",
|
|
24
|
-
"mcp>=1.
|
|
24
|
+
"mcp>=1.26.0",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
[dependency-groups]
|
|
28
28
|
dev = [
|
|
29
|
-
"pytest>=
|
|
30
|
-
"ruff>=0.
|
|
31
|
-
"mypy>=1.
|
|
32
|
-
"coverage>=7.
|
|
29
|
+
"pytest>=9.0.0",
|
|
30
|
+
"ruff>=0.15.0",
|
|
31
|
+
"mypy>=1.19.0",
|
|
32
|
+
"coverage>=7.13.0",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
[tool.ruff]
|
|
@@ -47,6 +47,9 @@ line-length = 88
|
|
|
47
47
|
# Auto-fix issues
|
|
48
48
|
fix = true
|
|
49
49
|
|
|
50
|
+
# Exclude non-Python project directories
|
|
51
|
+
exclude = ["projects/"]
|
|
52
|
+
|
|
50
53
|
[tool.ruff.format]
|
|
51
54
|
# Black-compatible formatting
|
|
52
55
|
quote-style = "double"
|
|
@@ -87,7 +90,7 @@ lines-after-imports = 2
|
|
|
87
90
|
|
|
88
91
|
[tool.ruff.lint.per-file-ignores]
|
|
89
92
|
# Tests can use assert and have unused imports
|
|
90
|
-
"tests/*" = ["S101", "F401", "F841"]
|
|
93
|
+
"tests/*" = ["S101", "F401", "F841", "RUF059"]
|
|
91
94
|
"__init__.py" = ["F401"]
|
|
92
95
|
|
|
93
96
|
[tool.mypy]
|
|
@@ -6,9 +6,29 @@ This module provides functionality for executing Lean commands in the correct en
|
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
8
|
import subprocess
|
|
9
|
+
import sys
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
def _find_native_dynlibs(project_path: Path) -> list[Path]:
|
|
14
|
+
"""Discover native shared libraries in Lake packages.
|
|
15
|
+
|
|
16
|
+
Scans .lake/packages/*/.lake/build/lib/ for .so (Linux) or .dylib (macOS)
|
|
17
|
+
files that need --load-dynlib for the Lean interpreter.
|
|
18
|
+
"""
|
|
19
|
+
packages_dir = project_path / ".lake" / "packages"
|
|
20
|
+
if not packages_dir.is_dir():
|
|
21
|
+
return []
|
|
22
|
+
|
|
23
|
+
if sys.platform == "darwin":
|
|
24
|
+
ext = "dylib"
|
|
25
|
+
elif sys.platform == "win32":
|
|
26
|
+
ext = "dll"
|
|
27
|
+
else:
|
|
28
|
+
ext = "so"
|
|
29
|
+
return sorted(packages_dir.glob(f"*/.lake/build/lib/lib*.{ext}"))
|
|
30
|
+
|
|
31
|
+
|
|
12
32
|
class LeanRunner:
|
|
13
33
|
"""
|
|
14
34
|
Utility for running Lean commands in the appropriate environment.
|
|
@@ -53,6 +73,11 @@ class LeanRunner:
|
|
|
53
73
|
|
|
54
74
|
# Always use lake env lean for projects - this ensures proper dependency management
|
|
55
75
|
command = ["lake", "env", "lean"]
|
|
76
|
+
|
|
77
|
+
# Load native shared libraries for FFI-dependent packages (e.g., cvc5)
|
|
78
|
+
for lib in _find_native_dynlibs(project_path):
|
|
79
|
+
command.append(f"--load-dynlib={lib}")
|
|
80
|
+
|
|
56
81
|
if capture_json:
|
|
57
82
|
command.append("--json")
|
|
58
83
|
command.append(str(abs_file_path))
|
|
@@ -14,6 +14,8 @@ import time
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
16
|
from mcp.server.fastmcp import FastMCP
|
|
17
|
+
from mcp.server.fastmcp.exceptions import ToolError
|
|
18
|
+
from mcp.server.fastmcp.tools.tool_manager import ToolManager
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
def _json(obj: object) -> str:
|
|
@@ -87,6 +89,25 @@ modify files. Use your own file tools to create/edit .lean files, then use LeanB
|
|
|
87
89
|
)
|
|
88
90
|
|
|
89
91
|
|
|
92
|
+
class _StrictToolManager(ToolManager):
|
|
93
|
+
"""Rejects unknown parameters instead of silently dropping them."""
|
|
94
|
+
|
|
95
|
+
async def call_tool(self, name, arguments, context=None, **kwargs):
|
|
96
|
+
tool = self.get_tool(name)
|
|
97
|
+
if tool and arguments:
|
|
98
|
+
known = set(tool.parameters.get("properties", {}).keys())
|
|
99
|
+
unknown = set(arguments.keys()) - known
|
|
100
|
+
if unknown:
|
|
101
|
+
raise ToolError(
|
|
102
|
+
f"Unknown parameter(s) for '{name}': {', '.join(sorted(unknown))}. "
|
|
103
|
+
f"Valid parameters: {', '.join(sorted(known))}"
|
|
104
|
+
)
|
|
105
|
+
return await super().call_tool(name, arguments, context, **kwargs)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
mcp._tool_manager = _StrictToolManager()
|
|
109
|
+
|
|
110
|
+
|
|
90
111
|
def _resolve_project(project: str) -> Path | None:
|
|
91
112
|
"""Resolve and validate a project path. Returns Path or None."""
|
|
92
113
|
p = Path(project)
|
|
@@ -612,6 +633,9 @@ def check(
|
|
|
612
633
|
"total_info": info_count,
|
|
613
634
|
"files_with_errors": len(files_with_errors),
|
|
614
635
|
},
|
|
636
|
+
"hint": "This checked the entire project via 'lake build'. "
|
|
637
|
+
"To check specific code, use expr=. "
|
|
638
|
+
"To execute code, use the eval tool.",
|
|
615
639
|
}
|
|
616
640
|
return _json(result)
|
|
617
641
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|