@treedy/lsp-mcp 0.1.2 → 0.1.4
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/README.md +49 -22
- package/dist/index.js +360 -252
- package/dist/index.js.map +7 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19843,6 +19843,7 @@ function loadConfig() {
|
|
|
19843
19843
|
const pythonEnabled = getEnvBool("LSP_MCP_PYTHON_ENABLED", true);
|
|
19844
19844
|
const pythonProvider = getEnvString("LSP_MCP_PYTHON_PROVIDER", "python-lsp-mcp");
|
|
19845
19845
|
const typescriptEnabled = getEnvBool("LSP_MCP_TYPESCRIPT_ENABLED", true);
|
|
19846
|
+
const vueEnabled = getEnvBool("LSP_MCP_VUE_ENABLED", true);
|
|
19846
19847
|
const autoUpdate = getEnvBool("LSP_MCP_AUTO_UPDATE", true);
|
|
19847
19848
|
return {
|
|
19848
19849
|
python: {
|
|
@@ -19852,6 +19853,9 @@ function loadConfig() {
|
|
|
19852
19853
|
typescript: {
|
|
19853
19854
|
enabled: typescriptEnabled
|
|
19854
19855
|
},
|
|
19856
|
+
vue: {
|
|
19857
|
+
enabled: vueEnabled
|
|
19858
|
+
},
|
|
19855
19859
|
autoUpdate
|
|
19856
19860
|
};
|
|
19857
19861
|
}
|
|
@@ -19890,6 +19894,14 @@ function getBackendCommand(language, config2) {
|
|
|
19890
19894
|
command: "npx",
|
|
19891
19895
|
args: autoUpdate ? ["--yes", "@treedy/typescript-lsp-mcp@latest"] : ["@treedy/typescript-lsp-mcp@latest"]
|
|
19892
19896
|
};
|
|
19897
|
+
} else if (language === "vue") {
|
|
19898
|
+
if (!config2.vue.enabled)
|
|
19899
|
+
return null;
|
|
19900
|
+
return {
|
|
19901
|
+
enabled: true,
|
|
19902
|
+
command: "npx",
|
|
19903
|
+
args: autoUpdate ? ["--yes", "@treedy/vue-lsp-mcp@latest"] : ["@treedy/vue-lsp-mcp@latest"]
|
|
19904
|
+
};
|
|
19893
19905
|
}
|
|
19894
19906
|
return null;
|
|
19895
19907
|
}
|
|
@@ -20673,6 +20685,8 @@ class BackendManager {
|
|
|
20673
20685
|
languages.push("python");
|
|
20674
20686
|
if (this.config.typescript.enabled)
|
|
20675
20687
|
languages.push("typescript");
|
|
20688
|
+
if (this.config.vue.enabled)
|
|
20689
|
+
languages.push("vue");
|
|
20676
20690
|
await Promise.all(languages.map(async (lang) => {
|
|
20677
20691
|
try {
|
|
20678
20692
|
const tools = await this.getTools(lang);
|
|
@@ -20702,6 +20716,9 @@ class BackendManager {
|
|
|
20702
20716
|
if (this.config.typescript.enabled && !this.backends.has("typescript")) {
|
|
20703
20717
|
status["typescript"] = { status: "not_started", tools: 0, restartCount: 0 };
|
|
20704
20718
|
}
|
|
20719
|
+
if (this.config.vue.enabled && !this.backends.has("vue")) {
|
|
20720
|
+
status["vue"] = { status: "not_started", tools: 0, restartCount: 0 };
|
|
20721
|
+
}
|
|
20705
20722
|
return status;
|
|
20706
20723
|
}
|
|
20707
20724
|
getVersions() {
|
|
@@ -20711,6 +20728,8 @@ class BackendManager {
|
|
|
20711
20728
|
languages.push("python");
|
|
20712
20729
|
if (this.config.typescript.enabled)
|
|
20713
20730
|
languages.push("typescript");
|
|
20731
|
+
if (this.config.vue.enabled)
|
|
20732
|
+
languages.push("vue");
|
|
20714
20733
|
for (const lang of languages) {
|
|
20715
20734
|
const backendConfig = getBackendCommand(lang, this.config);
|
|
20716
20735
|
const state = this.backends.get(lang);
|
|
@@ -20724,6 +20743,24 @@ class BackendManager {
|
|
|
20724
20743
|
}
|
|
20725
20744
|
return versions2;
|
|
20726
20745
|
}
|
|
20746
|
+
async restartBackend(language) {
|
|
20747
|
+
const existing = this.backends.get(language);
|
|
20748
|
+
const oldVersion = existing?.serverInfo?.version ?? null;
|
|
20749
|
+
if (existing) {
|
|
20750
|
+
console.error(`[BackendManager] Stopping ${language} for update...`);
|
|
20751
|
+
try {
|
|
20752
|
+
await existing.transport.close();
|
|
20753
|
+
await existing.client.close();
|
|
20754
|
+
} catch (error2) {
|
|
20755
|
+
console.error(`[BackendManager] Error closing ${language}:`, error2);
|
|
20756
|
+
}
|
|
20757
|
+
this.backends.delete(language);
|
|
20758
|
+
}
|
|
20759
|
+
console.error(`[BackendManager] Starting fresh ${language} backend...`);
|
|
20760
|
+
const state = await this.startBackend(language);
|
|
20761
|
+
const newVersion = state.serverInfo?.version ?? null;
|
|
20762
|
+
return { oldVersion, newVersion };
|
|
20763
|
+
}
|
|
20727
20764
|
async shutdown() {
|
|
20728
20765
|
console.error("[BackendManager] Shutting down all backends...");
|
|
20729
20766
|
const shutdownPromises = Array.from(this.backends.entries()).map(async ([lang, state]) => {
|
|
@@ -20742,84 +20779,6 @@ class BackendManager {
|
|
|
20742
20779
|
}
|
|
20743
20780
|
}
|
|
20744
20781
|
|
|
20745
|
-
// src/backends/python.ts
|
|
20746
|
-
var pythonPositionSchema = {
|
|
20747
|
-
file: exports_external.string().describe("Absolute path to the Python file"),
|
|
20748
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
20749
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)")
|
|
20750
|
-
};
|
|
20751
|
-
var pythonToolDescriptions = {
|
|
20752
|
-
hover: "Get type information and documentation at a specific position in a Python file",
|
|
20753
|
-
definition: "Go to definition of a symbol at a specific position in a Python file",
|
|
20754
|
-
references: "Find all references to a symbol at a specific position in a Python file",
|
|
20755
|
-
completions: "Get code completion suggestions at a specific position in a Python file",
|
|
20756
|
-
diagnostics: "Get type errors and warnings for a Python file or directory",
|
|
20757
|
-
symbols: "Extract symbols (classes, functions, methods, variables) from a Python file",
|
|
20758
|
-
rename: "Rename a symbol and update all references in Python files",
|
|
20759
|
-
search: "Search for a regex pattern in Python files",
|
|
20760
|
-
signature_help: "Get function signature help at a specific position in a Python file",
|
|
20761
|
-
update_document: "Update file content for incremental analysis in Python",
|
|
20762
|
-
status: "Check Python/Pyright environment status",
|
|
20763
|
-
move: "Move a function or class to another Python module",
|
|
20764
|
-
change_signature: "Change the signature of a Python function",
|
|
20765
|
-
function_signature: "Get the current signature of a Python function",
|
|
20766
|
-
set_backend: "Set the backend (rope/pyright) for Python code analysis",
|
|
20767
|
-
set_python_path: "Set the Python interpreter path for code analysis"
|
|
20768
|
-
};
|
|
20769
|
-
|
|
20770
|
-
// src/backends/typescript.ts
|
|
20771
|
-
var typescriptPositionSchema = {
|
|
20772
|
-
file: exports_external.string().describe("Absolute path to the TypeScript/JavaScript file"),
|
|
20773
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
20774
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)")
|
|
20775
|
-
};
|
|
20776
|
-
var typescriptToolDescriptions = {
|
|
20777
|
-
hover: "Get type information and documentation at a specific position in a TypeScript/JavaScript file",
|
|
20778
|
-
definition: "Go to definition of a symbol at a specific position",
|
|
20779
|
-
references: "Find all references to a symbol at a specific position",
|
|
20780
|
-
completions: "Get code completion suggestions at a specific position",
|
|
20781
|
-
diagnostics: "Get type errors and warnings for a TypeScript/JavaScript file",
|
|
20782
|
-
symbols: "Extract symbols (classes, functions, methods, variables) from a file",
|
|
20783
|
-
rename: "Preview renaming a symbol (shows all locations that would be renamed)",
|
|
20784
|
-
search: "Search for a regex pattern in TypeScript/JavaScript files",
|
|
20785
|
-
signature_help: "Get function signature help at a specific position",
|
|
20786
|
-
update_document: "Update file content for incremental analysis",
|
|
20787
|
-
status: "Check TypeScript environment status for a project"
|
|
20788
|
-
};
|
|
20789
|
-
|
|
20790
|
-
// src/tools/schemas.ts
|
|
20791
|
-
var positionArgs = {
|
|
20792
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
20793
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
20794
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)")
|
|
20795
|
-
};
|
|
20796
|
-
var searchArgs = {
|
|
20797
|
-
pattern: exports_external.string().describe("The regex pattern to search for"),
|
|
20798
|
-
path: exports_external.string().optional().describe("Directory or file to search in"),
|
|
20799
|
-
glob: exports_external.string().optional().describe("Glob pattern to filter files"),
|
|
20800
|
-
caseSensitive: exports_external.boolean().default(true).describe("Whether the search is case sensitive"),
|
|
20801
|
-
maxResults: exports_external.number().int().positive().default(50).describe("Maximum number of results")
|
|
20802
|
-
};
|
|
20803
|
-
var diagnosticsArgs = {
|
|
20804
|
-
path: exports_external.string().describe("Path to a file or directory to check")
|
|
20805
|
-
};
|
|
20806
|
-
var renameArgs = {
|
|
20807
|
-
...positionArgs,
|
|
20808
|
-
newName: exports_external.string().describe("New name for the symbol")
|
|
20809
|
-
};
|
|
20810
|
-
var symbolsArgs = {
|
|
20811
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
20812
|
-
query: exports_external.string().optional().describe("Optional filter query for symbol names")
|
|
20813
|
-
};
|
|
20814
|
-
var updateDocumentArgs = {
|
|
20815
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
20816
|
-
content: exports_external.string().describe("New content for the file")
|
|
20817
|
-
};
|
|
20818
|
-
var completionsArgs = {
|
|
20819
|
-
...positionArgs,
|
|
20820
|
-
limit: exports_external.number().int().positive().default(20).describe("Maximum number of completions to return")
|
|
20821
|
-
};
|
|
20822
|
-
|
|
20823
20782
|
// src/tools/meta.ts
|
|
20824
20783
|
import { readFileSync } from "fs";
|
|
20825
20784
|
import { dirname, join } from "path";
|
|
@@ -20845,6 +20804,9 @@ async function status(backendManager, config2) {
|
|
|
20845
20804
|
typescript: {
|
|
20846
20805
|
enabled: config2.typescript.enabled
|
|
20847
20806
|
},
|
|
20807
|
+
vue: {
|
|
20808
|
+
enabled: config2.vue.enabled
|
|
20809
|
+
},
|
|
20848
20810
|
autoUpdate: config2.autoUpdate
|
|
20849
20811
|
},
|
|
20850
20812
|
backends: backendStatus,
|
|
@@ -20855,8 +20817,9 @@ async function status(backendManager, config2) {
|
|
|
20855
20817
|
status: v.status
|
|
20856
20818
|
})),
|
|
20857
20819
|
usage: {
|
|
20858
|
-
|
|
20859
|
-
|
|
20820
|
+
list: "Use list_backends to see available backends",
|
|
20821
|
+
start: "Use start_backend to install and start a backend",
|
|
20822
|
+
tools: "Once started, tools are available as python_hover, typescript_definition, etc."
|
|
20860
20823
|
}
|
|
20861
20824
|
};
|
|
20862
20825
|
return {
|
|
@@ -20901,6 +20864,13 @@ async function checkVersions(backendManager, config2) {
|
|
|
20901
20864
|
registry: "npm",
|
|
20902
20865
|
command: "npx --yes @treedy/typescript-lsp-mcp@latest"
|
|
20903
20866
|
}
|
|
20867
|
+
},
|
|
20868
|
+
vue: {
|
|
20869
|
+
"vue-lsp-mcp": {
|
|
20870
|
+
registry: "npm",
|
|
20871
|
+
command: "npx --yes @treedy/vue-lsp-mcp@latest",
|
|
20872
|
+
description: "Vue SFC support via Volar"
|
|
20873
|
+
}
|
|
20904
20874
|
}
|
|
20905
20875
|
},
|
|
20906
20876
|
howToUpdate: config2.autoUpdate ? "Restart the server to fetch latest backend versions automatically." : "Set LSP_MCP_AUTO_UPDATE=true and restart, or manually update with commands above."
|
|
@@ -20924,6 +20894,193 @@ function switchPythonBackend(provider) {
|
|
|
20924
20894
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
20925
20895
|
};
|
|
20926
20896
|
}
|
|
20897
|
+
async function listBackends(backendManager, config2) {
|
|
20898
|
+
const backendStatus = backendManager.getStatus();
|
|
20899
|
+
const backends = [
|
|
20900
|
+
{
|
|
20901
|
+
name: "python",
|
|
20902
|
+
enabled: config2.python.enabled,
|
|
20903
|
+
provider: config2.python.provider,
|
|
20904
|
+
status: backendStatus.python?.status || "not_started",
|
|
20905
|
+
tools: backendStatus.python?.tools || 0,
|
|
20906
|
+
description: "Python code intelligence (hover, definition, references, refactoring)",
|
|
20907
|
+
startCommand: "Use start_backend tool with language='python'"
|
|
20908
|
+
},
|
|
20909
|
+
{
|
|
20910
|
+
name: "typescript",
|
|
20911
|
+
enabled: config2.typescript.enabled,
|
|
20912
|
+
status: backendStatus.typescript?.status || "not_started",
|
|
20913
|
+
tools: backendStatus.typescript?.tools || 0,
|
|
20914
|
+
description: "TypeScript/JavaScript code intelligence",
|
|
20915
|
+
startCommand: "Use start_backend tool with language='typescript'"
|
|
20916
|
+
},
|
|
20917
|
+
{
|
|
20918
|
+
name: "vue",
|
|
20919
|
+
enabled: config2.vue.enabled,
|
|
20920
|
+
status: backendStatus.vue?.status || "not_started",
|
|
20921
|
+
tools: backendStatus.vue?.tools || 0,
|
|
20922
|
+
description: "Vue Single File Component (.vue) code intelligence via Volar",
|
|
20923
|
+
startCommand: "Use start_backend tool with language='vue'"
|
|
20924
|
+
}
|
|
20925
|
+
];
|
|
20926
|
+
const result = {
|
|
20927
|
+
backends,
|
|
20928
|
+
usage: {
|
|
20929
|
+
start: "Call start_backend with language='python', 'typescript', or 'vue' to install and start a backend",
|
|
20930
|
+
tools: "Once started, backend tools will be available as {language}_{tool} (e.g., python_hover, vue_hover)"
|
|
20931
|
+
}
|
|
20932
|
+
};
|
|
20933
|
+
return {
|
|
20934
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
20935
|
+
};
|
|
20936
|
+
}
|
|
20937
|
+
var startBackendSchema = {
|
|
20938
|
+
language: exports_external.enum(["python", "typescript", "vue"]).describe("The backend to start")
|
|
20939
|
+
};
|
|
20940
|
+
async function startBackend(language, backendManager, config2, registerToolsCallback) {
|
|
20941
|
+
if (language === "python" && !config2.python.enabled) {
|
|
20942
|
+
return {
|
|
20943
|
+
content: [{
|
|
20944
|
+
type: "text",
|
|
20945
|
+
text: JSON.stringify({
|
|
20946
|
+
success: false,
|
|
20947
|
+
error: "Python backend is disabled",
|
|
20948
|
+
hint: "Set LSP_MCP_PYTHON_ENABLED=true to enable"
|
|
20949
|
+
}, null, 2)
|
|
20950
|
+
}]
|
|
20951
|
+
};
|
|
20952
|
+
}
|
|
20953
|
+
if (language === "typescript" && !config2.typescript.enabled) {
|
|
20954
|
+
return {
|
|
20955
|
+
content: [{
|
|
20956
|
+
type: "text",
|
|
20957
|
+
text: JSON.stringify({
|
|
20958
|
+
success: false,
|
|
20959
|
+
error: "TypeScript backend is disabled",
|
|
20960
|
+
hint: "Set LSP_MCP_TYPESCRIPT_ENABLED=true to enable"
|
|
20961
|
+
}, null, 2)
|
|
20962
|
+
}]
|
|
20963
|
+
};
|
|
20964
|
+
}
|
|
20965
|
+
if (language === "vue" && !config2.vue.enabled) {
|
|
20966
|
+
return {
|
|
20967
|
+
content: [{
|
|
20968
|
+
type: "text",
|
|
20969
|
+
text: JSON.stringify({
|
|
20970
|
+
success: false,
|
|
20971
|
+
error: "Vue backend is disabled",
|
|
20972
|
+
hint: "Set LSP_MCP_VUE_ENABLED=true to enable"
|
|
20973
|
+
}, null, 2)
|
|
20974
|
+
}]
|
|
20975
|
+
};
|
|
20976
|
+
}
|
|
20977
|
+
try {
|
|
20978
|
+
const toolCount = await registerToolsCallback(language);
|
|
20979
|
+
const backendStatus = backendManager.getStatus();
|
|
20980
|
+
const status2 = backendStatus[language];
|
|
20981
|
+
return {
|
|
20982
|
+
content: [{
|
|
20983
|
+
type: "text",
|
|
20984
|
+
text: JSON.stringify({
|
|
20985
|
+
success: true,
|
|
20986
|
+
language,
|
|
20987
|
+
status: status2?.status,
|
|
20988
|
+
serverName: status2?.serverName,
|
|
20989
|
+
version: status2?.version,
|
|
20990
|
+
toolsRegistered: toolCount,
|
|
20991
|
+
message: `${language} backend started successfully. ${toolCount} tools are now available.`,
|
|
20992
|
+
usage: `Tools are available as ${language}_hover, ${language}_definition, etc.`
|
|
20993
|
+
}, null, 2)
|
|
20994
|
+
}]
|
|
20995
|
+
};
|
|
20996
|
+
} catch (error2) {
|
|
20997
|
+
return {
|
|
20998
|
+
content: [{
|
|
20999
|
+
type: "text",
|
|
21000
|
+
text: JSON.stringify({
|
|
21001
|
+
success: false,
|
|
21002
|
+
language,
|
|
21003
|
+
error: String(error2),
|
|
21004
|
+
hint: "Check if the backend package is available and network connection is working"
|
|
21005
|
+
}, null, 2)
|
|
21006
|
+
}]
|
|
21007
|
+
};
|
|
21008
|
+
}
|
|
21009
|
+
}
|
|
21010
|
+
var updateBackendSchema = {
|
|
21011
|
+
language: exports_external.enum(["python", "typescript", "vue"]).describe("The backend to update")
|
|
21012
|
+
};
|
|
21013
|
+
async function updateBackend(language, backendManager, config2, updateCallback) {
|
|
21014
|
+
if (language === "python" && !config2.python.enabled) {
|
|
21015
|
+
return {
|
|
21016
|
+
content: [{
|
|
21017
|
+
type: "text",
|
|
21018
|
+
text: JSON.stringify({
|
|
21019
|
+
success: false,
|
|
21020
|
+
error: "Python backend is disabled",
|
|
21021
|
+
hint: "Set LSP_MCP_PYTHON_ENABLED=true to enable"
|
|
21022
|
+
}, null, 2)
|
|
21023
|
+
}]
|
|
21024
|
+
};
|
|
21025
|
+
}
|
|
21026
|
+
if (language === "typescript" && !config2.typescript.enabled) {
|
|
21027
|
+
return {
|
|
21028
|
+
content: [{
|
|
21029
|
+
type: "text",
|
|
21030
|
+
text: JSON.stringify({
|
|
21031
|
+
success: false,
|
|
21032
|
+
error: "TypeScript backend is disabled",
|
|
21033
|
+
hint: "Set LSP_MCP_TYPESCRIPT_ENABLED=true to enable"
|
|
21034
|
+
}, null, 2)
|
|
21035
|
+
}]
|
|
21036
|
+
};
|
|
21037
|
+
}
|
|
21038
|
+
if (language === "vue" && !config2.vue.enabled) {
|
|
21039
|
+
return {
|
|
21040
|
+
content: [{
|
|
21041
|
+
type: "text",
|
|
21042
|
+
text: JSON.stringify({
|
|
21043
|
+
success: false,
|
|
21044
|
+
error: "Vue backend is disabled",
|
|
21045
|
+
hint: "Set LSP_MCP_VUE_ENABLED=true to enable"
|
|
21046
|
+
}, null, 2)
|
|
21047
|
+
}]
|
|
21048
|
+
};
|
|
21049
|
+
}
|
|
21050
|
+
try {
|
|
21051
|
+
const { oldVersion, newVersion } = await updateCallback(language);
|
|
21052
|
+
const backendStatus = backendManager.getStatus();
|
|
21053
|
+
const status2 = backendStatus[language];
|
|
21054
|
+
const updated = oldVersion !== newVersion;
|
|
21055
|
+
return {
|
|
21056
|
+
content: [{
|
|
21057
|
+
type: "text",
|
|
21058
|
+
text: JSON.stringify({
|
|
21059
|
+
success: true,
|
|
21060
|
+
language,
|
|
21061
|
+
updated,
|
|
21062
|
+
oldVersion,
|
|
21063
|
+
newVersion,
|
|
21064
|
+
serverName: status2?.serverName,
|
|
21065
|
+
tools: status2?.tools,
|
|
21066
|
+
message: updated ? `${language} backend updated from ${oldVersion} to ${newVersion}.` : `${language} backend is already at the latest version (${newVersion}).`
|
|
21067
|
+
}, null, 2)
|
|
21068
|
+
}]
|
|
21069
|
+
};
|
|
21070
|
+
} catch (error2) {
|
|
21071
|
+
return {
|
|
21072
|
+
content: [{
|
|
21073
|
+
type: "text",
|
|
21074
|
+
text: JSON.stringify({
|
|
21075
|
+
success: false,
|
|
21076
|
+
language,
|
|
21077
|
+
error: String(error2),
|
|
21078
|
+
hint: "Check network connection and try again"
|
|
21079
|
+
}, null, 2)
|
|
21080
|
+
}]
|
|
21081
|
+
};
|
|
21082
|
+
}
|
|
21083
|
+
}
|
|
20927
21084
|
|
|
20928
21085
|
// src/prompts.ts
|
|
20929
21086
|
var skillsContent = {
|
|
@@ -21426,186 +21583,134 @@ var require2 = createRequire2(import.meta.url);
|
|
|
21426
21583
|
var packageJson = require2("../package.json");
|
|
21427
21584
|
var config2 = loadConfig();
|
|
21428
21585
|
var backendManager = new BackendManager(config2);
|
|
21586
|
+
var startedBackends = new Set;
|
|
21429
21587
|
var server = new McpServer({
|
|
21430
21588
|
name: "lsp-mcp",
|
|
21431
21589
|
version: packageJson.version
|
|
21432
21590
|
});
|
|
21433
21591
|
registerPrompts(server);
|
|
21592
|
+
function jsonSchemaToZod(schema) {
|
|
21593
|
+
const result = {};
|
|
21594
|
+
if (!schema || !schema.properties) {
|
|
21595
|
+
return result;
|
|
21596
|
+
}
|
|
21597
|
+
const required2 = new Set(schema.required || []);
|
|
21598
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
21599
|
+
let zodType;
|
|
21600
|
+
switch (prop.type) {
|
|
21601
|
+
case "string":
|
|
21602
|
+
zodType = exports_external.string();
|
|
21603
|
+
if (prop.enum) {
|
|
21604
|
+
zodType = exports_external.enum(prop.enum);
|
|
21605
|
+
}
|
|
21606
|
+
break;
|
|
21607
|
+
case "number":
|
|
21608
|
+
case "integer":
|
|
21609
|
+
zodType = exports_external.number();
|
|
21610
|
+
if (prop.type === "integer") {
|
|
21611
|
+
zodType = zodType.int();
|
|
21612
|
+
}
|
|
21613
|
+
if (prop.exclusiveMinimum !== undefined) {
|
|
21614
|
+
zodType = zodType.gt(prop.exclusiveMinimum);
|
|
21615
|
+
}
|
|
21616
|
+
if (prop.minimum !== undefined) {
|
|
21617
|
+
zodType = zodType.gte(prop.minimum);
|
|
21618
|
+
}
|
|
21619
|
+
if (prop.maximum !== undefined) {
|
|
21620
|
+
zodType = zodType.lte(prop.maximum);
|
|
21621
|
+
}
|
|
21622
|
+
break;
|
|
21623
|
+
case "boolean":
|
|
21624
|
+
zodType = exports_external.boolean();
|
|
21625
|
+
break;
|
|
21626
|
+
case "array":
|
|
21627
|
+
if (prop.items?.type === "string") {
|
|
21628
|
+
zodType = exports_external.array(exports_external.string());
|
|
21629
|
+
} else {
|
|
21630
|
+
zodType = exports_external.array(exports_external.any());
|
|
21631
|
+
}
|
|
21632
|
+
break;
|
|
21633
|
+
case "object":
|
|
21634
|
+
zodType = exports_external.record(exports_external.any());
|
|
21635
|
+
break;
|
|
21636
|
+
default:
|
|
21637
|
+
zodType = exports_external.any();
|
|
21638
|
+
}
|
|
21639
|
+
if (prop.description) {
|
|
21640
|
+
zodType = zodType.describe(prop.description);
|
|
21641
|
+
}
|
|
21642
|
+
if (prop.default !== undefined) {
|
|
21643
|
+
zodType = zodType.default(prop.default);
|
|
21644
|
+
}
|
|
21645
|
+
if (!required2.has(key)) {
|
|
21646
|
+
zodType = zodType.optional();
|
|
21647
|
+
}
|
|
21648
|
+
result[key] = zodType;
|
|
21649
|
+
}
|
|
21650
|
+
return result;
|
|
21651
|
+
}
|
|
21652
|
+
function registerBackendTools(language, tools) {
|
|
21653
|
+
let count = 0;
|
|
21654
|
+
for (const tool of tools) {
|
|
21655
|
+
const namespacedName = `${language}_${tool.name}`;
|
|
21656
|
+
const zodSchema = jsonSchemaToZod(tool.inputSchema);
|
|
21657
|
+
server.registerTool(namespacedName, {
|
|
21658
|
+
description: tool.description || `${language} ${tool.name} tool`,
|
|
21659
|
+
inputSchema: zodSchema
|
|
21660
|
+
}, async (args) => backendManager.callTool(language, tool.name, args));
|
|
21661
|
+
console.error(`[lsp-mcp] Registered ${namespacedName}`);
|
|
21662
|
+
count++;
|
|
21663
|
+
}
|
|
21664
|
+
return count;
|
|
21665
|
+
}
|
|
21666
|
+
async function startAndRegisterBackend(language) {
|
|
21667
|
+
if (startedBackends.has(language)) {
|
|
21668
|
+
const status2 = backendManager.getStatus()[language];
|
|
21669
|
+
console.error(`[lsp-mcp] ${language} backend already started (${status2?.tools} tools)`);
|
|
21670
|
+
return status2?.tools || 0;
|
|
21671
|
+
}
|
|
21672
|
+
console.error(`[lsp-mcp] Starting ${language} backend...`);
|
|
21673
|
+
try {
|
|
21674
|
+
const tools = await backendManager.getTools(language);
|
|
21675
|
+
const count = registerBackendTools(language, tools);
|
|
21676
|
+
startedBackends.add(language);
|
|
21677
|
+
console.error(`[lsp-mcp] ${language}: ${count} tools registered`);
|
|
21678
|
+
return count;
|
|
21679
|
+
} catch (error2) {
|
|
21680
|
+
console.error(`[lsp-mcp] Failed to start ${language} backend:`, error2);
|
|
21681
|
+
throw error2;
|
|
21682
|
+
}
|
|
21683
|
+
}
|
|
21684
|
+
async function updateAndRestartBackend(language) {
|
|
21685
|
+
console.error(`[lsp-mcp] Updating ${language} backend...`);
|
|
21686
|
+
const result = await backendManager.restartBackend(language);
|
|
21687
|
+
if (startedBackends.has(language)) {
|
|
21688
|
+
console.error(`[lsp-mcp] ${language} backend updated, tools still available`);
|
|
21689
|
+
} else {
|
|
21690
|
+
const tools = await backendManager.getTools(language);
|
|
21691
|
+
registerBackendTools(language, tools);
|
|
21692
|
+
startedBackends.add(language);
|
|
21693
|
+
console.error(`[lsp-mcp] ${language} backend updated and ${tools.length} tools registered`);
|
|
21694
|
+
}
|
|
21695
|
+
return result;
|
|
21696
|
+
}
|
|
21434
21697
|
server.registerTool("status", { description: "Get status of all LSP backends and server configuration" }, async () => status(backendManager, config2));
|
|
21435
21698
|
server.registerTool("check_versions", { description: "Check versions of all backends and server. Shows installed versions and how to check for updates." }, async () => checkVersions(backendManager, config2));
|
|
21436
21699
|
server.registerTool("switch_python_backend", {
|
|
21437
21700
|
description: "Switch the Python backend provider (requires restart)",
|
|
21438
21701
|
inputSchema: switchPythonBackendSchema
|
|
21439
21702
|
}, async ({ provider }) => switchPythonBackend(provider));
|
|
21440
|
-
|
|
21441
|
-
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
|
|
21445
|
-
|
|
21446
|
-
|
|
21447
|
-
|
|
21448
|
-
|
|
21449
|
-
|
|
21450
|
-
|
|
21451
|
-
description: pythonToolDescriptions.references,
|
|
21452
|
-
inputSchema: { ...positionArgs, backend: backendOption }
|
|
21453
|
-
}, async (args) => backendManager.callTool("python", "references", args));
|
|
21454
|
-
server.registerTool("python/completions", {
|
|
21455
|
-
description: pythonToolDescriptions.completions,
|
|
21456
|
-
inputSchema: { ...completionsArgs, backend: backendOption }
|
|
21457
|
-
}, async (args) => backendManager.callTool("python", "completions", args));
|
|
21458
|
-
server.registerTool("python/diagnostics", {
|
|
21459
|
-
description: pythonToolDescriptions.diagnostics,
|
|
21460
|
-
inputSchema: diagnosticsArgs
|
|
21461
|
-
}, async (args) => backendManager.callTool("python", "diagnostics", args));
|
|
21462
|
-
server.registerTool("python/symbols", {
|
|
21463
|
-
description: pythonToolDescriptions.symbols,
|
|
21464
|
-
inputSchema: { ...symbolsArgs, backend: backendOption }
|
|
21465
|
-
}, async (args) => backendManager.callTool("python", "symbols", args));
|
|
21466
|
-
server.registerTool("python/rename", {
|
|
21467
|
-
description: pythonToolDescriptions.rename,
|
|
21468
|
-
inputSchema: { ...positionArgs, new_name: exports_external.string().describe("New name for the symbol") }
|
|
21469
|
-
}, async (args) => backendManager.callTool("python", "rename", args));
|
|
21470
|
-
server.registerTool("python/search", {
|
|
21471
|
-
description: pythonToolDescriptions.search,
|
|
21472
|
-
inputSchema: searchArgs
|
|
21473
|
-
}, async (args) => backendManager.callTool("python", "search", args));
|
|
21474
|
-
server.registerTool("python/signature_help", {
|
|
21475
|
-
description: pythonToolDescriptions.signature_help,
|
|
21476
|
-
inputSchema: positionArgs
|
|
21477
|
-
}, async (args) => backendManager.callTool("python", "signature_help", args));
|
|
21478
|
-
server.registerTool("python/update_document", {
|
|
21479
|
-
description: pythonToolDescriptions.update_document,
|
|
21480
|
-
inputSchema: updateDocumentArgs
|
|
21481
|
-
}, async (args) => backendManager.callTool("python", "update_document", args));
|
|
21482
|
-
server.registerTool("python/status", {
|
|
21483
|
-
description: pythonToolDescriptions.status
|
|
21484
|
-
}, async () => backendManager.callTool("python", "status", {}));
|
|
21485
|
-
server.registerTool("python/move", {
|
|
21486
|
-
description: pythonToolDescriptions.move,
|
|
21487
|
-
inputSchema: {
|
|
21488
|
-
...positionArgs,
|
|
21489
|
-
destination: exports_external.string().describe('Destination module path (e.g., "mypackage.utils")'),
|
|
21490
|
-
preview: exports_external.boolean().default(false).describe("If true, only show what would change")
|
|
21491
|
-
}
|
|
21492
|
-
}, async (args) => backendManager.callTool("python", "move", args));
|
|
21493
|
-
server.registerTool("python/change_signature", {
|
|
21494
|
-
description: pythonToolDescriptions.change_signature,
|
|
21495
|
-
inputSchema: {
|
|
21496
|
-
...positionArgs,
|
|
21497
|
-
new_params: exports_external.array(exports_external.string()).optional().describe("New parameter order"),
|
|
21498
|
-
add_param: exports_external.string().optional().describe("Name of parameter to add"),
|
|
21499
|
-
add_param_default: exports_external.string().optional().describe("Default value for added parameter"),
|
|
21500
|
-
add_param_index: exports_external.number().int().optional().describe("Index where to insert new param"),
|
|
21501
|
-
remove_param: exports_external.string().optional().describe("Name of parameter to remove"),
|
|
21502
|
-
preview: exports_external.boolean().default(false).describe("If true, only show what would change")
|
|
21503
|
-
}
|
|
21504
|
-
}, async (args) => backendManager.callTool("python", "change_signature", args));
|
|
21505
|
-
server.registerTool("python/function_signature", {
|
|
21506
|
-
description: pythonToolDescriptions.function_signature,
|
|
21507
|
-
inputSchema: positionArgs
|
|
21508
|
-
}, async (args) => backendManager.callTool("python", "function_signature", args));
|
|
21509
|
-
server.registerTool("python/set_backend", {
|
|
21510
|
-
description: pythonToolDescriptions.set_backend,
|
|
21511
|
-
inputSchema: {
|
|
21512
|
-
backend: exports_external.enum(["rope", "pyright"]).describe("The backend to use"),
|
|
21513
|
-
tool: exports_external.string().optional().describe("Optional tool name to set backend for")
|
|
21514
|
-
}
|
|
21515
|
-
}, async (args) => backendManager.callTool("python", "set_backend", args));
|
|
21516
|
-
server.registerTool("python/set_python_path", {
|
|
21517
|
-
description: pythonToolDescriptions.set_python_path,
|
|
21518
|
-
inputSchema: {
|
|
21519
|
-
python_path: exports_external.string().describe("Absolute path to the Python interpreter"),
|
|
21520
|
-
workspace: exports_external.string().optional().describe("Optional workspace to set the path for")
|
|
21521
|
-
}
|
|
21522
|
-
}, async (args) => backendManager.callTool("python", "set_python_path", args));
|
|
21523
|
-
}
|
|
21524
|
-
if (config2.typescript.enabled) {
|
|
21525
|
-
server.registerTool("typescript/hover", {
|
|
21526
|
-
description: typescriptToolDescriptions.hover,
|
|
21527
|
-
inputSchema: positionArgs
|
|
21528
|
-
}, async (args) => backendManager.callTool("typescript", "hover", args));
|
|
21529
|
-
server.registerTool("typescript/definition", {
|
|
21530
|
-
description: typescriptToolDescriptions.definition,
|
|
21531
|
-
inputSchema: positionArgs
|
|
21532
|
-
}, async (args) => backendManager.callTool("typescript", "definition", args));
|
|
21533
|
-
server.registerTool("typescript/references", {
|
|
21534
|
-
description: typescriptToolDescriptions.references,
|
|
21535
|
-
inputSchema: positionArgs
|
|
21536
|
-
}, async (args) => backendManager.callTool("typescript", "references", args));
|
|
21537
|
-
server.registerTool("typescript/completions", {
|
|
21538
|
-
description: typescriptToolDescriptions.completions,
|
|
21539
|
-
inputSchema: completionsArgs
|
|
21540
|
-
}, async (args) => backendManager.callTool("typescript", "completions", args));
|
|
21541
|
-
server.registerTool("typescript/diagnostics", {
|
|
21542
|
-
description: typescriptToolDescriptions.diagnostics,
|
|
21543
|
-
inputSchema: diagnosticsArgs
|
|
21544
|
-
}, async (args) => backendManager.callTool("typescript", "diagnostics", args));
|
|
21545
|
-
server.registerTool("typescript/symbols", {
|
|
21546
|
-
description: typescriptToolDescriptions.symbols,
|
|
21547
|
-
inputSchema: symbolsArgs
|
|
21548
|
-
}, async (args) => backendManager.callTool("typescript", "symbols", args));
|
|
21549
|
-
server.registerTool("typescript/rename", {
|
|
21550
|
-
description: typescriptToolDescriptions.rename,
|
|
21551
|
-
inputSchema: renameArgs
|
|
21552
|
-
}, async (args) => backendManager.callTool("typescript", "rename", args));
|
|
21553
|
-
server.registerTool("typescript/search", {
|
|
21554
|
-
description: typescriptToolDescriptions.search,
|
|
21555
|
-
inputSchema: searchArgs
|
|
21556
|
-
}, async (args) => backendManager.callTool("typescript", "search", args));
|
|
21557
|
-
server.registerTool("typescript/signature_help", {
|
|
21558
|
-
description: typescriptToolDescriptions.signature_help,
|
|
21559
|
-
inputSchema: positionArgs
|
|
21560
|
-
}, async (args) => backendManager.callTool("typescript", "signature_help", args));
|
|
21561
|
-
server.registerTool("typescript/update_document", {
|
|
21562
|
-
description: typescriptToolDescriptions.update_document,
|
|
21563
|
-
inputSchema: updateDocumentArgs
|
|
21564
|
-
}, async (args) => backendManager.callTool("typescript", "update_document", args));
|
|
21565
|
-
server.registerTool("typescript/status", {
|
|
21566
|
-
description: typescriptToolDescriptions.status,
|
|
21567
|
-
inputSchema: {
|
|
21568
|
-
file: exports_external.string().describe("A TypeScript/JavaScript file to check project status for")
|
|
21569
|
-
}
|
|
21570
|
-
}, async (args) => backendManager.callTool("typescript", "status", args));
|
|
21571
|
-
server.registerTool("typescript/move", {
|
|
21572
|
-
description: "Move a function, class, or variable to a new file",
|
|
21573
|
-
inputSchema: {
|
|
21574
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
21575
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
21576
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)"),
|
|
21577
|
-
destination: exports_external.string().optional().describe("Destination file path (optional)"),
|
|
21578
|
-
preview: exports_external.boolean().default(false).describe("If true, only show what would change")
|
|
21579
|
-
}
|
|
21580
|
-
}, async (args) => backendManager.callTool("typescript", "move", args));
|
|
21581
|
-
server.registerTool("typescript/function_signature", {
|
|
21582
|
-
description: "Get the current signature of a function at a specific position",
|
|
21583
|
-
inputSchema: {
|
|
21584
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
21585
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
21586
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)")
|
|
21587
|
-
}
|
|
21588
|
-
}, async (args) => backendManager.callTool("typescript", "function_signature", args));
|
|
21589
|
-
server.registerTool("typescript/available_refactors", {
|
|
21590
|
-
description: "Get available refactoring actions at a specific position",
|
|
21591
|
-
inputSchema: {
|
|
21592
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
21593
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
21594
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)")
|
|
21595
|
-
}
|
|
21596
|
-
}, async (args) => backendManager.callTool("typescript", "available_refactors", args));
|
|
21597
|
-
server.registerTool("typescript/apply_refactor", {
|
|
21598
|
-
description: "Apply a specific refactoring action at a position",
|
|
21599
|
-
inputSchema: {
|
|
21600
|
-
file: exports_external.string().describe("Absolute path to the file"),
|
|
21601
|
-
line: exports_external.number().int().positive().describe("Line number (1-based)"),
|
|
21602
|
-
column: exports_external.number().int().positive().describe("Column number (1-based)"),
|
|
21603
|
-
refactorName: exports_external.string().describe("Name of the refactoring"),
|
|
21604
|
-
actionName: exports_external.string().describe("Name of the action"),
|
|
21605
|
-
preview: exports_external.boolean().default(false).describe("If true, only show what would change")
|
|
21606
|
-
}
|
|
21607
|
-
}, async (args) => backendManager.callTool("typescript", "apply_refactor", args));
|
|
21608
|
-
}
|
|
21703
|
+
server.registerTool("list_backends", {
|
|
21704
|
+
description: "List available backends and their status. Shows which backends are installed, running, and how many tools they provide."
|
|
21705
|
+
}, async () => listBackends(backendManager, config2));
|
|
21706
|
+
server.registerTool("start_backend", {
|
|
21707
|
+
description: "Start a backend and register its tools. This will download and install the backend if needed, then make its tools available.",
|
|
21708
|
+
inputSchema: startBackendSchema
|
|
21709
|
+
}, async ({ language }) => startBackend(language, backendManager, config2, startAndRegisterBackend));
|
|
21710
|
+
server.registerTool("update_backend", {
|
|
21711
|
+
description: "Update a backend to the latest version. This will restart the backend with the newest version available.",
|
|
21712
|
+
inputSchema: updateBackendSchema
|
|
21713
|
+
}, async ({ language }) => updateBackend(language, backendManager, config2, updateAndRestartBackend));
|
|
21609
21714
|
async function gracefulShutdown(signal) {
|
|
21610
21715
|
console.error(`
|
|
21611
21716
|
[lsp-mcp] Received ${signal}, shutting down gracefully...`);
|
|
@@ -21623,12 +21728,15 @@ process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
|
|
|
21623
21728
|
process.on("SIGINT", () => gracefulShutdown("SIGINT"));
|
|
21624
21729
|
async function main() {
|
|
21625
21730
|
console.error("LSP MCP Server - Unified Multi-Language Code Intelligence");
|
|
21731
|
+
console.error(` Version: ${packageJson.version}`);
|
|
21626
21732
|
console.error(" Python:", config2.python.enabled ? `enabled (${config2.python.provider})` : "disabled");
|
|
21627
21733
|
console.error(" TypeScript:", config2.typescript.enabled ? "enabled" : "disabled");
|
|
21628
21734
|
console.error("");
|
|
21629
|
-
console.error("
|
|
21735
|
+
console.error("Backends are loaded on-demand. Use these tools to get started:");
|
|
21736
|
+
console.error(" - list_backends: See available backends and their status");
|
|
21737
|
+
console.error(" - start_backend: Install and start a backend (e.g., start_backend language=python)");
|
|
21738
|
+
console.error("");
|
|
21630
21739
|
console.error("Prompts available: code-navigation, refactoring, code-analysis, lsp-rules, lsp-quick-start");
|
|
21631
|
-
console.error("Backends start lazily on first tool call.");
|
|
21632
21740
|
console.error("");
|
|
21633
21741
|
const transport = new StdioServerTransport;
|
|
21634
21742
|
await server.connect(transport);
|
|
@@ -21639,4 +21747,4 @@ main().catch((error2) => {
|
|
|
21639
21747
|
process.exit(1);
|
|
21640
21748
|
});
|
|
21641
21749
|
|
|
21642
|
-
//# debugId=
|
|
21750
|
+
//# debugId=0931320CB6D5336A64756E2164756E21
|