mcp-lsp-driver 0.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/LICENSE +21 -0
- package/README.md +468 -0
- package/dist/capabilities.d.ts +181 -0
- package/dist/capabilities.js +11 -0
- package/dist/formatting.d.ts +33 -0
- package/dist/formatting.js +67 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +13 -0
- package/dist/interfaces.d.ts +38 -0
- package/dist/interfaces.js +8 -0
- package/dist/resolver.d.ts +81 -0
- package/dist/resolver.js +171 -0
- package/dist/schemas.d.ts +41 -0
- package/dist/schemas.js +62 -0
- package/dist/server.d.ts +33 -0
- package/dist/server.js +557 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.js +8 -0
- package/package.json +52 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting utilities for converting LSP results to markdown.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
import type { Diagnostic, DocumentSymbol } from './types.js';
|
|
6
|
+
export declare const makeToolResult: <T extends {
|
|
7
|
+
[x: string]: unknown;
|
|
8
|
+
}>(result: T) => {
|
|
9
|
+
content: [{
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
}];
|
|
13
|
+
structuredContent: {
|
|
14
|
+
[x: string]: unknown;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Normalizes a URI to handle Windows/Unix path separator differences.
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeUri(uri: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Generates a unique ID for pending edit operations.
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateEditId(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Formats diagnostics as markdown for resource content.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatDiagnosticsAsMarkdown(diagnostics: Diagnostic[]): string;
|
|
29
|
+
/**
|
|
30
|
+
* Formats document symbols as markdown for resource content.
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatSymbolsAsMarkdown(symbols: DocumentSymbol[], indent?: number): string;
|
|
33
|
+
//# sourceMappingURL=formatting.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting utilities for converting LSP results to markdown.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
export const makeToolResult = (result) => ({
|
|
6
|
+
content: [{ type: 'text', text: JSON.stringify(result ?? '') }],
|
|
7
|
+
structuredContent: result,
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* Normalizes a URI to handle Windows/Unix path separator differences.
|
|
11
|
+
*/
|
|
12
|
+
export function normalizeUri(uri) {
|
|
13
|
+
// If it's already a file:// URI, leave it alone
|
|
14
|
+
if (uri.startsWith('file://')) {
|
|
15
|
+
return uri;
|
|
16
|
+
}
|
|
17
|
+
// Normalize backslashes to forward slashes for consistency
|
|
18
|
+
return uri.replace(/\\/g, '/');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Generates a unique ID for pending edit operations.
|
|
22
|
+
*/
|
|
23
|
+
export function generateEditId() {
|
|
24
|
+
return `edit-${Date.now()}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Formats diagnostics as markdown for resource content.
|
|
28
|
+
*/
|
|
29
|
+
export function formatDiagnosticsAsMarkdown(diagnostics) {
|
|
30
|
+
if (diagnostics.length === 0) {
|
|
31
|
+
return 'No diagnostics found.';
|
|
32
|
+
}
|
|
33
|
+
return diagnostics
|
|
34
|
+
.map((d) => {
|
|
35
|
+
const line = d.range.start.line + 1;
|
|
36
|
+
const severity = d.severity.toUpperCase();
|
|
37
|
+
const source = d.source ? ` [${d.source}]` : '';
|
|
38
|
+
const code = d.code !== undefined ? ` (${d.code})` : '';
|
|
39
|
+
return `- **${severity}**${source}${code} at line ${line}: ${d.message}`;
|
|
40
|
+
})
|
|
41
|
+
.join('\n');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Formats document symbols as markdown for resource content.
|
|
45
|
+
*/
|
|
46
|
+
export function formatSymbolsAsMarkdown(symbols, indent = 0) {
|
|
47
|
+
if (symbols.length === 0 && indent === 0) {
|
|
48
|
+
return 'No symbols found.';
|
|
49
|
+
}
|
|
50
|
+
const prefix = ' '.repeat(indent);
|
|
51
|
+
return symbols
|
|
52
|
+
.map((s) => {
|
|
53
|
+
const startLine = s.range.start.line + 1;
|
|
54
|
+
const endLine = s.range.end.line + 1;
|
|
55
|
+
const range = startLine === endLine
|
|
56
|
+
? `line ${startLine}`
|
|
57
|
+
: `lines ${startLine}-${endLine}`;
|
|
58
|
+
const detail = s.detail ? ` - ${s.detail}` : '';
|
|
59
|
+
const line = `${prefix}- **${s.kind}** \`${s.name}\`${detail} (${range})`;
|
|
60
|
+
if (s.children && s.children.length > 0) {
|
|
61
|
+
return `${line}\n${formatSymbolsAsMarkdown(s.children, indent + 1)}`;
|
|
62
|
+
}
|
|
63
|
+
return line;
|
|
64
|
+
})
|
|
65
|
+
.join('\n');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=formatting.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP LSP Driver SDK
|
|
3
|
+
*
|
|
4
|
+
* A TypeScript SDK for building IDE plugins that expose LSP features
|
|
5
|
+
* through the Model Context Protocol (MCP).
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export type { DefinitionProvider, DiagnosticsProvider, FilesystemProvider, GlobalFindMatch, GlobalFindOptions, GlobalFindProvider, HierarchyProvider, IdeCapabilities, OnDiagnosticsChangedCallback, OutlineProvider, ReferencesProvider, } from './capabilities.js';
|
|
10
|
+
export type { FileAccessProvider, UserInteractionProvider, } from './interfaces.js';
|
|
11
|
+
export type { ResolverConfig } from './resolver.js';
|
|
12
|
+
export { SymbolResolutionError, SymbolResolver } from './resolver.js';
|
|
13
|
+
export type { McpLspDriverConfig } from './server.js';
|
|
14
|
+
export { installMcpLspDriver } from './server.js';
|
|
15
|
+
export type { CodeSnippet, Diagnostic, DiagnosticSeverity, DiskRange, DocumentSymbol, EditFailureReason, EditResult, ExactPosition, FuzzyPosition, PendingEditOperation, SymbolKind, TextEdit, UnifiedUri, } from './types.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP LSP Driver SDK
|
|
3
|
+
*
|
|
4
|
+
* A TypeScript SDK for building IDE plugins that expose LSP features
|
|
5
|
+
* through the Model Context Protocol (MCP).
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
// Symbol Resolver
|
|
10
|
+
export { SymbolResolutionError, SymbolResolver } from './resolver.js';
|
|
11
|
+
// Driver
|
|
12
|
+
export { installMcpLspDriver } from './server.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure Interfaces for MCP LSP Driver SDK
|
|
3
|
+
*
|
|
4
|
+
* The SDK consumer (Plugin Developer) must implement these interfaces
|
|
5
|
+
* to bridge the SDK to the specific IDE.
|
|
6
|
+
*/
|
|
7
|
+
import type { PendingEditOperation, UnifiedUri } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Provides access to the file system for reading files.
|
|
10
|
+
* Since the SDK is responsible for resolving FuzzyPosition to ExactPosition,
|
|
11
|
+
* it needs direct access to read files from the disk.
|
|
12
|
+
*/
|
|
13
|
+
export interface FileAccessProvider {
|
|
14
|
+
/**
|
|
15
|
+
* Reads the content of a file from the disk (ignoring unsaved IDE buffers).
|
|
16
|
+
* Used for symbol resolution and context retrieval.
|
|
17
|
+
*
|
|
18
|
+
* @param uri - The URI of the file to read
|
|
19
|
+
* @returns The content of the file as a string
|
|
20
|
+
* @throws Error if the file cannot be read
|
|
21
|
+
*/
|
|
22
|
+
readFile(uri: UnifiedUri): Promise<string>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Provides user interaction capabilities for edit operations.
|
|
26
|
+
* The SDK uses this to present diffs and get user approval before applying changes.
|
|
27
|
+
*/
|
|
28
|
+
export interface UserInteractionProvider {
|
|
29
|
+
/**
|
|
30
|
+
* Displays a diff view or a confirmation dialog in the IDE.
|
|
31
|
+
* The user decides whether to apply the edits or discard them.
|
|
32
|
+
*
|
|
33
|
+
* @param operation - The pending edit operation to preview
|
|
34
|
+
* @returns true if applied, false if rejected/cancelled
|
|
35
|
+
*/
|
|
36
|
+
previewAndApplyEdits(operation: PendingEditOperation): Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Resolver Logic for MCP LSP Driver SDK
|
|
3
|
+
*
|
|
4
|
+
* This is the internal engine of the SDK. It translates the LLM's imprecise
|
|
5
|
+
* instructions into precise coordinates.
|
|
6
|
+
*/
|
|
7
|
+
import type { FileAccessProvider } from './interfaces.js';
|
|
8
|
+
import type { DiskRange, ExactPosition, FuzzyPosition, UnifiedUri } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Configuration options for the SymbolResolver.
|
|
11
|
+
*/
|
|
12
|
+
export interface ResolverConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Number of lines to scan above and below the lineHint if the symbol
|
|
15
|
+
* is not found at the exact line. Defaults to 2.
|
|
16
|
+
*/
|
|
17
|
+
lineSearchRadius?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when a symbol cannot be resolved.
|
|
21
|
+
*/
|
|
22
|
+
export declare class SymbolResolutionError extends Error {
|
|
23
|
+
readonly symbolName: string;
|
|
24
|
+
readonly lineHint: number;
|
|
25
|
+
readonly reason: string;
|
|
26
|
+
constructor(symbolName: string, lineHint: number, reason: string);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The SymbolResolver translates fuzzy positions (as provided by an LLM)
|
|
30
|
+
* into exact positions that can be used by the IDE.
|
|
31
|
+
*
|
|
32
|
+
* Algorithm:
|
|
33
|
+
* 1. Read file content via FileAccessProvider.
|
|
34
|
+
* 2. Split content into lines.
|
|
35
|
+
* 3. Target the lineHint (converting 1-based to 0-based).
|
|
36
|
+
* 4. Search for symbolName in that line.
|
|
37
|
+
* - If orderHint is 0, find first occurrence.
|
|
38
|
+
* - If orderHint is N, find Nth occurrence.
|
|
39
|
+
* 5. Robustness Fallback:
|
|
40
|
+
* - If the line is empty or symbol not found at lineHint,
|
|
41
|
+
* scan +/- lineSearchRadius lines to handle minor line shifts.
|
|
42
|
+
* 6. Return ExactPosition (line, character start index).
|
|
43
|
+
*/
|
|
44
|
+
export declare class SymbolResolver {
|
|
45
|
+
private readonly fs;
|
|
46
|
+
private readonly lineSearchRadius;
|
|
47
|
+
constructor(fs: FileAccessProvider, config?: ResolverConfig);
|
|
48
|
+
/**
|
|
49
|
+
* Resolves a fuzzy position to an exact position.
|
|
50
|
+
*
|
|
51
|
+
* @param uri - The URI of the file
|
|
52
|
+
* @param fuzzy - The fuzzy position provided by the LLM
|
|
53
|
+
* @returns The exact position in the file
|
|
54
|
+
* @throws SymbolResolutionError if the symbol cannot be found
|
|
55
|
+
*/
|
|
56
|
+
resolvePosition(uri: UnifiedUri, fuzzy: FuzzyPosition): Promise<ExactPosition>;
|
|
57
|
+
/**
|
|
58
|
+
* Finds the Nth occurrence of a symbol in a line.
|
|
59
|
+
*
|
|
60
|
+
* @param line - The line to search in (may be undefined if out of bounds)
|
|
61
|
+
* @param symbolName - The symbol to find
|
|
62
|
+
* @param orderHint - Which occurrence to find (0-based)
|
|
63
|
+
* @returns The character offset of the symbol, or null if not found
|
|
64
|
+
*/
|
|
65
|
+
private findSymbolInLine;
|
|
66
|
+
/**
|
|
67
|
+
* Finds exact text in a file and returns its range.
|
|
68
|
+
* Used for search-and-replace operations.
|
|
69
|
+
*
|
|
70
|
+
* @param uri - The URI of the file
|
|
71
|
+
* @param searchText - The exact text to find
|
|
72
|
+
* @returns The range of the found text
|
|
73
|
+
* @throws Error if the text is not found or appears multiple times
|
|
74
|
+
*/
|
|
75
|
+
findExactText(uri: UnifiedUri, searchText: string): Promise<DiskRange>;
|
|
76
|
+
/**
|
|
77
|
+
* Converts a character offset to a line/character position.
|
|
78
|
+
*/
|
|
79
|
+
private offsetToPosition;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=resolver.d.ts.map
|
package/dist/resolver.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Resolver Logic for MCP LSP Driver SDK
|
|
3
|
+
*
|
|
4
|
+
* This is the internal engine of the SDK. It translates the LLM's imprecise
|
|
5
|
+
* instructions into precise coordinates.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Error thrown when a symbol cannot be resolved.
|
|
9
|
+
*/
|
|
10
|
+
export class SymbolResolutionError extends Error {
|
|
11
|
+
symbolName;
|
|
12
|
+
lineHint;
|
|
13
|
+
reason;
|
|
14
|
+
constructor(symbolName, lineHint, reason) {
|
|
15
|
+
super(`Could not find symbol '${symbolName}' at or near line ${lineHint}. ${reason}`);
|
|
16
|
+
this.symbolName = symbolName;
|
|
17
|
+
this.lineHint = lineHint;
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
this.name = 'SymbolResolutionError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The SymbolResolver translates fuzzy positions (as provided by an LLM)
|
|
24
|
+
* into exact positions that can be used by the IDE.
|
|
25
|
+
*
|
|
26
|
+
* Algorithm:
|
|
27
|
+
* 1. Read file content via FileAccessProvider.
|
|
28
|
+
* 2. Split content into lines.
|
|
29
|
+
* 3. Target the lineHint (converting 1-based to 0-based).
|
|
30
|
+
* 4. Search for symbolName in that line.
|
|
31
|
+
* - If orderHint is 0, find first occurrence.
|
|
32
|
+
* - If orderHint is N, find Nth occurrence.
|
|
33
|
+
* 5. Robustness Fallback:
|
|
34
|
+
* - If the line is empty or symbol not found at lineHint,
|
|
35
|
+
* scan +/- lineSearchRadius lines to handle minor line shifts.
|
|
36
|
+
* 6. Return ExactPosition (line, character start index).
|
|
37
|
+
*/
|
|
38
|
+
export class SymbolResolver {
|
|
39
|
+
fs;
|
|
40
|
+
lineSearchRadius;
|
|
41
|
+
constructor(fs, config) {
|
|
42
|
+
this.fs = fs;
|
|
43
|
+
this.lineSearchRadius = config?.lineSearchRadius ?? 2;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolves a fuzzy position to an exact position.
|
|
47
|
+
*
|
|
48
|
+
* @param uri - The URI of the file
|
|
49
|
+
* @param fuzzy - The fuzzy position provided by the LLM
|
|
50
|
+
* @returns The exact position in the file
|
|
51
|
+
* @throws SymbolResolutionError if the symbol cannot be found
|
|
52
|
+
*/
|
|
53
|
+
async resolvePosition(uri, fuzzy) {
|
|
54
|
+
const content = await this.fs.readFile(uri);
|
|
55
|
+
const lines = content.split(/\r?\n/);
|
|
56
|
+
// Convert 1-based lineHint to 0-based index
|
|
57
|
+
const targetLine = fuzzy.lineHint - 1;
|
|
58
|
+
const orderHint = fuzzy.orderHint ?? 0;
|
|
59
|
+
// First, try to find the symbol at the exact line
|
|
60
|
+
const exactResult = this.findSymbolInLine(lines[targetLine], fuzzy.symbolName, orderHint);
|
|
61
|
+
if (exactResult !== null) {
|
|
62
|
+
return { line: targetLine, character: exactResult };
|
|
63
|
+
}
|
|
64
|
+
// Fallback: scan nearby lines
|
|
65
|
+
for (let offset = 1; offset <= this.lineSearchRadius; offset++) {
|
|
66
|
+
// Check line above
|
|
67
|
+
const lineAbove = targetLine - offset;
|
|
68
|
+
if (lineAbove >= 0) {
|
|
69
|
+
const resultAbove = this.findSymbolInLine(lines[lineAbove], fuzzy.symbolName, orderHint);
|
|
70
|
+
if (resultAbove !== null) {
|
|
71
|
+
return { line: lineAbove, character: resultAbove };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Check line below
|
|
75
|
+
const lineBelow = targetLine + offset;
|
|
76
|
+
if (lineBelow < lines.length) {
|
|
77
|
+
const resultBelow = this.findSymbolInLine(lines[lineBelow], fuzzy.symbolName, orderHint);
|
|
78
|
+
if (resultBelow !== null) {
|
|
79
|
+
return { line: lineBelow, character: resultBelow };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Symbol not found anywhere in the search range
|
|
84
|
+
throw new SymbolResolutionError(fuzzy.symbolName, fuzzy.lineHint, `Please verify the file content and try again. Searched lines ${Math.max(1, fuzzy.lineHint - this.lineSearchRadius)} to ${Math.min(lines.length, fuzzy.lineHint + this.lineSearchRadius)}.`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Finds the Nth occurrence of a symbol in a line.
|
|
88
|
+
*
|
|
89
|
+
* @param line - The line to search in (may be undefined if out of bounds)
|
|
90
|
+
* @param symbolName - The symbol to find
|
|
91
|
+
* @param orderHint - Which occurrence to find (0-based)
|
|
92
|
+
* @returns The character offset of the symbol, or null if not found
|
|
93
|
+
*/
|
|
94
|
+
findSymbolInLine(line, symbolName, orderHint) {
|
|
95
|
+
if (line === undefined || line.length === 0) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
let currentIndex = 0;
|
|
99
|
+
let occurrenceCount = 0;
|
|
100
|
+
while (currentIndex < line.length) {
|
|
101
|
+
const foundIndex = line.indexOf(symbolName, currentIndex);
|
|
102
|
+
if (foundIndex === -1) {
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
if (occurrenceCount === orderHint) {
|
|
106
|
+
return foundIndex;
|
|
107
|
+
}
|
|
108
|
+
occurrenceCount++;
|
|
109
|
+
currentIndex = foundIndex + 1;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Finds exact text in a file and returns its range.
|
|
115
|
+
* Used for search-and-replace operations.
|
|
116
|
+
*
|
|
117
|
+
* @param uri - The URI of the file
|
|
118
|
+
* @param searchText - The exact text to find
|
|
119
|
+
* @returns The range of the found text
|
|
120
|
+
* @throws Error if the text is not found or appears multiple times
|
|
121
|
+
*/
|
|
122
|
+
async findExactText(uri, searchText) {
|
|
123
|
+
const content = await this.fs.readFile(uri);
|
|
124
|
+
// Find all occurrences
|
|
125
|
+
const occurrences = [];
|
|
126
|
+
let searchIndex = 0;
|
|
127
|
+
while (searchIndex < content.length) {
|
|
128
|
+
const foundIndex = content.indexOf(searchText, searchIndex);
|
|
129
|
+
if (foundIndex === -1) {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
occurrences.push(foundIndex);
|
|
133
|
+
searchIndex = foundIndex + 1;
|
|
134
|
+
}
|
|
135
|
+
if (occurrences.length === 0) {
|
|
136
|
+
throw new Error(`Text not found in file: "${searchText.slice(0, 50)}${searchText.length > 50 ? '...' : ''}"`);
|
|
137
|
+
}
|
|
138
|
+
if (occurrences.length > 1) {
|
|
139
|
+
throw new Error(`Text appears ${occurrences.length} times in file. Please provide more context to uniquely identify the location.`);
|
|
140
|
+
}
|
|
141
|
+
// Convert character offset to line/character position
|
|
142
|
+
const startOffset = occurrences[0];
|
|
143
|
+
const endOffset = startOffset + searchText.length;
|
|
144
|
+
const start = this.offsetToPosition(content, startOffset);
|
|
145
|
+
const end = this.offsetToPosition(content, endOffset);
|
|
146
|
+
return { start, end };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Converts a character offset to a line/character position.
|
|
150
|
+
*/
|
|
151
|
+
offsetToPosition(content, offset) {
|
|
152
|
+
let line = 0;
|
|
153
|
+
let character = 0;
|
|
154
|
+
let currentOffset = 0;
|
|
155
|
+
for (const char of content) {
|
|
156
|
+
if (currentOffset === offset) {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
if (char === '\n') {
|
|
160
|
+
line++;
|
|
161
|
+
character = 0;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
character++;
|
|
165
|
+
}
|
|
166
|
+
currentOffset++;
|
|
167
|
+
}
|
|
168
|
+
return { line, character };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for MCP tool inputs and outputs.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
import * as z from 'zod/mini';
|
|
6
|
+
export declare const FuzzyPositionSchema: z.ZodMiniObject<{
|
|
7
|
+
uri: z.ZodMiniString<string>;
|
|
8
|
+
symbol_name: z.ZodMiniString<string>;
|
|
9
|
+
line_hint: z.ZodMiniNumber<number>;
|
|
10
|
+
order_hint: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniNumber<number>>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export declare const ApplyEditSchema: z.ZodMiniObject<{
|
|
13
|
+
uri: z.ZodMiniString<string>;
|
|
14
|
+
search_text: z.ZodMiniString<string>;
|
|
15
|
+
replace_text: z.ZodMiniString<string>;
|
|
16
|
+
description: z.ZodMiniString<string>;
|
|
17
|
+
}, z.core.$strip>;
|
|
18
|
+
export declare const CallHierarchySchema: z.ZodMiniObject<{
|
|
19
|
+
uri: z.ZodMiniString<string>;
|
|
20
|
+
symbol_name: z.ZodMiniString<string>;
|
|
21
|
+
line_hint: z.ZodMiniNumber<number>;
|
|
22
|
+
order_hint: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniNumber<number>>>;
|
|
23
|
+
direction: z.ZodMiniEnum<{
|
|
24
|
+
incoming: "incoming";
|
|
25
|
+
outgoing: "outgoing";
|
|
26
|
+
}>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
export declare const GlobalFindSchema: z.ZodMiniObject<{
|
|
29
|
+
query: z.ZodMiniString<string>;
|
|
30
|
+
case_sensitive: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
|
|
31
|
+
exact_match: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
|
|
32
|
+
regex_mode: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
export declare const GlobalReplaceSchema: z.ZodMiniObject<{
|
|
35
|
+
query: z.ZodMiniString<string>;
|
|
36
|
+
case_sensitive: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
|
|
37
|
+
exact_match: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
|
|
38
|
+
regex_mode: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
|
|
39
|
+
replace_with: z.ZodMiniString<string>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod schemas for MCP tool inputs and outputs.
|
|
3
|
+
* @internal
|
|
4
|
+
*/
|
|
5
|
+
import * as z from 'zod/mini';
|
|
6
|
+
const uri = z.string().check(z.describe('The relative file path'));
|
|
7
|
+
const symbol_name = z
|
|
8
|
+
.string()
|
|
9
|
+
.check(z.describe('The text of the symbol to find'));
|
|
10
|
+
const line_hint = z
|
|
11
|
+
.number()
|
|
12
|
+
.check(z.int(), z.positive(), z.describe('Approximate 1-based line number where the symbol is expected'));
|
|
13
|
+
const order_hint = z
|
|
14
|
+
._default(z.optional(z.number().check(z.int(), z.minimum(0))), 0)
|
|
15
|
+
.check(z.describe('0-based index of which occurrence to target if symbol appears multiple times'));
|
|
16
|
+
export const FuzzyPositionSchema = z.object({
|
|
17
|
+
uri,
|
|
18
|
+
symbol_name,
|
|
19
|
+
line_hint,
|
|
20
|
+
order_hint,
|
|
21
|
+
});
|
|
22
|
+
export const ApplyEditSchema = z.object({
|
|
23
|
+
uri,
|
|
24
|
+
search_text: z
|
|
25
|
+
.string()
|
|
26
|
+
.check(z.describe('Exact text to replace (must exist uniquely in the file)')),
|
|
27
|
+
replace_text: z.string().check(z.describe('New text to insert')),
|
|
28
|
+
description: z.string().check(z.describe('Rationale for the edit')),
|
|
29
|
+
});
|
|
30
|
+
export const CallHierarchySchema = z.object({
|
|
31
|
+
uri: z.string().check(z.describe('The file URI or path')),
|
|
32
|
+
symbol_name,
|
|
33
|
+
line_hint,
|
|
34
|
+
order_hint,
|
|
35
|
+
direction: z
|
|
36
|
+
.enum(['incoming', 'outgoing'])
|
|
37
|
+
.check(z.describe('Direction of the call hierarchy')),
|
|
38
|
+
});
|
|
39
|
+
const query = z.string().check(z.describe('The search query'));
|
|
40
|
+
const case_sensitive = z
|
|
41
|
+
._default(z.optional(z.boolean()), false)
|
|
42
|
+
.check(z.describe('Whether the search is case-sensitive'));
|
|
43
|
+
const exact_match = z
|
|
44
|
+
._default(z.optional(z.boolean()), false)
|
|
45
|
+
.check(z.describe('Whether to match exact words only'));
|
|
46
|
+
const regex_mode = z
|
|
47
|
+
._default(z.optional(z.boolean()), false)
|
|
48
|
+
.check(z.describe('Whether the query is a regular expression'));
|
|
49
|
+
export const GlobalFindSchema = z.object({
|
|
50
|
+
query,
|
|
51
|
+
case_sensitive,
|
|
52
|
+
exact_match,
|
|
53
|
+
regex_mode,
|
|
54
|
+
});
|
|
55
|
+
export const GlobalReplaceSchema = z.object({
|
|
56
|
+
query,
|
|
57
|
+
case_sensitive,
|
|
58
|
+
exact_match,
|
|
59
|
+
regex_mode,
|
|
60
|
+
replace_with: z.string().check(z.describe('The replacement text')),
|
|
61
|
+
});
|
|
62
|
+
//# sourceMappingURL=schemas.js.map
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Implementation for LSP Driver SDK
|
|
3
|
+
*
|
|
4
|
+
* The SDK automatically registers tools based on which capability providers
|
|
5
|
+
* are defined in the IdeCapabilities configuration.
|
|
6
|
+
*/
|
|
7
|
+
import { type McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
|
+
import type { IdeCapabilities } from './capabilities.js';
|
|
9
|
+
import { type ResolverConfig } from './resolver.js';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration options for the MCP LSP Driver.
|
|
12
|
+
*/
|
|
13
|
+
export interface McpLspDriverConfig {
|
|
14
|
+
/** Configuration for the symbol resolver */
|
|
15
|
+
resolverConfig?: ResolverConfig;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Register LSP-based tools and resources on the provided MCP server.
|
|
19
|
+
*/
|
|
20
|
+
export declare function installMcpLspDriver({ server, capabilities, config, }: {
|
|
21
|
+
server: McpServer;
|
|
22
|
+
capabilities: IdeCapabilities;
|
|
23
|
+
config?: McpLspDriverConfig;
|
|
24
|
+
}): {
|
|
25
|
+
success: boolean;
|
|
26
|
+
error: unknown;
|
|
27
|
+
reason: string;
|
|
28
|
+
} | {
|
|
29
|
+
success: boolean;
|
|
30
|
+
error?: undefined;
|
|
31
|
+
reason?: undefined;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=server.d.ts.map
|