@treedy/lsp-mcp 0.1.6 → 0.1.7
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/index.js +121 -55
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20670,11 +20670,31 @@ class BackendManager {
|
|
|
20670
20670
|
if (state.status !== "ready") {
|
|
20671
20671
|
throw new Error(`${language} backend is not ready: ${state.lastError}`);
|
|
20672
20672
|
}
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
20673
|
+
try {
|
|
20674
|
+
const result = await state.client.callTool({
|
|
20675
|
+
name: toolName,
|
|
20676
|
+
arguments: args
|
|
20677
|
+
});
|
|
20678
|
+
return result;
|
|
20679
|
+
} catch (error2) {
|
|
20680
|
+
state.status = "error";
|
|
20681
|
+
state.lastError = String(error2);
|
|
20682
|
+
console.error(`[BackendManager] ${language} tool call failed, attempting restart:`, error2);
|
|
20683
|
+
try {
|
|
20684
|
+
await this.restartBackend(language);
|
|
20685
|
+
const restarted = this.backends.get(language);
|
|
20686
|
+
if (!restarted || restarted.status !== "ready") {
|
|
20687
|
+
throw new Error(`${language} backend failed to restart`);
|
|
20688
|
+
}
|
|
20689
|
+
const result = await restarted.client.callTool({
|
|
20690
|
+
name: toolName,
|
|
20691
|
+
arguments: args
|
|
20692
|
+
});
|
|
20693
|
+
return result;
|
|
20694
|
+
} catch (restartError) {
|
|
20695
|
+
throw new Error(`${language} backend error after restart: ${restartError}`);
|
|
20696
|
+
}
|
|
20697
|
+
}
|
|
20678
20698
|
}
|
|
20679
20699
|
async getTools(language) {
|
|
20680
20700
|
const state = await this.getBackend(language);
|
|
@@ -20748,6 +20768,7 @@ class BackendManager {
|
|
|
20748
20768
|
async restartBackend(language) {
|
|
20749
20769
|
const existing = this.backends.get(language);
|
|
20750
20770
|
const oldVersion = existing?.serverInfo?.version ?? null;
|
|
20771
|
+
const restartCount = (existing?.restartCount ?? 0) + 1;
|
|
20751
20772
|
if (existing) {
|
|
20752
20773
|
console.error(`[BackendManager] Stopping ${language} for update...`);
|
|
20753
20774
|
try {
|
|
@@ -20760,6 +20781,7 @@ class BackendManager {
|
|
|
20760
20781
|
}
|
|
20761
20782
|
console.error(`[BackendManager] Starting fresh ${language} backend...`);
|
|
20762
20783
|
const state = await this.startBackend(language);
|
|
20784
|
+
state.restartCount = restartCount;
|
|
20763
20785
|
const newVersion = state.serverInfo?.version ?? null;
|
|
20764
20786
|
return { oldVersion, newVersion };
|
|
20765
20787
|
}
|
|
@@ -21586,6 +21608,7 @@ var packageJson = require2("../package.json");
|
|
|
21586
21608
|
var config2 = loadConfig();
|
|
21587
21609
|
var backendManager = new BackendManager(config2);
|
|
21588
21610
|
var startedBackends = new Set;
|
|
21611
|
+
var registeredTools = new Set;
|
|
21589
21612
|
var server = new McpServer({
|
|
21590
21613
|
name: "lsp-mcp",
|
|
21591
21614
|
version: packageJson.version
|
|
@@ -21598,46 +21621,7 @@ function jsonSchemaToZod(schema) {
|
|
|
21598
21621
|
}
|
|
21599
21622
|
const required2 = new Set(schema.required || []);
|
|
21600
21623
|
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
21601
|
-
let zodType;
|
|
21602
|
-
switch (prop.type) {
|
|
21603
|
-
case "string":
|
|
21604
|
-
zodType = exports_external.string();
|
|
21605
|
-
if (prop.enum) {
|
|
21606
|
-
zodType = exports_external.enum(prop.enum);
|
|
21607
|
-
}
|
|
21608
|
-
break;
|
|
21609
|
-
case "number":
|
|
21610
|
-
case "integer":
|
|
21611
|
-
zodType = exports_external.number();
|
|
21612
|
-
if (prop.type === "integer") {
|
|
21613
|
-
zodType = zodType.int();
|
|
21614
|
-
}
|
|
21615
|
-
if (prop.exclusiveMinimum !== undefined) {
|
|
21616
|
-
zodType = zodType.gt(prop.exclusiveMinimum);
|
|
21617
|
-
}
|
|
21618
|
-
if (prop.minimum !== undefined) {
|
|
21619
|
-
zodType = zodType.gte(prop.minimum);
|
|
21620
|
-
}
|
|
21621
|
-
if (prop.maximum !== undefined) {
|
|
21622
|
-
zodType = zodType.lte(prop.maximum);
|
|
21623
|
-
}
|
|
21624
|
-
break;
|
|
21625
|
-
case "boolean":
|
|
21626
|
-
zodType = exports_external.boolean();
|
|
21627
|
-
break;
|
|
21628
|
-
case "array":
|
|
21629
|
-
if (prop.items?.type === "string") {
|
|
21630
|
-
zodType = exports_external.array(exports_external.string());
|
|
21631
|
-
} else {
|
|
21632
|
-
zodType = exports_external.array(exports_external.any());
|
|
21633
|
-
}
|
|
21634
|
-
break;
|
|
21635
|
-
case "object":
|
|
21636
|
-
zodType = exports_external.record(exports_external.any());
|
|
21637
|
-
break;
|
|
21638
|
-
default:
|
|
21639
|
-
zodType = exports_external.any();
|
|
21640
|
-
}
|
|
21624
|
+
let zodType = schemaToZod(prop);
|
|
21641
21625
|
if (prop.description) {
|
|
21642
21626
|
zodType = zodType.describe(prop.description);
|
|
21643
21627
|
}
|
|
@@ -21651,16 +21635,101 @@ function jsonSchemaToZod(schema) {
|
|
|
21651
21635
|
}
|
|
21652
21636
|
return result;
|
|
21653
21637
|
}
|
|
21638
|
+
function schemaToZod(schema) {
|
|
21639
|
+
if (!schema)
|
|
21640
|
+
return exports_external.any();
|
|
21641
|
+
if (schema.oneOf || schema.anyOf) {
|
|
21642
|
+
const variants = schema.oneOf ?? schema.anyOf;
|
|
21643
|
+
const mapped = variants.map((variant) => schemaToZod(variant));
|
|
21644
|
+
if (mapped.length === 1)
|
|
21645
|
+
return mapped[0];
|
|
21646
|
+
if (mapped.length > 1)
|
|
21647
|
+
return exports_external.union(mapped);
|
|
21648
|
+
return exports_external.any();
|
|
21649
|
+
}
|
|
21650
|
+
if (schema.allOf) {
|
|
21651
|
+
const variants = schema.allOf;
|
|
21652
|
+
if (variants.length === 0)
|
|
21653
|
+
return exports_external.any();
|
|
21654
|
+
return variants.map((variant) => schemaToZod(variant)).reduce((acc, next) => exports_external.intersection(acc, next));
|
|
21655
|
+
}
|
|
21656
|
+
if (schema.enum && schema.type === "string") {
|
|
21657
|
+
return exports_external.enum(schema.enum);
|
|
21658
|
+
}
|
|
21659
|
+
switch (schema.type) {
|
|
21660
|
+
case "string": {
|
|
21661
|
+
let zodType = exports_external.string();
|
|
21662
|
+
if (schema.minLength !== undefined)
|
|
21663
|
+
zodType = zodType.min(schema.minLength);
|
|
21664
|
+
if (schema.maxLength !== undefined)
|
|
21665
|
+
zodType = zodType.max(schema.maxLength);
|
|
21666
|
+
if (schema.pattern) {
|
|
21667
|
+
try {
|
|
21668
|
+
zodType = zodType.regex(new RegExp(schema.pattern));
|
|
21669
|
+
} catch {}
|
|
21670
|
+
}
|
|
21671
|
+
return zodType;
|
|
21672
|
+
}
|
|
21673
|
+
case "number":
|
|
21674
|
+
case "integer": {
|
|
21675
|
+
let zodType = exports_external.number();
|
|
21676
|
+
if (schema.type === "integer") {
|
|
21677
|
+
zodType = zodType.int();
|
|
21678
|
+
}
|
|
21679
|
+
if (schema.exclusiveMinimum !== undefined) {
|
|
21680
|
+
zodType = zodType.gt(schema.exclusiveMinimum);
|
|
21681
|
+
}
|
|
21682
|
+
if (schema.minimum !== undefined) {
|
|
21683
|
+
zodType = zodType.gte(schema.minimum);
|
|
21684
|
+
}
|
|
21685
|
+
if (schema.maximum !== undefined) {
|
|
21686
|
+
zodType = zodType.lte(schema.maximum);
|
|
21687
|
+
}
|
|
21688
|
+
return zodType;
|
|
21689
|
+
}
|
|
21690
|
+
case "boolean":
|
|
21691
|
+
return exports_external.boolean();
|
|
21692
|
+
case "array":
|
|
21693
|
+
return exports_external.array(schemaToZod(schema.items ?? {}));
|
|
21694
|
+
case "object": {
|
|
21695
|
+
if (schema.properties) {
|
|
21696
|
+
const shape = {};
|
|
21697
|
+
const required2 = new Set(schema.required || []);
|
|
21698
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
21699
|
+
let propSchema = schemaToZod(prop);
|
|
21700
|
+
if (prop.description) {
|
|
21701
|
+
propSchema = propSchema.describe(prop.description);
|
|
21702
|
+
}
|
|
21703
|
+
if (prop.default !== undefined) {
|
|
21704
|
+
propSchema = propSchema.default(prop.default);
|
|
21705
|
+
}
|
|
21706
|
+
if (!required2.has(key)) {
|
|
21707
|
+
propSchema = propSchema.optional();
|
|
21708
|
+
}
|
|
21709
|
+
shape[key] = propSchema;
|
|
21710
|
+
}
|
|
21711
|
+
return exports_external.object(shape).passthrough();
|
|
21712
|
+
}
|
|
21713
|
+
return exports_external.record(exports_external.any());
|
|
21714
|
+
}
|
|
21715
|
+
default:
|
|
21716
|
+
return exports_external.any();
|
|
21717
|
+
}
|
|
21718
|
+
}
|
|
21654
21719
|
function registerBackendTools(language, tools) {
|
|
21655
21720
|
let count = 0;
|
|
21656
21721
|
for (const tool of tools) {
|
|
21657
21722
|
const namespacedName = `${language}_${tool.name}`;
|
|
21723
|
+
if (registeredTools.has(namespacedName)) {
|
|
21724
|
+
continue;
|
|
21725
|
+
}
|
|
21658
21726
|
const zodSchema = jsonSchemaToZod(tool.inputSchema);
|
|
21659
21727
|
server.registerTool(namespacedName, {
|
|
21660
21728
|
description: tool.description || `${language} ${tool.name} tool`,
|
|
21661
21729
|
inputSchema: zodSchema
|
|
21662
21730
|
}, async (args) => backendManager.callTool(language, tool.name, args));
|
|
21663
21731
|
console.error(`[lsp-mcp] Registered ${namespacedName}`);
|
|
21732
|
+
registeredTools.add(namespacedName);
|
|
21664
21733
|
count++;
|
|
21665
21734
|
}
|
|
21666
21735
|
server.sendToolListChanged();
|
|
@@ -21677,7 +21746,7 @@ async function startAndRegisterBackend(language) {
|
|
|
21677
21746
|
const tools = await backendManager.getTools(language);
|
|
21678
21747
|
const count = registerBackendTools(language, tools);
|
|
21679
21748
|
startedBackends.add(language);
|
|
21680
|
-
console.error(`[lsp-mcp] ${language}: ${count} tools registered`);
|
|
21749
|
+
console.error(`[lsp-mcp] ${language}: ${count} new tools registered`);
|
|
21681
21750
|
return count;
|
|
21682
21751
|
} catch (error2) {
|
|
21683
21752
|
console.error(`[lsp-mcp] Failed to start ${language} backend:`, error2);
|
|
@@ -21687,14 +21756,10 @@ async function startAndRegisterBackend(language) {
|
|
|
21687
21756
|
async function updateAndRestartBackend(language) {
|
|
21688
21757
|
console.error(`[lsp-mcp] Updating ${language} backend...`);
|
|
21689
21758
|
const result = await backendManager.restartBackend(language);
|
|
21690
|
-
|
|
21691
|
-
|
|
21692
|
-
|
|
21693
|
-
|
|
21694
|
-
registerBackendTools(language, tools);
|
|
21695
|
-
startedBackends.add(language);
|
|
21696
|
-
console.error(`[lsp-mcp] ${language} backend updated and ${tools.length} tools registered`);
|
|
21697
|
-
}
|
|
21759
|
+
const tools = await backendManager.getTools(language);
|
|
21760
|
+
const newlyRegistered = registerBackendTools(language, tools);
|
|
21761
|
+
startedBackends.add(language);
|
|
21762
|
+
console.error(`[lsp-mcp] ${language} backend updated (${newlyRegistered} new tools registered)`);
|
|
21698
21763
|
return result;
|
|
21699
21764
|
}
|
|
21700
21765
|
server.registerTool("status", { description: "Get status of all LSP backends and server configuration" }, async () => status(backendManager, config2));
|
|
@@ -21792,6 +21857,7 @@ function preRegisterKnownTools() {
|
|
|
21792
21857
|
}
|
|
21793
21858
|
return backendManager.callTool(language, tool.name, args);
|
|
21794
21859
|
});
|
|
21860
|
+
registeredTools.add(namespacedName);
|
|
21795
21861
|
totalCount++;
|
|
21796
21862
|
}
|
|
21797
21863
|
console.error(`[lsp-mcp] Pre-registered ${tools.length} ${language} tools`);
|
|
@@ -21852,4 +21918,4 @@ main().catch((error2) => {
|
|
|
21852
21918
|
process.exit(1);
|
|
21853
21919
|
});
|
|
21854
21920
|
|
|
21855
|
-
//# debugId=
|
|
21921
|
+
//# debugId=55BC37C22EC14E0664756E2164756E21
|