@theupsider/lsp-mcp 0.1.1 → 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.
@@ -54,6 +54,7 @@ function registerReadTools(registrar, lifecycleManager, options) {
54
54
  });
55
55
  registrar.registerTool('lsp_workspace_symbols', { description: 'Search workspace symbols', inputSchema: zod_1.z.object({ query: zod_1.z.string().default('') }) }, async (args) => {
56
56
  const query = typeof args.query === 'string' ? args.query : '';
57
+ await lifecycleManager.ensureSeedFilesOpen();
57
58
  const results = await Promise.all(lifecycleManager.getReadyClients().map(async (client) => {
58
59
  return await client.request('workspace/symbol', { query }, 30000);
59
60
  }));
@@ -70,14 +71,24 @@ function registerReadTools(registrar, lifecycleManager, options) {
70
71
  raw: (result) => asCompletionItems(result)?.slice(0, 50) ?? null
71
72
  });
72
73
  });
73
- registrar.registerTool('lsp_diagnostics', { description: 'Show diagnostics', inputSchema: zod_1.z.object({ file: zod_1.z.string().optional(), scope: zod_1.z.enum(['file', 'workspace']).default('file'), language: zod_1.z.string().optional() }) }, async (args) => {
74
+ registrar.registerTool('lsp_diagnostics', { description: 'Get errors and warnings. Pass a file path to trigger analysis of that file and its language server, then return diagnostics for that file (scope: file) or all files seen so far (scope: workspace). Omit file for workspace scope to query whatever has been opened previously.', inputSchema: zod_1.z.object({ file: zod_1.z.string().optional(), scope: zod_1.z.enum(['file', 'workspace']).default('file'), language: zod_1.z.string().optional() }) }, async (args) => {
75
+ const filePath = typeof args.file === 'string' ? args.file : '';
74
76
  const scope = args.scope === 'workspace' ? 'workspace' : 'file';
77
+ if (filePath) {
78
+ await lifecycleManager.ensureLanguageForFile(filePath);
79
+ const client = lifecycleManager.getClientForFile(filePath);
80
+ if (client) {
81
+ const waitPromise = client.waitForDiagnosticsPublish(filePath, 10000);
82
+ await client.ensureDidOpen(filePath);
83
+ client.notify('textDocument/didSave', { textDocument: { uri: (0, uri_1.pathToUri)(filePath) } });
84
+ await waitPromise;
85
+ }
86
+ }
75
87
  if (scope === 'workspace') {
76
88
  const language = typeof args.language === 'string' ? args.language : undefined;
77
89
  const diagnostics = lifecycleManager.getWorkspaceDiagnostics(language).slice(0, 200);
78
90
  return (0, shared_1.success)((0, formatters_1.formatDiagnostics)(diagnostics, 'workspace'), diagnostics);
79
91
  }
80
- const filePath = typeof args.file === 'string' ? args.file : '';
81
92
  const diagnostics = lifecycleManager.getFileDiagnostics(filePath);
82
93
  return (0, shared_1.success)((0, formatters_1.formatDiagnostics)(diagnostics, 'file'), diagnostics);
83
94
  });
@@ -168,7 +179,7 @@ async function runFileRequest(options) {
168
179
  };
169
180
  const uri = (0, uri_1.pathToUri)(filePath);
170
181
  try {
171
- await (0, shared_1.ensureDidOpen)(client, filePath);
182
+ await client.ensureDidOpen(filePath);
172
183
  const result = await client.request(options.method, options.params?.(uri, position) ?? {
173
184
  textDocument: { uri },
174
185
  position
@@ -5,41 +5,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.success = success;
7
7
  exports.failure = failure;
8
- exports.ensureDidOpen = ensureDidOpen;
9
- exports.clearOpenedFiles = clearOpenedFiles;
10
8
  exports.noServerResult = noServerResult;
11
9
  exports.noProjectRootResult = noProjectRootResult;
12
10
  exports.mapToolError = mapToolError;
13
11
  exports.normalizeLocations = normalizeLocations;
14
12
  exports.normalizeSymbols = normalizeSymbols;
15
- const promises_1 = require("node:fs/promises");
16
13
  const node_path_1 = __importDefault(require("node:path"));
17
14
  const uri_1 = require("../../utils/uri");
18
- const openedFiles = new Set();
19
15
  function success(text, raw) {
20
16
  return { content: [{ type: 'text', text }], raw };
21
17
  }
22
18
  function failure(text, raw = null) {
23
19
  return { content: [{ type: 'text', text }], error: true, raw };
24
20
  }
25
- async function ensureDidOpen(client, filePath) {
26
- if (openedFiles.has(filePath)) {
27
- return;
28
- }
29
- const text = await (0, promises_1.readFile)(filePath, 'utf8');
30
- client.notify('textDocument/didOpen', {
31
- textDocument: {
32
- uri: (0, uri_1.pathToUri)(filePath),
33
- languageId: languageIdForFile(filePath),
34
- version: 1,
35
- text
36
- }
37
- });
38
- openedFiles.add(filePath);
39
- }
40
- function clearOpenedFiles() {
41
- openedFiles.clear();
42
- }
43
21
  function noServerResult(filePath) {
44
22
  return failure(`No language server available for ${node_path_1.default.extname(filePath) || 'unknown'} files. Run lsp_health for details.`);
45
23
  }
@@ -82,25 +60,3 @@ function normalizeSymbols(symbols) {
82
60
  }
83
61
  return normalized;
84
62
  }
85
- function languageIdForFile(filePath) {
86
- const ext = node_path_1.default.extname(filePath).toLowerCase();
87
- const languageMap = {
88
- '.ts': 'typescript',
89
- '.tsx': 'typescriptreact',
90
- '.js': 'javascript',
91
- '.jsx': 'javascriptreact',
92
- '.py': 'python',
93
- '.go': 'go',
94
- '.rs': 'rust',
95
- '.java': 'java',
96
- '.cs': 'csharp',
97
- '.php': 'php',
98
- '.rb': 'ruby',
99
- '.kt': 'kotlin',
100
- '.swift': 'swift',
101
- '.c': 'c',
102
- '.cpp': 'cpp',
103
- '.h': 'c'
104
- };
105
- return languageMap[ext] ?? 'plaintext';
106
- }
@@ -21,7 +21,7 @@ function registerWriteTools(registrar, lifecycleManager) {
21
21
  return (0, shared_1.failure)('Rename is not supported by the active language server.');
22
22
  }
23
23
  try {
24
- await (0, shared_1.ensureDidOpen)(client, filePath);
24
+ await client.ensureDidOpen(filePath);
25
25
  const edit = await client.request('textDocument/rename', {
26
26
  textDocument: { uri: (0, uri_1.pathToUri)(filePath) },
27
27
  position: getPosition(args),
@@ -41,7 +41,7 @@ function registerWriteTools(registrar, lifecycleManager) {
41
41
  return (0, shared_1.noServerResult)(filePath);
42
42
  }
43
43
  try {
44
- await (0, shared_1.ensureDidOpen)(client, filePath);
44
+ await client.ensureDidOpen(filePath);
45
45
  const range = isRange(args.range)
46
46
  ? args.range
47
47
  : { start: getPosition(args), end: getPosition(args) };
@@ -108,7 +108,7 @@ async function runFormattingRequest(_method, args, lifecycleManager, requestEdit
108
108
  return (0, shared_1.noServerResult)(filePath);
109
109
  }
110
110
  try {
111
- await (0, shared_1.ensureDidOpen)(client, filePath);
111
+ await client.ensureDidOpen(filePath);
112
112
  const options = await resolveFormattingOptions(filePath, args.options);
113
113
  const edits = await requestEdits(client, filePath, options);
114
114
  return await applyTextEdits(edits, [filePath], lifecycleManager, client);
@@ -126,7 +126,7 @@ async function applyWorkspaceEdit(edit, lifecycleManager, fallbackClient, verb)
126
126
  for (const [uri, edits] of changeEntries) {
127
127
  const filePath = (0, uri_1.uriToPath)(uri);
128
128
  const client = lifecycleManager.getClientForFile(filePath) ?? fallbackClient;
129
- await (0, shared_1.ensureDidOpen)(client, filePath);
129
+ await client.ensureDidOpen(filePath);
130
130
  await applyEditsToFile(filePath, edits ?? []);
131
131
  client.notify('textDocument/didSave', { textDocument: { uri } });
132
132
  changedFiles.push(filePath);
@@ -135,7 +135,7 @@ async function applyWorkspaceEdit(edit, lifecycleManager, fallbackClient, verb)
135
135
  if ('textDocument' in change && 'edits' in change) {
136
136
  const filePath = (0, uri_1.uriToPath)(change.textDocument.uri);
137
137
  const client = lifecycleManager.getClientForFile(filePath) ?? fallbackClient;
138
- await (0, shared_1.ensureDidOpen)(client, filePath);
138
+ await client.ensureDidOpen(filePath);
139
139
  await applyEditsToFile(filePath, change.edits);
140
140
  client.notify('textDocument/didSave', { textDocument: { uri: change.textDocument.uri } });
141
141
  changedFiles.push(filePath);
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "@theupsider/lsp-mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "Universal LSP MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "commonjs",
7
+ "author": {
8
+ "name": "David Fischer",
9
+ "url": "https://davidfischer.dev"
10
+ },
7
11
  "main": "dist/index.js",
8
12
  "bin": {
9
13
  "lsp-mcp": "dist/index.js"
@@ -29,4 +33,4 @@
29
33
  "ts-jest": "latest",
30
34
  "typescript": "latest"
31
35
  }
32
- }
36
+ }