mcp-lsp-driver 0.1.0 → 1.0.1

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
@@ -6,8 +6,7 @@ A TypeScript SDK that bridges Language Server Protocol (LSP) capabilities with t
6
6
 
7
7
  - **Fuzzy-to-Exact Resolution**: LLMs interact via semantic anchors (`symbolName`, `lineHint`), and the SDK resolves them to precise coordinates
8
8
  - **Disk-Based Truth**: All read operations reflect the state of files on disk, ignoring unsaved IDE buffers
9
- - **Human-in-the-Loop Edits**: Write operations require explicit user approval before applying changes
10
- - **Type Safety**: Strict TypeScript with no `any` types
9
+ - **High Abstraction**: Beyond LSP, it also provides functionality related to something like dual chains (graph capability) and metadata (frontmatter capability).
11
10
 
12
11
  ## Installation
13
12
 
@@ -37,14 +36,22 @@ const fileAccess = {
37
36
  return await fs.readFile(uri, 'utf-8')
38
37
  },
39
38
 
40
- getFileTree: (uri: string) => yourIDE.workspace.files
39
+ getFileTree: (uri: string) => yourIDE.workspace.getFileTree(uri),
40
+
41
+ readDirectory: (uri: string) => yourIDE.workspace.readDirectory(uri)
41
42
  }
42
43
 
43
- // 3. Implement User Interaction (required for edits)
44
- const userInteraction = {
44
+ // 3. Implement Edit Provider (required for edits)
45
+ const edit = {
46
+ // Option 1: Preview and apply with user approval
45
47
  previewAndApplyEdits: async (operation) => {
46
48
  // Show diff in your IDE and get user approval
47
49
  return await showDiffDialog(operation)
50
+ },
51
+ // Option 2: Apply directly without preview (use one or both)
52
+ applyEdits: async (operation) => {
53
+ // Apply edits directly
54
+ return await yourIDE.applyEdits(operation)
48
55
  }
49
56
  }
50
57
 
@@ -77,7 +84,7 @@ const outline = {
77
84
  // 5. Register LSP tools and resources on the server
78
85
  const capabilities: IdeCapabilities = {
79
86
  fileAccess,
80
- userInteraction,
87
+ edit,
81
88
  definition,
82
89
  diagnostics,
83
90
  outline,
@@ -109,19 +116,25 @@ Provides disk access for reading files:
109
116
  interface FileAccessProvider {
110
117
  readFile(uri: UnifiedUri): Promise<string>
111
118
  getFileTree(folderPath: UnifiedUri): Promise<string[]>
119
+ readDirectory(folderPath: UnifiedUri): Promise<string[]>
112
120
  }
113
121
  ```
114
122
 
115
- #### `UserInteractionProvider` (Required for edits)
123
+ #### `EditProvider` (Required for edits)
116
124
 
117
- Handles user approval for edit operations:
125
+ Handles applying changes to files. At least one method must be implemented:
118
126
 
119
127
  ```typescript
120
- interface UserInteractionProvider {
121
- previewAndApplyEdits(operation: PendingEditOperation): Promise<boolean>
128
+ interface EditProvider {
129
+ // Apply edits directly without user interaction
130
+ applyEdits?(operation: PendingEditOperation): Promise<boolean>
131
+ // Preview edits and get user approval before applying
132
+ previewAndApplyEdits?(operation: PendingEditOperation): Promise<boolean>
122
133
  }
123
134
  ```
124
135
 
136
+ If both methods are provided, `previewAndApplyEdits` takes precedence.
137
+
125
138
  ### Capability Providers
126
139
 
127
140
  All capability providers receive `ExactPosition` coordinates (0-based). The SDK handles fuzzy-to-exact conversion before calling these.
@@ -192,6 +205,51 @@ Provides global find and replace functionality across the workspace. `GlobalFind
192
205
  - `matchText`: The matching text
193
206
  - `context`: Context around the match (e.g., the full line)
194
207
 
208
+ #### `GraphProvider`
209
+
210
+ ```typescript
211
+ interface GraphProvider {
212
+ getLinkStructure(): Promise<Link[]>
213
+ resolveOutlinks(path: UnifiedUri): Promise<Link[]>
214
+ resolveBacklinks(path: UnifiedUri): Promise<Link[]>
215
+ addLink(path: UnifiedUri, pattern: string, linkTo: UnifiedUri): Promise<boolean>
216
+ }
217
+ ```
218
+
219
+ Provides graph/link functionality for document relationships (e.g., wiki-style links, cross-references). `Link` includes:
220
+ - `sourceUri`: The source URI where the link originates
221
+ - `targetUri`: The target URI the link points to
222
+ - `subpath`: Optional subpath within the target (e.g., `#section` for Obsidian-style anchors)
223
+ - `displayText`: Optional display text of the link
224
+ - `resolved`: Whether the link target exists
225
+ - `line`: 1-based line number where the link appears
226
+ - `column`: 1-based column number where the link starts
227
+
228
+ #### `FrontmatterProvider`
229
+
230
+ ```typescript
231
+ interface FrontmatterProvider {
232
+ getFrontmatterStructure(property: string, path?: UnifiedUri): Promise<FrontmatterMatch[]>
233
+ getFrontmatter(path: UnifiedUri): Promise<Frontmatter>
234
+ setFrontmatter(path: UnifiedUri, property: string, value: FrontmatterValue): Promise<boolean>
235
+ }
236
+ ```
237
+
238
+ Provides frontmatter metadata functionality for documents (e.g., YAML frontmatter in Markdown files). Types:
239
+
240
+ ```typescript
241
+ type FrontmatterValue = string | string[] | number | number[] | boolean | boolean[] | Date | undefined
242
+ type Frontmatter = { [key: string]: FrontmatterValue }
243
+ interface FrontmatterMatch {
244
+ path: UnifiedUri
245
+ value: FrontmatterValue
246
+ }
247
+ ```
248
+
249
+ - `getFrontmatterStructure`: Searches for a specific property across documents. If `path` is provided, searches only that document.
250
+ - `getFrontmatter`: Gets all frontmatter for a specific document.
251
+ - `setFrontmatter`: Sets a frontmatter property. Use `undefined` to remove the property.
252
+
195
253
  ### IdeCapabilities
196
254
 
197
255
  Combine all providers into a single configuration:
@@ -199,13 +257,15 @@ Combine all providers into a single configuration:
199
257
  ```typescript
200
258
  interface IdeCapabilities {
201
259
  fileAccess: FileAccessProvider // Required
202
- userInteraction?: UserInteractionProvider // Required for apply_edit tool
260
+ edit?: EditProvider // Required for apply_edit tool
203
261
  definition?: DefinitionProvider // Enables goto_definition tool
204
262
  references?: ReferencesProvider // Enables find_references tool
205
263
  hierarchy?: HierarchyProvider // Enables call_hierarchy tool
206
264
  diagnostics?: DiagnosticsProvider // Enables diagnostics resources
207
265
  outline?: OutlineProvider // Enables outline resource
208
266
  globalFind?: GlobalFindProvider // Enables global_find and global_replace tools
267
+ graph?: GraphProvider // Enables graph tools and resources
268
+ frontmatter?: FrontmatterProvider // Enables frontmatter tools and resource
209
269
  onDiagnosticsChanged?: (callback: OnDiagnosticsChangedCallback) => void
210
270
  }
211
271
  ```
@@ -277,27 +337,71 @@ Replace all occurrences of text across the entire workspace.
277
337
  - Number of replacements made
278
338
  - Success status and message
279
339
 
340
+ ### `get_link_structure`
341
+
342
+ Get all links in the workspace, showing relationships between documents.
343
+
344
+ **Inputs:** None
345
+
346
+ **Returns:**
347
+ - Array of links with source URI, target URI, subpath, display text, resolved status, line, and column
348
+
349
+ ### `add_link`
350
+
351
+ Add a link to a document by finding a text pattern and replacing it with a link.
352
+
353
+ **Inputs:**
354
+ - `path`: The path to the document to modify
355
+ - `pattern`: The text pattern to find and replace with a link
356
+ - `link_to`: The target URI the link should point to
357
+
358
+ **Returns:**
359
+ - Success status and message
360
+
361
+ ### `get_frontmatter_structure`
362
+
363
+ Get frontmatter property values across documents.
364
+
365
+ **Inputs:**
366
+ - `property`: The frontmatter property name to search for (required)
367
+ - `path`: Optional path to limit the search to a specific document
368
+
369
+ **Returns:**
370
+ - Array of matches with path and value
371
+
372
+ ### `set_frontmatter`
373
+
374
+ Set a frontmatter property on a document.
375
+
376
+ **Inputs:**
377
+ - `path`: The path to the document to modify (required)
378
+ - `property`: The frontmatter property name to set (required)
379
+ - `value`: The value to set. Can be a string, number, boolean, array of these types, or null to remove the property.
380
+
381
+ **Returns:**
382
+ - Success status and message
383
+
280
384
  ## MCP Resources
281
385
 
282
386
  The SDK automatically registers resources based on which capabilities you provide:
283
387
 
284
- ### `lsp://diagnostics/{path}`
388
+ ### `diagnostics://{path}`
285
389
 
286
390
  Get diagnostics (errors, warnings) for a specific file.
287
391
 
288
- **Resource URI Pattern:** `lsp://diagnostics/{+path}`
392
+ **Resource URI Pattern:** `diagnostics://{+path}`
289
393
 
290
- **Example:** `lsp://diagnostics/src/main.ts`
394
+ **Example:** `diagnostics://src/main.ts`
291
395
 
292
396
  Returns diagnostics formatted as markdown with location, severity, and message information.
293
397
 
294
398
  **Subscription Support:** If your IDE implements `onDiagnosticsChanged` capability, these resources become subscribable. When diagnostics change, the driver sends resource update notifications.
295
399
 
296
- ### `lsp://diagnostics/workspace`
400
+ ### `diagnostics://workspace`
297
401
 
298
402
  Get diagnostics across the entire workspace.
299
403
 
300
- **Resource URI:** `lsp://diagnostics/workspace`
404
+ **Resource URI:** `diagnostics://workspace`
301
405
 
302
406
  Only available if your `DiagnosticsProvider` implements the optional `getWorkspaceDiagnostics()` method.
303
407
 
@@ -305,13 +409,13 @@ Returns workspace diagnostics grouped by file, formatted as markdown.
305
409
 
306
410
  **Subscription Support:** If your IDE implements `onDiagnosticsChanged` capability, this resource becomes subscribable.
307
411
 
308
- ### `lsp://outline/{path}`
412
+ ### `outline://{path}`
309
413
 
310
414
  Get the document outline (symbol tree) for a file.
311
415
 
312
- **Resource URI Pattern:** `lsp://outline/{+path}`
416
+ **Resource URI Pattern:** `outline://{+path}`
313
417
 
314
- **Example:** `lsp://outline/src/components/Button.tsx`
418
+ **Example:** `outline://src/components/Button.tsx`
315
419
 
316
420
  Returns document symbols formatted as a hierarchical markdown outline, including:
317
421
  - Symbol names and kinds (class, function, method, etc.)
@@ -320,13 +424,61 @@ Returns document symbols formatted as a hierarchical markdown outline, including
320
424
 
321
425
  No subscription support for this resource (read-only).
322
426
 
323
- ### `lsp://files/{path}`
427
+ ### `filetree://{path}`
428
+
429
+ Get the complete file tree for a directory, excluding git-ignored files.
430
+
431
+ **Resource URI Pattern:** `filetree://{+path}`
432
+
433
+ **Example:** `filetree://src`, `filetree://.`
434
+
435
+ Returns a JSON array of all file paths in the directory tree (recursive). Use "." for the root directory.
436
+
437
+ No subscription support for this resource (read-only).
438
+
439
+ ### `files://{path}`
440
+
441
+ For directories: returns directory children (git-ignored files excluded, similar to `ls`). For files: gets file content with optional line range.
442
+
443
+ **Resource URI Pattern:** `files://{+path}`
444
+
445
+ **Example:** `files://src`, `files://src/index.ts`, `files://src/index.ts#L1-L2`
446
+
447
+ No subscription support for this resource (read-only).
448
+
449
+ ### `outlinks://{path}`
450
+
451
+ Get outgoing links from a specific file.
452
+
453
+ **Resource URI Pattern:** `outlinks://{+path}`
454
+
455
+ **Example:** `outlinks://notes/index.md`
456
+
457
+ Returns a JSON array of links originating from the specified document.
458
+
459
+ No subscription support for this resource (read-only).
460
+
461
+ ### `backlinks://{path}`
324
462
 
325
- For directories: gets the file tree for a directory, excluding git-ignored files. For files: gets file content with optional line range.
463
+ Get incoming links (backlinks) to a specific file.
326
464
 
327
- **Resource URI Pattern:** `lsp://files/{+path}`
465
+ **Resource URI Pattern:** `backlinks://{+path}`
328
466
 
329
- **Example:** `lsp://files/src`, `lsp://files/src/index.ts`, `lsp://files/src/index.ts#L1-L2`
467
+ **Example:** `backlinks://notes/topic-a.md`
468
+
469
+ Returns a JSON array of links pointing to the specified document.
470
+
471
+ No subscription support for this resource (read-only).
472
+
473
+ ### `frontmatter://{path}`
474
+
475
+ Get frontmatter metadata for a specific file.
476
+
477
+ **Resource URI Pattern:** `frontmatter://{+path}`
478
+
479
+ **Example:** `frontmatter://notes/index.md`
480
+
481
+ Returns a JSON object containing all frontmatter properties and values for the document.
330
482
 
331
483
  No subscription support for this resource (read-only).
332
484
 
@@ -415,6 +567,16 @@ interface Diagnostic {
415
567
  code?: string | number
416
568
  }
417
569
 
570
+ interface Link {
571
+ sourceUri: UnifiedUri
572
+ targetUri: UnifiedUri
573
+ subpath?: string
574
+ displayText?: string
575
+ resolved: boolean
576
+ line: number
577
+ column: number
578
+ }
579
+
418
580
  type EditResult =
419
581
  | { success: true; message: string }
420
582
  | { success: false; message: string; reason: 'UserRejected' | 'IOError' | 'ValidationFailed' }