@treedy/lsp-mcp 0.1.3 → 0.1.5
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 +6 -0
- package/dist/index.js +199 -11
- package/dist/index.js.map +6 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,7 @@ Replace `{lang}` with `python` or `typescript`.
|
|
|
97
97
|
|------|-------------|
|
|
98
98
|
| `list_backends` | List available backends and their status |
|
|
99
99
|
| `start_backend` | Install and start a backend (downloads if needed) |
|
|
100
|
+
| `update_backend` | Update a backend to the latest version |
|
|
100
101
|
| `status` | Overall server and backend status with versions |
|
|
101
102
|
| `check_versions` | Detailed version info for server and all backends |
|
|
102
103
|
| `switch_python_backend` | Switch Python provider |
|
|
@@ -120,6 +121,11 @@ Replace `{lang}` with `python` or `typescript`.
|
|
|
120
121
|
typescript_definition file=/path/to/file.ts line=15 column=10
|
|
121
122
|
```
|
|
122
123
|
|
|
124
|
+
4. **Update a backend** (when new version is available):
|
|
125
|
+
```
|
|
126
|
+
update_backend language=python
|
|
127
|
+
```
|
|
128
|
+
|
|
123
129
|
## Available Prompts (Skills)
|
|
124
130
|
|
|
125
131
|
The server exposes skill documentation as MCP prompts that agents can request:
|
package/dist/index.js
CHANGED
|
@@ -19843,7 +19843,9 @@ 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);
|
|
19848
|
+
const eagerStart = getEnvBool("LSP_MCP_EAGER_START", false);
|
|
19847
19849
|
return {
|
|
19848
19850
|
python: {
|
|
19849
19851
|
enabled: pythonEnabled,
|
|
@@ -19852,7 +19854,11 @@ function loadConfig() {
|
|
|
19852
19854
|
typescript: {
|
|
19853
19855
|
enabled: typescriptEnabled
|
|
19854
19856
|
},
|
|
19855
|
-
|
|
19857
|
+
vue: {
|
|
19858
|
+
enabled: vueEnabled
|
|
19859
|
+
},
|
|
19860
|
+
autoUpdate,
|
|
19861
|
+
eagerStart
|
|
19856
19862
|
};
|
|
19857
19863
|
}
|
|
19858
19864
|
function getEnvBool(name, defaultValue) {
|
|
@@ -19890,6 +19896,14 @@ function getBackendCommand(language, config2) {
|
|
|
19890
19896
|
command: "npx",
|
|
19891
19897
|
args: autoUpdate ? ["--yes", "@treedy/typescript-lsp-mcp@latest"] : ["@treedy/typescript-lsp-mcp@latest"]
|
|
19892
19898
|
};
|
|
19899
|
+
} else if (language === "vue") {
|
|
19900
|
+
if (!config2.vue.enabled)
|
|
19901
|
+
return null;
|
|
19902
|
+
return {
|
|
19903
|
+
enabled: true,
|
|
19904
|
+
command: "npx",
|
|
19905
|
+
args: autoUpdate ? ["--yes", "@treedy/vue-lsp-mcp@latest"] : ["@treedy/vue-lsp-mcp@latest"]
|
|
19906
|
+
};
|
|
19893
19907
|
}
|
|
19894
19908
|
return null;
|
|
19895
19909
|
}
|
|
@@ -20673,6 +20687,8 @@ class BackendManager {
|
|
|
20673
20687
|
languages.push("python");
|
|
20674
20688
|
if (this.config.typescript.enabled)
|
|
20675
20689
|
languages.push("typescript");
|
|
20690
|
+
if (this.config.vue.enabled)
|
|
20691
|
+
languages.push("vue");
|
|
20676
20692
|
await Promise.all(languages.map(async (lang) => {
|
|
20677
20693
|
try {
|
|
20678
20694
|
const tools = await this.getTools(lang);
|
|
@@ -20702,6 +20718,9 @@ class BackendManager {
|
|
|
20702
20718
|
if (this.config.typescript.enabled && !this.backends.has("typescript")) {
|
|
20703
20719
|
status["typescript"] = { status: "not_started", tools: 0, restartCount: 0 };
|
|
20704
20720
|
}
|
|
20721
|
+
if (this.config.vue.enabled && !this.backends.has("vue")) {
|
|
20722
|
+
status["vue"] = { status: "not_started", tools: 0, restartCount: 0 };
|
|
20723
|
+
}
|
|
20705
20724
|
return status;
|
|
20706
20725
|
}
|
|
20707
20726
|
getVersions() {
|
|
@@ -20711,6 +20730,8 @@ class BackendManager {
|
|
|
20711
20730
|
languages.push("python");
|
|
20712
20731
|
if (this.config.typescript.enabled)
|
|
20713
20732
|
languages.push("typescript");
|
|
20733
|
+
if (this.config.vue.enabled)
|
|
20734
|
+
languages.push("vue");
|
|
20714
20735
|
for (const lang of languages) {
|
|
20715
20736
|
const backendConfig = getBackendCommand(lang, this.config);
|
|
20716
20737
|
const state = this.backends.get(lang);
|
|
@@ -20724,6 +20745,24 @@ class BackendManager {
|
|
|
20724
20745
|
}
|
|
20725
20746
|
return versions2;
|
|
20726
20747
|
}
|
|
20748
|
+
async restartBackend(language) {
|
|
20749
|
+
const existing = this.backends.get(language);
|
|
20750
|
+
const oldVersion = existing?.serverInfo?.version ?? null;
|
|
20751
|
+
if (existing) {
|
|
20752
|
+
console.error(`[BackendManager] Stopping ${language} for update...`);
|
|
20753
|
+
try {
|
|
20754
|
+
await existing.transport.close();
|
|
20755
|
+
await existing.client.close();
|
|
20756
|
+
} catch (error2) {
|
|
20757
|
+
console.error(`[BackendManager] Error closing ${language}:`, error2);
|
|
20758
|
+
}
|
|
20759
|
+
this.backends.delete(language);
|
|
20760
|
+
}
|
|
20761
|
+
console.error(`[BackendManager] Starting fresh ${language} backend...`);
|
|
20762
|
+
const state = await this.startBackend(language);
|
|
20763
|
+
const newVersion = state.serverInfo?.version ?? null;
|
|
20764
|
+
return { oldVersion, newVersion };
|
|
20765
|
+
}
|
|
20727
20766
|
async shutdown() {
|
|
20728
20767
|
console.error("[BackendManager] Shutting down all backends...");
|
|
20729
20768
|
const shutdownPromises = Array.from(this.backends.entries()).map(async ([lang, state]) => {
|
|
@@ -20767,6 +20806,9 @@ async function status(backendManager, config2) {
|
|
|
20767
20806
|
typescript: {
|
|
20768
20807
|
enabled: config2.typescript.enabled
|
|
20769
20808
|
},
|
|
20809
|
+
vue: {
|
|
20810
|
+
enabled: config2.vue.enabled
|
|
20811
|
+
},
|
|
20770
20812
|
autoUpdate: config2.autoUpdate
|
|
20771
20813
|
},
|
|
20772
20814
|
backends: backendStatus,
|
|
@@ -20824,6 +20866,13 @@ async function checkVersions(backendManager, config2) {
|
|
|
20824
20866
|
registry: "npm",
|
|
20825
20867
|
command: "npx --yes @treedy/typescript-lsp-mcp@latest"
|
|
20826
20868
|
}
|
|
20869
|
+
},
|
|
20870
|
+
vue: {
|
|
20871
|
+
"vue-lsp-mcp": {
|
|
20872
|
+
registry: "npm",
|
|
20873
|
+
command: "npx --yes @treedy/vue-lsp-mcp@latest",
|
|
20874
|
+
description: "Vue SFC support via Volar"
|
|
20875
|
+
}
|
|
20827
20876
|
}
|
|
20828
20877
|
},
|
|
20829
20878
|
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."
|
|
@@ -20866,13 +20915,21 @@ async function listBackends(backendManager, config2) {
|
|
|
20866
20915
|
tools: backendStatus.typescript?.tools || 0,
|
|
20867
20916
|
description: "TypeScript/JavaScript code intelligence",
|
|
20868
20917
|
startCommand: "Use start_backend tool with language='typescript'"
|
|
20918
|
+
},
|
|
20919
|
+
{
|
|
20920
|
+
name: "vue",
|
|
20921
|
+
enabled: config2.vue.enabled,
|
|
20922
|
+
status: backendStatus.vue?.status || "not_started",
|
|
20923
|
+
tools: backendStatus.vue?.tools || 0,
|
|
20924
|
+
description: "Vue Single File Component (.vue) code intelligence via Volar",
|
|
20925
|
+
startCommand: "Use start_backend tool with language='vue'"
|
|
20869
20926
|
}
|
|
20870
20927
|
];
|
|
20871
20928
|
const result = {
|
|
20872
20929
|
backends,
|
|
20873
20930
|
usage: {
|
|
20874
|
-
start: "Call start_backend with language='python' or '
|
|
20875
|
-
tools: "Once started, backend tools will be available as {language}_{tool} (e.g., python_hover)"
|
|
20931
|
+
start: "Call start_backend with language='python', 'typescript', or 'vue' to install and start a backend",
|
|
20932
|
+
tools: "Once started, backend tools will be available as {language}_{tool} (e.g., python_hover, vue_hover)"
|
|
20876
20933
|
}
|
|
20877
20934
|
};
|
|
20878
20935
|
return {
|
|
@@ -20880,7 +20937,7 @@ async function listBackends(backendManager, config2) {
|
|
|
20880
20937
|
};
|
|
20881
20938
|
}
|
|
20882
20939
|
var startBackendSchema = {
|
|
20883
|
-
language: exports_external.enum(["python", "typescript"]).describe("The backend to start")
|
|
20940
|
+
language: exports_external.enum(["python", "typescript", "vue"]).describe("The backend to start")
|
|
20884
20941
|
};
|
|
20885
20942
|
async function startBackend(language, backendManager, config2, registerToolsCallback) {
|
|
20886
20943
|
if (language === "python" && !config2.python.enabled) {
|
|
@@ -20907,6 +20964,18 @@ async function startBackend(language, backendManager, config2, registerToolsCall
|
|
|
20907
20964
|
}]
|
|
20908
20965
|
};
|
|
20909
20966
|
}
|
|
20967
|
+
if (language === "vue" && !config2.vue.enabled) {
|
|
20968
|
+
return {
|
|
20969
|
+
content: [{
|
|
20970
|
+
type: "text",
|
|
20971
|
+
text: JSON.stringify({
|
|
20972
|
+
success: false,
|
|
20973
|
+
error: "Vue backend is disabled",
|
|
20974
|
+
hint: "Set LSP_MCP_VUE_ENABLED=true to enable"
|
|
20975
|
+
}, null, 2)
|
|
20976
|
+
}]
|
|
20977
|
+
};
|
|
20978
|
+
}
|
|
20910
20979
|
try {
|
|
20911
20980
|
const toolCount = await registerToolsCallback(language);
|
|
20912
20981
|
const backendStatus = backendManager.getStatus();
|
|
@@ -20940,6 +21009,80 @@ async function startBackend(language, backendManager, config2, registerToolsCall
|
|
|
20940
21009
|
};
|
|
20941
21010
|
}
|
|
20942
21011
|
}
|
|
21012
|
+
var updateBackendSchema = {
|
|
21013
|
+
language: exports_external.enum(["python", "typescript", "vue"]).describe("The backend to update")
|
|
21014
|
+
};
|
|
21015
|
+
async function updateBackend(language, backendManager, config2, updateCallback) {
|
|
21016
|
+
if (language === "python" && !config2.python.enabled) {
|
|
21017
|
+
return {
|
|
21018
|
+
content: [{
|
|
21019
|
+
type: "text",
|
|
21020
|
+
text: JSON.stringify({
|
|
21021
|
+
success: false,
|
|
21022
|
+
error: "Python backend is disabled",
|
|
21023
|
+
hint: "Set LSP_MCP_PYTHON_ENABLED=true to enable"
|
|
21024
|
+
}, null, 2)
|
|
21025
|
+
}]
|
|
21026
|
+
};
|
|
21027
|
+
}
|
|
21028
|
+
if (language === "typescript" && !config2.typescript.enabled) {
|
|
21029
|
+
return {
|
|
21030
|
+
content: [{
|
|
21031
|
+
type: "text",
|
|
21032
|
+
text: JSON.stringify({
|
|
21033
|
+
success: false,
|
|
21034
|
+
error: "TypeScript backend is disabled",
|
|
21035
|
+
hint: "Set LSP_MCP_TYPESCRIPT_ENABLED=true to enable"
|
|
21036
|
+
}, null, 2)
|
|
21037
|
+
}]
|
|
21038
|
+
};
|
|
21039
|
+
}
|
|
21040
|
+
if (language === "vue" && !config2.vue.enabled) {
|
|
21041
|
+
return {
|
|
21042
|
+
content: [{
|
|
21043
|
+
type: "text",
|
|
21044
|
+
text: JSON.stringify({
|
|
21045
|
+
success: false,
|
|
21046
|
+
error: "Vue backend is disabled",
|
|
21047
|
+
hint: "Set LSP_MCP_VUE_ENABLED=true to enable"
|
|
21048
|
+
}, null, 2)
|
|
21049
|
+
}]
|
|
21050
|
+
};
|
|
21051
|
+
}
|
|
21052
|
+
try {
|
|
21053
|
+
const { oldVersion, newVersion } = await updateCallback(language);
|
|
21054
|
+
const backendStatus = backendManager.getStatus();
|
|
21055
|
+
const status2 = backendStatus[language];
|
|
21056
|
+
const updated = oldVersion !== newVersion;
|
|
21057
|
+
return {
|
|
21058
|
+
content: [{
|
|
21059
|
+
type: "text",
|
|
21060
|
+
text: JSON.stringify({
|
|
21061
|
+
success: true,
|
|
21062
|
+
language,
|
|
21063
|
+
updated,
|
|
21064
|
+
oldVersion,
|
|
21065
|
+
newVersion,
|
|
21066
|
+
serverName: status2?.serverName,
|
|
21067
|
+
tools: status2?.tools,
|
|
21068
|
+
message: updated ? `${language} backend updated from ${oldVersion} to ${newVersion}.` : `${language} backend is already at the latest version (${newVersion}).`
|
|
21069
|
+
}, null, 2)
|
|
21070
|
+
}]
|
|
21071
|
+
};
|
|
21072
|
+
} catch (error2) {
|
|
21073
|
+
return {
|
|
21074
|
+
content: [{
|
|
21075
|
+
type: "text",
|
|
21076
|
+
text: JSON.stringify({
|
|
21077
|
+
success: false,
|
|
21078
|
+
language,
|
|
21079
|
+
error: String(error2),
|
|
21080
|
+
hint: "Check network connection and try again"
|
|
21081
|
+
}, null, 2)
|
|
21082
|
+
}]
|
|
21083
|
+
};
|
|
21084
|
+
}
|
|
21085
|
+
}
|
|
20943
21086
|
|
|
20944
21087
|
// src/prompts.ts
|
|
20945
21088
|
var skillsContent = {
|
|
@@ -21520,6 +21663,7 @@ function registerBackendTools(language, tools) {
|
|
|
21520
21663
|
console.error(`[lsp-mcp] Registered ${namespacedName}`);
|
|
21521
21664
|
count++;
|
|
21522
21665
|
}
|
|
21666
|
+
server.sendToolListChanged();
|
|
21523
21667
|
return count;
|
|
21524
21668
|
}
|
|
21525
21669
|
async function startAndRegisterBackend(language) {
|
|
@@ -21540,6 +21684,19 @@ async function startAndRegisterBackend(language) {
|
|
|
21540
21684
|
throw error2;
|
|
21541
21685
|
}
|
|
21542
21686
|
}
|
|
21687
|
+
async function updateAndRestartBackend(language) {
|
|
21688
|
+
console.error(`[lsp-mcp] Updating ${language} backend...`);
|
|
21689
|
+
const result = await backendManager.restartBackend(language);
|
|
21690
|
+
if (startedBackends.has(language)) {
|
|
21691
|
+
console.error(`[lsp-mcp] ${language} backend updated, tools still available`);
|
|
21692
|
+
} else {
|
|
21693
|
+
const tools = await backendManager.getTools(language);
|
|
21694
|
+
registerBackendTools(language, tools);
|
|
21695
|
+
startedBackends.add(language);
|
|
21696
|
+
console.error(`[lsp-mcp] ${language} backend updated and ${tools.length} tools registered`);
|
|
21697
|
+
}
|
|
21698
|
+
return result;
|
|
21699
|
+
}
|
|
21543
21700
|
server.registerTool("status", { description: "Get status of all LSP backends and server configuration" }, async () => status(backendManager, config2));
|
|
21544
21701
|
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));
|
|
21545
21702
|
server.registerTool("switch_python_backend", {
|
|
@@ -21553,6 +21710,10 @@ server.registerTool("start_backend", {
|
|
|
21553
21710
|
description: "Start a backend and register its tools. This will download and install the backend if needed, then make its tools available.",
|
|
21554
21711
|
inputSchema: startBackendSchema
|
|
21555
21712
|
}, async ({ language }) => startBackend(language, backendManager, config2, startAndRegisterBackend));
|
|
21713
|
+
server.registerTool("update_backend", {
|
|
21714
|
+
description: "Update a backend to the latest version. This will restart the backend with the newest version available.",
|
|
21715
|
+
inputSchema: updateBackendSchema
|
|
21716
|
+
}, async ({ language }) => updateBackend(language, backendManager, config2, updateAndRestartBackend));
|
|
21556
21717
|
async function gracefulShutdown(signal) {
|
|
21557
21718
|
console.error(`
|
|
21558
21719
|
[lsp-mcp] Received ${signal}, shutting down gracefully...`);
|
|
@@ -21573,15 +21734,42 @@ async function main() {
|
|
|
21573
21734
|
console.error(` Version: ${packageJson.version}`);
|
|
21574
21735
|
console.error(" Python:", config2.python.enabled ? `enabled (${config2.python.provider})` : "disabled");
|
|
21575
21736
|
console.error(" TypeScript:", config2.typescript.enabled ? "enabled" : "disabled");
|
|
21576
|
-
console.error("");
|
|
21577
|
-
console.error("
|
|
21578
|
-
console.error(" - list_backends: See available backends and their status");
|
|
21579
|
-
console.error(" - start_backend: Install and start a backend (e.g., start_backend language=python)");
|
|
21580
|
-
console.error("");
|
|
21581
|
-
console.error("Prompts available: code-navigation, refactoring, code-analysis, lsp-rules, lsp-quick-start");
|
|
21737
|
+
console.error(" Vue:", config2.vue.enabled ? "enabled" : "disabled");
|
|
21738
|
+
console.error(" Eager Start:", config2.eagerStart ? "enabled" : "disabled");
|
|
21582
21739
|
console.error("");
|
|
21583
21740
|
const transport = new StdioServerTransport;
|
|
21584
21741
|
await server.connect(transport);
|
|
21742
|
+
if (config2.eagerStart) {
|
|
21743
|
+
console.error("Starting all enabled backends...");
|
|
21744
|
+
const languages = [];
|
|
21745
|
+
if (config2.python.enabled)
|
|
21746
|
+
languages.push("python");
|
|
21747
|
+
if (config2.typescript.enabled)
|
|
21748
|
+
languages.push("typescript");
|
|
21749
|
+
if (config2.vue.enabled)
|
|
21750
|
+
languages.push("vue");
|
|
21751
|
+
const results = await Promise.allSettled(languages.map(async (lang) => {
|
|
21752
|
+
try {
|
|
21753
|
+
const count = await startAndRegisterBackend(lang);
|
|
21754
|
+
return { lang, count };
|
|
21755
|
+
} catch (error2) {
|
|
21756
|
+
console.error(`[lsp-mcp] Failed to start ${lang}:`, error2);
|
|
21757
|
+
return { lang, error: error2 };
|
|
21758
|
+
}
|
|
21759
|
+
}));
|
|
21760
|
+
for (const result of results) {
|
|
21761
|
+
if (result.status === "fulfilled" && "count" in result.value) {
|
|
21762
|
+
console.error(` ${result.value.lang}: ${result.value.count} tools registered`);
|
|
21763
|
+
} else if (result.status === "fulfilled" && "error" in result.value) {
|
|
21764
|
+
console.error(` ${result.value.lang}: failed to start`);
|
|
21765
|
+
}
|
|
21766
|
+
}
|
|
21767
|
+
} else {
|
|
21768
|
+
console.error("Backends are loaded on-demand. Use these tools to get started:");
|
|
21769
|
+
console.error(" - list_backends: See available backends and their status");
|
|
21770
|
+
console.error(" - start_backend: Install and start a backend (e.g., start_backend language=python)");
|
|
21771
|
+
}
|
|
21772
|
+
console.error("");
|
|
21585
21773
|
console.error("Ready");
|
|
21586
21774
|
}
|
|
21587
21775
|
main().catch((error2) => {
|
|
@@ -21589,4 +21777,4 @@ main().catch((error2) => {
|
|
|
21589
21777
|
process.exit(1);
|
|
21590
21778
|
});
|
|
21591
21779
|
|
|
21592
|
-
//# debugId=
|
|
21780
|
+
//# debugId=93725E95ED75445864756E2164756E21
|