@treedy/lsp-mcp 0.1.0 → 0.1.3

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 CHANGED
@@ -5,10 +5,10 @@ Unified MCP server aggregating multi-language LSP backends for code intelligence
5
5
  ## Features
6
6
 
7
7
  - **Unified Entry Point**: Single MCP server for multiple languages
8
- - **Namespaced Tools**: `python/hover`, `typescript/definition`, etc.
9
- - **Auto Language Detection**: Infers language from file extensions
8
+ - **Namespaced Tools**: `python_hover`, `typescript_definition`, etc.
9
+ - **On-Demand Loading**: Backends are installed and started only when needed
10
+ - **Dynamic Tool Registration**: Backend tools are discovered automatically
10
11
  - **Skill Prompts**: Best practices exposed as MCP prompts for agents
11
- - **Lazy Loading**: Backends start on first use
12
12
  - **Graceful Degradation**: Clear error messages when backends unavailable
13
13
 
14
14
  ## Installation
@@ -67,17 +67,17 @@ This ensures backends are always up-to-date when the server starts. To disable a
67
67
 
68
68
  | Tool | Description |
69
69
  |------|-------------|
70
- | `{lang}/hover` | Get type information and documentation |
71
- | `{lang}/definition` | Go to definition |
72
- | `{lang}/references` | Find all references |
73
- | `{lang}/completions` | Code completion suggestions |
74
- | `{lang}/diagnostics` | Type errors and warnings |
75
- | `{lang}/symbols` | Extract symbols from file |
76
- | `{lang}/rename` | Rename symbol |
77
- | `{lang}/search` | Regex pattern search |
78
- | `{lang}/signature_help` | Function signature help |
79
- | `{lang}/update_document` | Update file for incremental analysis |
80
- | `{lang}/status` | Backend status |
70
+ | `{lang}_hover` | Get type information and documentation |
71
+ | `{lang}_definition` | Go to definition |
72
+ | `{lang}_references` | Find all references |
73
+ | `{lang}_completions` | Code completion suggestions |
74
+ | `{lang}_diagnostics` | Type errors and warnings |
75
+ | `{lang}_symbols` | Extract symbols from file |
76
+ | `{lang}_rename` | Rename symbol |
77
+ | `{lang}_search` | Regex pattern search |
78
+ | `{lang}_signature_help` | Function signature help |
79
+ | `{lang}_update_document` | Update file for incremental analysis |
80
+ | `{lang}_status` | Backend status |
81
81
 
82
82
  Replace `{lang}` with `python` or `typescript`.
83
83
 
@@ -85,20 +85,41 @@ Replace `{lang}` with `python` or `typescript`.
85
85
 
86
86
  | Tool | Description |
87
87
  |------|-------------|
88
- | `python/move` | Move function/class to another module |
89
- | `python/change_signature` | Modify function signature |
90
- | `python/function_signature` | Get current function signature |
91
- | `python/set_backend` | Switch between rope/pyright |
92
- | `python/set_python_path` | Set Python interpreter |
88
+ | `python_move` | Move function/class to another module |
89
+ | `python_change_signature` | Modify function signature |
90
+ | `python_function_signature` | Get current function signature |
91
+ | `python_set_backend` | Switch between rope/pyright |
92
+ | `python_set_python_path` | Set Python interpreter |
93
93
 
94
94
  ### Meta Tools
95
95
 
96
96
  | Tool | Description |
97
97
  |------|-------------|
98
+ | `list_backends` | List available backends and their status |
99
+ | `start_backend` | Install and start a backend (downloads if needed) |
98
100
  | `status` | Overall server and backend status with versions |
99
101
  | `check_versions` | Detailed version info for server and all backends |
100
102
  | `switch_python_backend` | Switch Python provider |
101
103
 
104
+ ## Quick Start
105
+
106
+ 1. **List available backends**:
107
+ ```
108
+ list_backends
109
+ ```
110
+
111
+ 2. **Start a backend** (this will download and install if needed):
112
+ ```
113
+ start_backend language=python
114
+ start_backend language=typescript
115
+ ```
116
+
117
+ 3. **Use backend tools** (available after starting):
118
+ ```
119
+ python_hover file=/path/to/file.py line=10 column=5
120
+ typescript_definition file=/path/to/file.ts line=15 column=10
121
+ ```
122
+
102
123
  ## Available Prompts (Skills)
103
124
 
104
125
  The server exposes skill documentation as MCP prompts that agents can request:
@@ -142,7 +163,7 @@ Repeat until clean
142
163
 
143
164
  ```json
144
165
  {
145
- "name": "python/hover",
166
+ "name": "python_hover",
146
167
  "arguments": {
147
168
  "file": "/path/to/file.py",
148
169
  "line": 10,
@@ -155,7 +176,7 @@ Repeat until clean
155
176
 
156
177
  ```json
157
178
  {
158
- "name": "typescript/definition",
179
+ "name": "typescript_definition",
159
180
  "arguments": {
160
181
  "file": "/path/to/file.ts",
161
182
  "line": 15,
@@ -193,7 +214,7 @@ This will automatically route to the Python backend.
193
214
  │ │
194
215
  │ ┌────────────────────────────────────────────────────────────┐ │
195
216
  │ │ Tool Router │ │
196
- │ │ - Parse tool name (python/hover → {lang, tool}) │ │
217
+ │ │ - Parse tool name (python_hover → {lang, tool}) │ │
197
218
  │ │ - Infer language from file extension │ │
198
219
  │ │ - Route to appropriate backend │ │
199
220
  │ └────────────────────────────────────────────────────────────┘ │
package/dist/index.js CHANGED
@@ -19835,6 +19835,9 @@ class StdioServerTransport {
19835
19835
  }
19836
19836
  }
19837
19837
 
19838
+ // src/index.ts
19839
+ import { createRequire as createRequire2 } from "module";
19840
+
19838
19841
  // src/config.ts
19839
19842
  function loadConfig() {
19840
19843
  const pythonEnabled = getEnvBool("LSP_MCP_PYTHON_ENABLED", true);
@@ -20739,84 +20742,6 @@ class BackendManager {
20739
20742
  }
20740
20743
  }
20741
20744
 
20742
- // src/backends/python.ts
20743
- var pythonPositionSchema = {
20744
- file: exports_external.string().describe("Absolute path to the Python file"),
20745
- line: exports_external.number().int().positive().describe("Line number (1-based)"),
20746
- column: exports_external.number().int().positive().describe("Column number (1-based)")
20747
- };
20748
- var pythonToolDescriptions = {
20749
- hover: "Get type information and documentation at a specific position in a Python file",
20750
- definition: "Go to definition of a symbol at a specific position in a Python file",
20751
- references: "Find all references to a symbol at a specific position in a Python file",
20752
- completions: "Get code completion suggestions at a specific position in a Python file",
20753
- diagnostics: "Get type errors and warnings for a Python file or directory",
20754
- symbols: "Extract symbols (classes, functions, methods, variables) from a Python file",
20755
- rename: "Rename a symbol and update all references in Python files",
20756
- search: "Search for a regex pattern in Python files",
20757
- signature_help: "Get function signature help at a specific position in a Python file",
20758
- update_document: "Update file content for incremental analysis in Python",
20759
- status: "Check Python/Pyright environment status",
20760
- move: "Move a function or class to another Python module",
20761
- change_signature: "Change the signature of a Python function",
20762
- function_signature: "Get the current signature of a Python function",
20763
- set_backend: "Set the backend (rope/pyright) for Python code analysis",
20764
- set_python_path: "Set the Python interpreter path for code analysis"
20765
- };
20766
-
20767
- // src/backends/typescript.ts
20768
- var typescriptPositionSchema = {
20769
- file: exports_external.string().describe("Absolute path to the TypeScript/JavaScript file"),
20770
- line: exports_external.number().int().positive().describe("Line number (1-based)"),
20771
- column: exports_external.number().int().positive().describe("Column number (1-based)")
20772
- };
20773
- var typescriptToolDescriptions = {
20774
- hover: "Get type information and documentation at a specific position in a TypeScript/JavaScript file",
20775
- definition: "Go to definition of a symbol at a specific position",
20776
- references: "Find all references to a symbol at a specific position",
20777
- completions: "Get code completion suggestions at a specific position",
20778
- diagnostics: "Get type errors and warnings for a TypeScript/JavaScript file",
20779
- symbols: "Extract symbols (classes, functions, methods, variables) from a file",
20780
- rename: "Preview renaming a symbol (shows all locations that would be renamed)",
20781
- search: "Search for a regex pattern in TypeScript/JavaScript files",
20782
- signature_help: "Get function signature help at a specific position",
20783
- update_document: "Update file content for incremental analysis",
20784
- status: "Check TypeScript environment status for a project"
20785
- };
20786
-
20787
- // src/tools/schemas.ts
20788
- var positionArgs = {
20789
- file: exports_external.string().describe("Absolute path to the file"),
20790
- line: exports_external.number().int().positive().describe("Line number (1-based)"),
20791
- column: exports_external.number().int().positive().describe("Column number (1-based)")
20792
- };
20793
- var searchArgs = {
20794
- pattern: exports_external.string().describe("The regex pattern to search for"),
20795
- path: exports_external.string().optional().describe("Directory or file to search in"),
20796
- glob: exports_external.string().optional().describe("Glob pattern to filter files"),
20797
- caseSensitive: exports_external.boolean().default(true).describe("Whether the search is case sensitive"),
20798
- maxResults: exports_external.number().int().positive().default(50).describe("Maximum number of results")
20799
- };
20800
- var diagnosticsArgs = {
20801
- path: exports_external.string().describe("Path to a file or directory to check")
20802
- };
20803
- var renameArgs = {
20804
- ...positionArgs,
20805
- newName: exports_external.string().describe("New name for the symbol")
20806
- };
20807
- var symbolsArgs = {
20808
- file: exports_external.string().describe("Absolute path to the file"),
20809
- query: exports_external.string().optional().describe("Optional filter query for symbol names")
20810
- };
20811
- var updateDocumentArgs = {
20812
- file: exports_external.string().describe("Absolute path to the file"),
20813
- content: exports_external.string().describe("New content for the file")
20814
- };
20815
- var completionsArgs = {
20816
- ...positionArgs,
20817
- limit: exports_external.number().int().positive().default(20).describe("Maximum number of completions to return")
20818
- };
20819
-
20820
20745
  // src/tools/meta.ts
20821
20746
  import { readFileSync } from "fs";
20822
20747
  import { dirname, join } from "path";
@@ -20852,8 +20777,9 @@ async function status(backendManager, config2) {
20852
20777
  status: v.status
20853
20778
  })),
20854
20779
  usage: {
20855
- namespaced: "Use python/hover or typescript/hover to specify language",
20856
- auto_infer: "Or provide a file path and language will be inferred from extension"
20780
+ list: "Use list_backends to see available backends",
20781
+ start: "Use start_backend to install and start a backend",
20782
+ tools: "Once started, tools are available as python_hover, typescript_definition, etc."
20857
20783
  }
20858
20784
  };
20859
20785
  return {
@@ -20921,6 +20847,99 @@ function switchPythonBackend(provider) {
20921
20847
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
20922
20848
  };
20923
20849
  }
20850
+ async function listBackends(backendManager, config2) {
20851
+ const backendStatus = backendManager.getStatus();
20852
+ const backends = [
20853
+ {
20854
+ name: "python",
20855
+ enabled: config2.python.enabled,
20856
+ provider: config2.python.provider,
20857
+ status: backendStatus.python?.status || "not_started",
20858
+ tools: backendStatus.python?.tools || 0,
20859
+ description: "Python code intelligence (hover, definition, references, refactoring)",
20860
+ startCommand: "Use start_backend tool with language='python'"
20861
+ },
20862
+ {
20863
+ name: "typescript",
20864
+ enabled: config2.typescript.enabled,
20865
+ status: backendStatus.typescript?.status || "not_started",
20866
+ tools: backendStatus.typescript?.tools || 0,
20867
+ description: "TypeScript/JavaScript code intelligence",
20868
+ startCommand: "Use start_backend tool with language='typescript'"
20869
+ }
20870
+ ];
20871
+ const result = {
20872
+ backends,
20873
+ usage: {
20874
+ start: "Call start_backend with language='python' or 'typescript' to install and start a backend",
20875
+ tools: "Once started, backend tools will be available as {language}_{tool} (e.g., python_hover)"
20876
+ }
20877
+ };
20878
+ return {
20879
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
20880
+ };
20881
+ }
20882
+ var startBackendSchema = {
20883
+ language: exports_external.enum(["python", "typescript"]).describe("The backend to start")
20884
+ };
20885
+ async function startBackend(language, backendManager, config2, registerToolsCallback) {
20886
+ if (language === "python" && !config2.python.enabled) {
20887
+ return {
20888
+ content: [{
20889
+ type: "text",
20890
+ text: JSON.stringify({
20891
+ success: false,
20892
+ error: "Python backend is disabled",
20893
+ hint: "Set LSP_MCP_PYTHON_ENABLED=true to enable"
20894
+ }, null, 2)
20895
+ }]
20896
+ };
20897
+ }
20898
+ if (language === "typescript" && !config2.typescript.enabled) {
20899
+ return {
20900
+ content: [{
20901
+ type: "text",
20902
+ text: JSON.stringify({
20903
+ success: false,
20904
+ error: "TypeScript backend is disabled",
20905
+ hint: "Set LSP_MCP_TYPESCRIPT_ENABLED=true to enable"
20906
+ }, null, 2)
20907
+ }]
20908
+ };
20909
+ }
20910
+ try {
20911
+ const toolCount = await registerToolsCallback(language);
20912
+ const backendStatus = backendManager.getStatus();
20913
+ const status2 = backendStatus[language];
20914
+ return {
20915
+ content: [{
20916
+ type: "text",
20917
+ text: JSON.stringify({
20918
+ success: true,
20919
+ language,
20920
+ status: status2?.status,
20921
+ serverName: status2?.serverName,
20922
+ version: status2?.version,
20923
+ toolsRegistered: toolCount,
20924
+ message: `${language} backend started successfully. ${toolCount} tools are now available.`,
20925
+ usage: `Tools are available as ${language}_hover, ${language}_definition, etc.`
20926
+ }, null, 2)
20927
+ }]
20928
+ };
20929
+ } catch (error2) {
20930
+ return {
20931
+ content: [{
20932
+ type: "text",
20933
+ text: JSON.stringify({
20934
+ success: false,
20935
+ language,
20936
+ error: String(error2),
20937
+ hint: "Check if the backend package is available and network connection is working"
20938
+ }, null, 2)
20939
+ }]
20940
+ };
20941
+ }
20942
+ }
20924
20943
 
20925
20944
  // src/prompts.ts
20926
20945
  var skillsContent = {
@@ -21419,151 +21438,121 @@ Or use file extension auto-detection by providing a file path.
21419
21438
  }
21420
21439
 
21421
21440
  // src/index.ts
21441
+ var require2 = createRequire2(import.meta.url);
21442
+ var packageJson = require2("../package.json");
21422
21443
  var config2 = loadConfig();
21423
21444
  var backendManager = new BackendManager(config2);
21445
+ var startedBackends = new Set;
21424
21446
  var server = new McpServer({
21425
21447
  name: "lsp-mcp",
21426
- version: "0.1.0"
21448
+ version: packageJson.version
21427
21449
  });
21428
21450
  registerPrompts(server);
21451
+ function jsonSchemaToZod(schema) {
21452
+ const result = {};
21453
+ if (!schema || !schema.properties) {
21454
+ return result;
21455
+ }
21456
+ const required2 = new Set(schema.required || []);
21457
+ for (const [key, prop] of Object.entries(schema.properties)) {
21458
+ let zodType;
21459
+ switch (prop.type) {
21460
+ case "string":
21461
+ zodType = exports_external.string();
21462
+ if (prop.enum) {
21463
+ zodType = exports_external.enum(prop.enum);
21464
+ }
21465
+ break;
21466
+ case "number":
21467
+ case "integer":
21468
+ zodType = exports_external.number();
21469
+ if (prop.type === "integer") {
21470
+ zodType = zodType.int();
21471
+ }
21472
+ if (prop.exclusiveMinimum !== undefined) {
21473
+ zodType = zodType.gt(prop.exclusiveMinimum);
21474
+ }
21475
+ if (prop.minimum !== undefined) {
21476
+ zodType = zodType.gte(prop.minimum);
21477
+ }
21478
+ if (prop.maximum !== undefined) {
21479
+ zodType = zodType.lte(prop.maximum);
21480
+ }
21481
+ break;
21482
+ case "boolean":
21483
+ zodType = exports_external.boolean();
21484
+ break;
21485
+ case "array":
21486
+ if (prop.items?.type === "string") {
21487
+ zodType = exports_external.array(exports_external.string());
21488
+ } else {
21489
+ zodType = exports_external.array(exports_external.any());
21490
+ }
21491
+ break;
21492
+ case "object":
21493
+ zodType = exports_external.record(exports_external.any());
21494
+ break;
21495
+ default:
21496
+ zodType = exports_external.any();
21497
+ }
21498
+ if (prop.description) {
21499
+ zodType = zodType.describe(prop.description);
21500
+ }
21501
+ if (prop.default !== undefined) {
21502
+ zodType = zodType.default(prop.default);
21503
+ }
21504
+ if (!required2.has(key)) {
21505
+ zodType = zodType.optional();
21506
+ }
21507
+ result[key] = zodType;
21508
+ }
21509
+ return result;
21510
+ }
21511
+ function registerBackendTools(language, tools) {
21512
+ let count = 0;
21513
+ for (const tool of tools) {
21514
+ const namespacedName = `${language}_${tool.name}`;
21515
+ const zodSchema = jsonSchemaToZod(tool.inputSchema);
21516
+ server.registerTool(namespacedName, {
21517
+ description: tool.description || `${language} ${tool.name} tool`,
21518
+ inputSchema: zodSchema
21519
+ }, async (args) => backendManager.callTool(language, tool.name, args));
21520
+ console.error(`[lsp-mcp] Registered ${namespacedName}`);
21521
+ count++;
21522
+ }
21523
+ return count;
21524
+ }
21525
+ async function startAndRegisterBackend(language) {
21526
+ if (startedBackends.has(language)) {
21527
+ const status2 = backendManager.getStatus()[language];
21528
+ console.error(`[lsp-mcp] ${language} backend already started (${status2?.tools} tools)`);
21529
+ return status2?.tools || 0;
21530
+ }
21531
+ console.error(`[lsp-mcp] Starting ${language} backend...`);
21532
+ try {
21533
+ const tools = await backendManager.getTools(language);
21534
+ const count = registerBackendTools(language, tools);
21535
+ startedBackends.add(language);
21536
+ console.error(`[lsp-mcp] ${language}: ${count} tools registered`);
21537
+ return count;
21538
+ } catch (error2) {
21539
+ console.error(`[lsp-mcp] Failed to start ${language} backend:`, error2);
21540
+ throw error2;
21541
+ }
21542
+ }
21429
21543
  server.registerTool("status", { description: "Get status of all LSP backends and server configuration" }, async () => status(backendManager, config2));
21430
21544
  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));
21431
21545
  server.registerTool("switch_python_backend", {
21432
21546
  description: "Switch the Python backend provider (requires restart)",
21433
21547
  inputSchema: switchPythonBackendSchema
21434
21548
  }, async ({ provider }) => switchPythonBackend(provider));
21435
- if (config2.python.enabled) {
21436
- const backendOption = exports_external.enum(["rope", "pyright"]).optional().describe("Backend to use (rope/pyright)");
21437
- server.registerTool("python/hover", {
21438
- description: pythonToolDescriptions.hover,
21439
- inputSchema: { ...positionArgs, backend: backendOption }
21440
- }, async (args) => backendManager.callTool("python", "hover", args));
21441
- server.registerTool("python/definition", {
21442
- description: pythonToolDescriptions.definition,
21443
- inputSchema: { ...positionArgs, backend: backendOption }
21444
- }, async (args) => backendManager.callTool("python", "definition", args));
21445
- server.registerTool("python/references", {
21446
- description: pythonToolDescriptions.references,
21447
- inputSchema: { ...positionArgs, backend: backendOption }
21448
- }, async (args) => backendManager.callTool("python", "references", args));
21449
- server.registerTool("python/completions", {
21450
- description: pythonToolDescriptions.completions,
21451
- inputSchema: { ...completionsArgs, backend: backendOption }
21452
- }, async (args) => backendManager.callTool("python", "completions", args));
21453
- server.registerTool("python/diagnostics", {
21454
- description: pythonToolDescriptions.diagnostics,
21455
- inputSchema: diagnosticsArgs
21456
- }, async (args) => backendManager.callTool("python", "diagnostics", args));
21457
- server.registerTool("python/symbols", {
21458
- description: pythonToolDescriptions.symbols,
21459
- inputSchema: { ...symbolsArgs, backend: backendOption }
21460
- }, async (args) => backendManager.callTool("python", "symbols", args));
21461
- server.registerTool("python/rename", {
21462
- description: pythonToolDescriptions.rename,
21463
- inputSchema: { ...positionArgs, new_name: exports_external.string().describe("New name for the symbol") }
21464
- }, async (args) => backendManager.callTool("python", "rename", args));
21465
- server.registerTool("python/search", {
21466
- description: pythonToolDescriptions.search,
21467
- inputSchema: searchArgs
21468
- }, async (args) => backendManager.callTool("python", "search", args));
21469
- server.registerTool("python/signature_help", {
21470
- description: pythonToolDescriptions.signature_help,
21471
- inputSchema: positionArgs
21472
- }, async (args) => backendManager.callTool("python", "signature_help", args));
21473
- server.registerTool("python/update_document", {
21474
- description: pythonToolDescriptions.update_document,
21475
- inputSchema: updateDocumentArgs
21476
- }, async (args) => backendManager.callTool("python", "update_document", args));
21477
- server.registerTool("python/status", {
21478
- description: pythonToolDescriptions.status
21479
- }, async () => backendManager.callTool("python", "status", {}));
21480
- server.registerTool("python/move", {
21481
- description: pythonToolDescriptions.move,
21482
- inputSchema: {
21483
- ...positionArgs,
21484
- destination: exports_external.string().describe('Destination module path (e.g., "mypackage.utils")'),
21485
- preview: exports_external.boolean().default(false).describe("If true, only show what would change")
21486
- }
21487
- }, async (args) => backendManager.callTool("python", "move", args));
21488
- server.registerTool("python/change_signature", {
21489
- description: pythonToolDescriptions.change_signature,
21490
- inputSchema: {
21491
- ...positionArgs,
21492
- new_params: exports_external.array(exports_external.string()).optional().describe("New parameter order"),
21493
- add_param: exports_external.string().optional().describe("Name of parameter to add"),
21494
- add_param_default: exports_external.string().optional().describe("Default value for added parameter"),
21495
- add_param_index: exports_external.number().int().optional().describe("Index where to insert new param"),
21496
- remove_param: exports_external.string().optional().describe("Name of parameter to remove"),
21497
- preview: exports_external.boolean().default(false).describe("If true, only show what would change")
21498
- }
21499
- }, async (args) => backendManager.callTool("python", "change_signature", args));
21500
- server.registerTool("python/function_signature", {
21501
- description: pythonToolDescriptions.function_signature,
21502
- inputSchema: positionArgs
21503
- }, async (args) => backendManager.callTool("python", "function_signature", args));
21504
- server.registerTool("python/set_backend", {
21505
- description: pythonToolDescriptions.set_backend,
21506
- inputSchema: {
21507
- backend: exports_external.enum(["rope", "pyright"]).describe("The backend to use"),
21508
- tool: exports_external.string().optional().describe("Optional tool name to set backend for")
21509
- }
21510
- }, async (args) => backendManager.callTool("python", "set_backend", args));
21511
- server.registerTool("python/set_python_path", {
21512
- description: pythonToolDescriptions.set_python_path,
21513
- inputSchema: {
21514
- python_path: exports_external.string().describe("Absolute path to the Python interpreter"),
21515
- workspace: exports_external.string().optional().describe("Optional workspace to set the path for")
21516
- }
21517
- }, async (args) => backendManager.callTool("python", "set_python_path", args));
21518
- }
21519
- if (config2.typescript.enabled) {
21520
- server.registerTool("typescript/hover", {
21521
- description: typescriptToolDescriptions.hover,
21522
- inputSchema: positionArgs
21523
- }, async (args) => backendManager.callTool("typescript", "hover", args));
21524
- server.registerTool("typescript/definition", {
21525
- description: typescriptToolDescriptions.definition,
21526
- inputSchema: positionArgs
21527
- }, async (args) => backendManager.callTool("typescript", "definition", args));
21528
- server.registerTool("typescript/references", {
21529
- description: typescriptToolDescriptions.references,
21530
- inputSchema: positionArgs
21531
- }, async (args) => backendManager.callTool("typescript", "references", args));
21532
- server.registerTool("typescript/completions", {
21533
- description: typescriptToolDescriptions.completions,
21534
- inputSchema: completionsArgs
21535
- }, async (args) => backendManager.callTool("typescript", "completions", args));
21536
- server.registerTool("typescript/diagnostics", {
21537
- description: typescriptToolDescriptions.diagnostics,
21538
- inputSchema: diagnosticsArgs
21539
- }, async (args) => backendManager.callTool("typescript", "diagnostics", args));
21540
- server.registerTool("typescript/symbols", {
21541
- description: typescriptToolDescriptions.symbols,
21542
- inputSchema: symbolsArgs
21543
- }, async (args) => backendManager.callTool("typescript", "symbols", args));
21544
- server.registerTool("typescript/rename", {
21545
- description: typescriptToolDescriptions.rename,
21546
- inputSchema: renameArgs
21547
- }, async (args) => backendManager.callTool("typescript", "rename", args));
21548
- server.registerTool("typescript/search", {
21549
- description: typescriptToolDescriptions.search,
21550
- inputSchema: searchArgs
21551
- }, async (args) => backendManager.callTool("typescript", "search", args));
21552
- server.registerTool("typescript/signature_help", {
21553
- description: typescriptToolDescriptions.signature_help,
21554
- inputSchema: positionArgs
21555
- }, async (args) => backendManager.callTool("typescript", "signature_help", args));
21556
- server.registerTool("typescript/update_document", {
21557
- description: typescriptToolDescriptions.update_document,
21558
- inputSchema: updateDocumentArgs
21559
- }, async (args) => backendManager.callTool("typescript", "update_document", args));
21560
- server.registerTool("typescript/status", {
21561
- description: typescriptToolDescriptions.status,
21562
- inputSchema: {
21563
- file: exports_external.string().describe("A TypeScript/JavaScript file to check project status for")
21564
- }
21565
- }, async (args) => backendManager.callTool("typescript", "status", args));
21566
- }
21549
+ server.registerTool("list_backends", {
21550
+ description: "List available backends and their status. Shows which backends are installed, running, and how many tools they provide."
21551
+ }, async () => listBackends(backendManager, config2));
21552
+ server.registerTool("start_backend", {
21553
+ description: "Start a backend and register its tools. This will download and install the backend if needed, then make its tools available.",
21554
+ inputSchema: startBackendSchema
21555
+ }, async ({ language }) => startBackend(language, backendManager, config2, startAndRegisterBackend));
21567
21556
  async function gracefulShutdown(signal) {
21568
21557
  console.error(`
21569
21558
  [lsp-mcp] Received ${signal}, shutting down gracefully...`);
@@ -21581,12 +21570,15 @@ process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
21581
21570
  process.on("SIGINT", () => gracefulShutdown("SIGINT"));
21582
21571
  async function main() {
21583
21572
  console.error("LSP MCP Server - Unified Multi-Language Code Intelligence");
21573
+ console.error(` Version: ${packageJson.version}`);
21584
21574
  console.error(" Python:", config2.python.enabled ? `enabled (${config2.python.provider})` : "disabled");
21585
21575
  console.error(" TypeScript:", config2.typescript.enabled ? "enabled" : "disabled");
21586
21576
  console.error("");
21587
- console.error("Tools are namespaced: python/hover, typescript/definition, etc.");
21577
+ console.error("Backends are loaded on-demand. Use these tools to get started:");
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("");
21588
21581
  console.error("Prompts available: code-navigation, refactoring, code-analysis, lsp-rules, lsp-quick-start");
21589
- console.error("Backends start lazily on first tool call.");
21590
21582
  console.error("");
21591
21583
  const transport = new StdioServerTransport;
21592
21584
  await server.connect(transport);
@@ -21597,4 +21589,4 @@ main().catch((error2) => {
21597
21589
  process.exit(1);
21598
21590
  });
21599
21591
 
21600
- //# debugId=4B43BCFD3247DF0564756E2164756E21
21592
+ //# debugId=A15518B7EDCDD67064756E2164756E21