@treedy/lsp-mcp 0.1.7 → 0.1.8
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.
- package/dist/bundled/pyright/dist/index.d.ts +2 -0
- package/dist/bundled/pyright/dist/index.js +1620 -0
- package/dist/bundled/pyright/dist/index.js.map +26 -0
- package/dist/bundled/pyright/dist/lsp/connection.d.ts +71 -0
- package/dist/bundled/pyright/dist/lsp/document-manager.d.ts +67 -0
- package/dist/bundled/pyright/dist/lsp/index.d.ts +3 -0
- package/dist/bundled/pyright/dist/lsp/types.d.ts +55 -0
- package/dist/bundled/pyright/dist/lsp-client.d.ts +55 -0
- package/dist/bundled/pyright/dist/tools/completions.d.ts +18 -0
- package/dist/bundled/pyright/dist/tools/definition.d.ts +16 -0
- package/dist/bundled/pyright/dist/tools/diagnostics.d.ts +12 -0
- package/dist/bundled/pyright/dist/tools/hover.d.ts +16 -0
- package/dist/bundled/pyright/dist/tools/references.d.ts +16 -0
- package/dist/bundled/pyright/dist/tools/rename.d.ts +18 -0
- package/dist/bundled/pyright/dist/tools/search.d.ts +20 -0
- package/dist/bundled/pyright/dist/tools/signature-help.d.ts +16 -0
- package/dist/bundled/pyright/dist/tools/status.d.ts +14 -0
- package/dist/bundled/pyright/dist/tools/symbols.d.ts +17 -0
- package/dist/bundled/pyright/dist/tools/update-document.d.ts +14 -0
- package/dist/bundled/pyright/dist/utils/position.d.ts +33 -0
- package/dist/bundled/pyright/package.json +54 -0
- package/dist/bundled/python/README.md +230 -0
- package/dist/bundled/python/pyproject.toml +61 -0
- package/dist/bundled/python/src/rope_mcp/__init__.py +3 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/__init__.cpython-312.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/config.cpython-312.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/config.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/pyright_client.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/rope_client.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/server.cpython-312.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/__pycache__/server.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/config.py +408 -0
- package/dist/bundled/python/src/rope_mcp/lsp/__init__.py +15 -0
- package/dist/bundled/python/src/rope_mcp/lsp/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/lsp/__pycache__/client.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/lsp/__pycache__/types.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/lsp/client.py +624 -0
- package/dist/bundled/python/src/rope_mcp/lsp/types.py +82 -0
- package/dist/bundled/python/src/rope_mcp/pyright_client.py +147 -0
- package/dist/bundled/python/src/rope_mcp/rope_client.py +198 -0
- package/dist/bundled/python/src/rope_mcp/server.py +963 -0
- package/dist/bundled/python/src/rope_mcp/tools/__init__.py +26 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/change_signature.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/completions.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/definition.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/diagnostics.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/hover.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/move.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/references.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/rename.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/search.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/__pycache__/symbols.cpython-313.pyc +0 -0
- package/dist/bundled/python/src/rope_mcp/tools/change_signature.py +184 -0
- package/dist/bundled/python/src/rope_mcp/tools/completions.py +84 -0
- package/dist/bundled/python/src/rope_mcp/tools/definition.py +51 -0
- package/dist/bundled/python/src/rope_mcp/tools/diagnostics.py +18 -0
- package/dist/bundled/python/src/rope_mcp/tools/hover.py +49 -0
- package/dist/bundled/python/src/rope_mcp/tools/move.py +81 -0
- package/dist/bundled/python/src/rope_mcp/tools/references.py +60 -0
- package/dist/bundled/python/src/rope_mcp/tools/rename.py +61 -0
- package/dist/bundled/python/src/rope_mcp/tools/search.py +128 -0
- package/dist/bundled/python/src/rope_mcp/tools/symbols.py +118 -0
- package/dist/bundled/python/uv.lock +979 -0
- package/dist/bundled/typescript/dist/index.js +29534 -0
- package/dist/bundled/typescript/dist/index.js.map +211 -0
- package/dist/bundled/typescript/package.json +46 -0
- package/dist/bundled/vue/dist/index.d.ts +8 -0
- package/dist/bundled/vue/dist/index.js +21111 -0
- package/dist/bundled/vue/dist/ts-vue-service.d.ts +67 -0
- package/dist/bundled/vue/dist/vue-service.d.ts +144 -0
- package/dist/bundled/vue/package.json +45 -0
- package/dist/index.js +148 -58
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Search tool implementation using ripgrep."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_search(
|
|
10
|
+
pattern: str,
|
|
11
|
+
path: Optional[str] = None,
|
|
12
|
+
glob: Optional[str] = None,
|
|
13
|
+
case_sensitive: bool = True,
|
|
14
|
+
max_results: int = 50,
|
|
15
|
+
) -> dict:
|
|
16
|
+
"""Search for a regex pattern in files using ripgrep.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
pattern: The regex pattern to search for
|
|
20
|
+
path: Directory or file to search in (defaults to current working directory)
|
|
21
|
+
glob: Glob pattern to filter files (e.g., "*.py", "**/*.ts")
|
|
22
|
+
case_sensitive: Whether the search is case sensitive
|
|
23
|
+
max_results: Maximum number of results to return
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Dict containing search results or error message
|
|
27
|
+
"""
|
|
28
|
+
search_path = path or os.getcwd()
|
|
29
|
+
|
|
30
|
+
# Build rg command
|
|
31
|
+
rg_args = [
|
|
32
|
+
"rg",
|
|
33
|
+
"--json",
|
|
34
|
+
"--line-number",
|
|
35
|
+
"--column",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
if not case_sensitive:
|
|
39
|
+
rg_args.append("--ignore-case")
|
|
40
|
+
|
|
41
|
+
if glob:
|
|
42
|
+
rg_args.extend(["--glob", glob])
|
|
43
|
+
|
|
44
|
+
rg_args.extend(["--", pattern, search_path])
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
result = subprocess.run(
|
|
48
|
+
rg_args,
|
|
49
|
+
capture_output=True,
|
|
50
|
+
text=True,
|
|
51
|
+
timeout=60,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# rg returns 1 when no matches found (not an error)
|
|
55
|
+
if result.returncode == 1 and not result.stdout.strip():
|
|
56
|
+
return {
|
|
57
|
+
"results": [],
|
|
58
|
+
"count": 0,
|
|
59
|
+
"message": f"No matches found for pattern: {pattern}",
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# rg returns 2 when there are errors but may still have results
|
|
63
|
+
# We should still try to parse any results we got
|
|
64
|
+
if result.returncode not in (0, 1, 2) or (
|
|
65
|
+
result.returncode != 0 and not result.stdout.strip()
|
|
66
|
+
):
|
|
67
|
+
return {
|
|
68
|
+
"error": f"ripgrep error: {result.stderr}",
|
|
69
|
+
"pattern": pattern,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
results = []
|
|
73
|
+
lines = result.stdout.strip().split("\n") if result.stdout.strip() else []
|
|
74
|
+
|
|
75
|
+
for line in lines:
|
|
76
|
+
if not line:
|
|
77
|
+
continue
|
|
78
|
+
if len(results) >= max_results:
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
data = json.loads(line)
|
|
83
|
+
if data.get("type") == "match":
|
|
84
|
+
match_data = data["data"]
|
|
85
|
+
file_path = match_data["path"]["text"]
|
|
86
|
+
line_number = match_data["line_number"]
|
|
87
|
+
line_text = match_data["lines"]["text"].rstrip()
|
|
88
|
+
|
|
89
|
+
# Get all submatches in this line
|
|
90
|
+
for submatch in match_data.get("submatches", []):
|
|
91
|
+
if len(results) >= max_results:
|
|
92
|
+
break
|
|
93
|
+
results.append(
|
|
94
|
+
{
|
|
95
|
+
"file": os.path.abspath(file_path),
|
|
96
|
+
"line": line_number,
|
|
97
|
+
"column": submatch["start"] + 1, # Convert to 1-based
|
|
98
|
+
"text": line_text,
|
|
99
|
+
"match": submatch["match"]["text"],
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
except (json.JSONDecodeError, KeyError):
|
|
103
|
+
# Skip non-JSON or malformed lines
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
"results": results,
|
|
108
|
+
"count": len(results),
|
|
109
|
+
"pattern": pattern,
|
|
110
|
+
"path": search_path,
|
|
111
|
+
"limited": len(results) >= max_results,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
except FileNotFoundError:
|
|
115
|
+
return {
|
|
116
|
+
"error": "ripgrep (rg) is not installed. Install with: brew install ripgrep",
|
|
117
|
+
"pattern": pattern,
|
|
118
|
+
}
|
|
119
|
+
except subprocess.TimeoutExpired:
|
|
120
|
+
return {
|
|
121
|
+
"error": "Search timed out",
|
|
122
|
+
"pattern": pattern,
|
|
123
|
+
}
|
|
124
|
+
except Exception as e:
|
|
125
|
+
return {
|
|
126
|
+
"error": str(e),
|
|
127
|
+
"pattern": pattern,
|
|
128
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Symbols tool implementation - document/workspace symbols."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_symbols(file: str, query: Optional[str] = None) -> dict:
|
|
8
|
+
"""Get symbols from a Python file.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
file: Absolute path to the Python file
|
|
12
|
+
query: Optional filter query for symbol names
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
Dict containing list of symbols or error message
|
|
16
|
+
"""
|
|
17
|
+
try:
|
|
18
|
+
# Read file directly - no need for Rope for AST parsing
|
|
19
|
+
with open(file, encoding="utf-8") as f:
|
|
20
|
+
source = f.read()
|
|
21
|
+
|
|
22
|
+
# Parse the AST to extract symbols
|
|
23
|
+
tree = ast.parse(source, filename=file)
|
|
24
|
+
symbols = _extract_symbols(tree, file)
|
|
25
|
+
|
|
26
|
+
# Filter by query if provided
|
|
27
|
+
if query:
|
|
28
|
+
query_lower = query.lower()
|
|
29
|
+
symbols = [s for s in symbols if query_lower in s["name"].lower()]
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
"symbols": symbols,
|
|
33
|
+
"count": len(symbols),
|
|
34
|
+
"file": file,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
except SyntaxError as e:
|
|
38
|
+
return {
|
|
39
|
+
"error": f"Syntax error: {e}",
|
|
40
|
+
"file": file,
|
|
41
|
+
}
|
|
42
|
+
except Exception as e:
|
|
43
|
+
return {
|
|
44
|
+
"error": str(e),
|
|
45
|
+
"file": file,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _extract_symbols(tree: ast.AST, file_path: str) -> list[dict]:
|
|
50
|
+
"""Extract symbols from an AST."""
|
|
51
|
+
symbols = []
|
|
52
|
+
|
|
53
|
+
for node in ast.walk(tree):
|
|
54
|
+
symbol = None
|
|
55
|
+
|
|
56
|
+
if isinstance(node, ast.ClassDef):
|
|
57
|
+
symbol = {
|
|
58
|
+
"name": node.name,
|
|
59
|
+
"kind": "Class",
|
|
60
|
+
"line": node.lineno,
|
|
61
|
+
"column": node.col_offset + 1,
|
|
62
|
+
"end_line": node.end_lineno,
|
|
63
|
+
"file": file_path,
|
|
64
|
+
}
|
|
65
|
+
elif isinstance(node, ast.FunctionDef | ast.AsyncFunctionDef):
|
|
66
|
+
# Check if it's a method (inside a class)
|
|
67
|
+
kind = "Function"
|
|
68
|
+
symbol = {
|
|
69
|
+
"name": node.name,
|
|
70
|
+
"kind": kind,
|
|
71
|
+
"line": node.lineno,
|
|
72
|
+
"column": node.col_offset + 1,
|
|
73
|
+
"end_line": node.end_lineno,
|
|
74
|
+
"file": file_path,
|
|
75
|
+
}
|
|
76
|
+
elif isinstance(node, ast.Assign):
|
|
77
|
+
# Module-level variable assignments
|
|
78
|
+
if isinstance(node, ast.Assign) and node.col_offset == 0:
|
|
79
|
+
for target in node.targets:
|
|
80
|
+
if isinstance(target, ast.Name):
|
|
81
|
+
symbol = {
|
|
82
|
+
"name": target.id,
|
|
83
|
+
"kind": "Variable",
|
|
84
|
+
"line": node.lineno,
|
|
85
|
+
"column": node.col_offset + 1,
|
|
86
|
+
"file": file_path,
|
|
87
|
+
}
|
|
88
|
+
symbols.append(symbol)
|
|
89
|
+
continue
|
|
90
|
+
elif isinstance(node, ast.Import):
|
|
91
|
+
for alias in node.names:
|
|
92
|
+
name = alias.asname or alias.name
|
|
93
|
+
symbol = {
|
|
94
|
+
"name": name,
|
|
95
|
+
"kind": "Module",
|
|
96
|
+
"line": node.lineno,
|
|
97
|
+
"column": node.col_offset + 1,
|
|
98
|
+
"file": file_path,
|
|
99
|
+
}
|
|
100
|
+
symbols.append(symbol)
|
|
101
|
+
continue
|
|
102
|
+
elif isinstance(node, ast.ImportFrom):
|
|
103
|
+
for alias in node.names:
|
|
104
|
+
name = alias.asname or alias.name
|
|
105
|
+
symbol = {
|
|
106
|
+
"name": name,
|
|
107
|
+
"kind": "Module",
|
|
108
|
+
"line": node.lineno,
|
|
109
|
+
"column": node.col_offset + 1,
|
|
110
|
+
"file": file_path,
|
|
111
|
+
}
|
|
112
|
+
symbols.append(symbol)
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
if symbol:
|
|
116
|
+
symbols.append(symbol)
|
|
117
|
+
|
|
118
|
+
return symbols
|