mcp-lsp-driver 1.0.2 → 1.1.0

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.cjs ADDED
@@ -0,0 +1,15 @@
1
+ 'use strict';var net=require('net'),fs=require('fs'),mcp_js=require('@modelcontextprotocol/sdk/server/mcp.js'),zod=require('zod');var w=class{socket;requestHandler;notificationHandler;nextId=1;pending=new Map;buffer="";destroyed=false;constructor(e,t){this.socket=e,this.requestHandler=t?.onRequest,this.notificationHandler=t?.onNotification,e.on("data",i=>this.handleData(i)),e.on("close",()=>this.rejectAll(new Error("Connection closed"))),e.on("error",i=>this.rejectAll(i));}sendRequest(e,t){return this.destroyed?Promise.reject(new Error("Transport destroyed")):new Promise((i,n)=>{let r=this.nextId++;this.pending.set(r,{resolve:i,reject:n});let o={type:"request",id:r,method:e,params:t};this.socket.write(`${JSON.stringify(o)}
2
+ `);})}sendNotification(e,t){if(this.destroyed)return;let i={type:"notification",method:e,params:t};this.socket.write(`${JSON.stringify(i)}
3
+ `);}destroy(){this.destroyed||(this.destroyed=true,this.rejectAll(new Error("Transport destroyed")),this.socket.destroy());}handleData(e){this.buffer+=e.toString();let t=this.buffer.split(`
4
+ `);this.buffer=t.pop()??"";for(let i of t){let n=i.replace(/\r$/,"");if(n)try{let r=JSON.parse(n);this.dispatch(r);}catch{}}}dispatch(e){switch(e.type){case "response":{let t=this.pending.get(e.id);t&&(this.pending.delete(e.id),e.error?t.reject(new Error(e.error.message)):t.resolve(e.result));break}case "request":{this.requestHandler&&this.requestHandler(e.method,e.params).then(t=>{if(this.destroyed)return;let i={type:"response",id:e.id,result:t};this.socket.write(`${JSON.stringify(i)}
5
+ `);}).catch(t=>{if(this.destroyed)return;let i={type:"response",id:e.id,error:{message:t instanceof Error?t.message:String(t)}};this.socket.write(`${JSON.stringify(i)}
6
+ `);});break}case "notification":{this.notificationHandler?.(e.method,e.params);break}}}rejectAll(e){for(let[,t]of this.pending)t.reject(e);this.pending.clear();}};function T(s){return process.platform==="win32"?`\\\\.\\pipe\\${s}`:`/tmp/${s}.sock`}var R=[{providerKey:"fileAccess",methods:["readFile","readDirectory","getFileTree"]},{providerKey:"edit",methods:["applyEdits","previewAndApplyEdits"]},{providerKey:"definition",methods:["provideDefinition"]},{providerKey:"references",methods:["provideReferences"]},{providerKey:"hierarchy",methods:["provideCallHierarchy"]},{providerKey:"diagnostics",methods:["provideDiagnostics","getWorkspaceDiagnostics"]},{providerKey:"outline",methods:["provideDocumentSymbols"]},{providerKey:"globalFind",methods:["globalFind","globalReplace"]},{providerKey:"graph",methods:["getLinkStructure","resolveOutlinks","resolveBacklinks","addLink"]},{providerKey:"frontmatter",methods:["getFrontmatterStructure","getFrontmatter","setFrontmatter"]}];function Y(s){let{pipeName:e,connectTimeout:t=5e3}=s,i=T(e);return new Promise((n,r)=>{let o=net.connect(i),a=false,l=setTimeout(()=>{a||(a=true,o.destroy(),r(new Error(`Connection timeout after ${t}ms`)));},t);o.on("error",c=>{a||(a=true,clearTimeout(l),r(c));}),o.on("connect",()=>{if(clearTimeout(l),a)return;let c,u=new w(o,{onNotification:(f,h)=>{f==="onDiagnosticsChanged"&&c&&c(h[0]);}});u.sendRequest("_handshake",[]).then(f=>{if(a)return;let y=f.methods;if(!y.includes("fileAccess.readFile")||!y.includes("fileAccess.readDirectory"))throw u.destroy(),new Error("Server missing required methods: fileAccess.readFile, fileAccess.readDirectory");let v={};for(let{providerKey:b,methods:C}of R){let L=C.filter(E=>y.includes(`${b}.${E}`));if(L.length===0)continue;let _={};for(let E of L)_[E]=(...Q)=>u.sendRequest(`${b}.${E}`,Q);v[b]=_;}y.includes("onDiagnosticsChanged")&&(v.onDiagnosticsChanged=b=>{c=b;}),a=true,n({capabilities:v,availableMethods:y,disconnect(){u.destroy();}});}).catch(f=>{a||(a=true,u.destroy(),r(f instanceof Error?f:new Error(String(f))));});});})}function ee(s){let{capabilities:e,pipeName:t}=s,i=T(t),n=new Map;for(let{providerKey:l,methods:c}of R){let u=e[l];if(u)for(let f of c){let h=u[f];if(typeof h=="function"){let y=`${l}.${f}`;n.set(y,(...v)=>h.apply(u,v));}}}let r=[...n.keys()];e.onDiagnosticsChanged&&r.push("onDiagnosticsChanged");let o=new Set,a=net.createServer(l=>{let c=new w(l,{onRequest:async(u,f)=>{if(u==="_handshake")return {methods:r};let h=n.get(u);if(!h)throw new Error(`Unknown method: ${u}`);return h(...f)}});o.add(c),l.on("close",()=>o.delete(c));});return e.onDiagnosticsChanged&&e.onDiagnosticsChanged(l=>{for(let c of o)c.sendNotification("onDiagnosticsChanged",[l]);}),new Promise((l,c)=>{if(process.platform!=="win32")try{fs.unlinkSync(i);}catch{}a.on("error",c),a.listen(i,()=>{a.removeListener("error",c),l({get pipePath(){return i},get connectionCount(){return o.size},async close(){for(let u of o)u.destroy();if(o.clear(),await new Promise((u,f)=>{a.close(h=>{h?f(h):u();});}),process.platform!=="win32")try{fs.unlinkSync(i);}catch{}}});});})}var x=class extends Error{constructor(t,i,n){super(`Could not find symbol '${t}' at or near line ${i}. ${n}`);this.symbolName=t;this.lineHint=i;this.reason=n;this.name="SymbolResolutionError";}},k=class{constructor(e,t){this.fs=e;this.lineSearchRadius=t?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(e,t){let n=(await this.fs.readFile(e)).split(/\r?\n/),r=t.lineHint-1,o=t.orderHint??0,a=this.findSymbolInLine(n[r],t.symbolName,o);if(a!==null)return {line:r,character:a};for(let l=1;l<=this.lineSearchRadius;l++){let c=r-l;if(c>=0){let f=this.findSymbolInLine(n[c],t.symbolName,o);if(f!==null)return {line:c,character:f}}let u=r+l;if(u<n.length){let f=this.findSymbolInLine(n[u],t.symbolName,o);if(f!==null)return {line:u,character:f}}}throw new x(t.symbolName,t.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,t.lineHint-this.lineSearchRadius)} to ${Math.min(n.length,t.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(e,t,i){if(e===void 0||e.length===0)return null;let n=0,r=0;for(;n<e.length;){let o=e.indexOf(t,n);if(o===-1)break;if(r===i)return o;r++,n=o+1;}return null}async findExactText(e,t){let i=await this.fs.readFile(e),n=[],r=0;for(;r<i.length;){let u=i.indexOf(t,r);if(u===-1)break;n.push(u),r=u+1;}if(n.length===0)throw new Error(`Text not found in file: "${t.slice(0,50)}${t.length>50?"...":""}"`);if(n.length>1)throw new Error(`Text appears ${n.length} times in file. Please provide more context to uniquely identify the location.`);let o=n[0],a=o+t.length,l=this.offsetToPosition(i,o),c=this.offsetToPosition(i,a);return {start:l,end:c}}offsetToPosition(e,t){let i=0,n=0,r=0;for(let o of e){if(r===t)break;o===`
7
+ `?(i++,n=0):n++,r++;}return {line:i,character:n}}};var g=s=>({content:[{type:"text",text:JSON.stringify(s??"")}],structuredContent:s});function m(s){if(s.includes(".."))throw new Error('URI could not include ".." operator');return s.replace(/\\/g,"/")}function M(){return `edit-${Date.now()}`}function $(s){return s.length===0?"No diagnostics found.":s.map(e=>{let t=e.range.start.line+1,i=e.severity.toUpperCase(),n=e.source?` [${e.source}]`:"",r=e.code!==void 0?` (${e.code})`:"";return `- **${i}**${n}${r} at line ${t}: ${e.message}`}).join(`
8
+ `)}function D(s,e=0){if(s.length===0&&e===0)return "No symbols found.";let t=" ".repeat(e);return s.map(i=>{let n=i.range.start.line+1,r=i.range.end.line+1,o=n===r?`line ${n}`:`lines ${n}-${r}`,a=i.detail?` - ${i.detail}`:"",l=`${t}- **${i.kind}** \`${i.name}\`${a} (${o})`;return i.children&&i.children.length>0?`${l}
9
+ ${D(i.children,e+1)}`:l}).join(`
10
+ `)}var j=zod.z.string().describe("The relative file path"),O=zod.z.string().describe("The text of the symbol to find"),N=zod.z.number().int().positive().describe("Approximate 1-based line number where the symbol is expected"),A=zod.z.number().int().min(0).default(0).describe("0-based index of which occurrence to target if symbol appears multiple times"),F=zod.z.object({uri:j,symbol_name:O,line_hint:N,order_hint:A}),P=zod.z.object({uri:j,search_text:zod.z.string().describe("Exact text to replace (must exist uniquely in the file)"),replace_text:zod.z.string().describe("New text to insert"),description:zod.z.string().describe("Rationale for the edit")}),H=zod.z.object({uri:zod.z.string().describe("The file URI or path"),symbol_name:O,line_hint:N,order_hint:A,direction:zod.z.enum(["incoming","outgoing"]).describe("Direction of the call hierarchy")}),U=zod.z.string().describe("The search query"),q=zod.z.boolean().default(false).describe("Whether the search is case-sensitive"),z=zod.z.boolean().default(false).describe("Whether to match exact words only"),K=zod.z.boolean().default(false).describe("Whether the query is a regular expression"),G=zod.z.object({query:U,case_sensitive:q,exact_match:z,regex_mode:K}),J=zod.z.object({query:U,case_sensitive:q,exact_match:z,regex_mode:K,replace_with:zod.z.string().describe("The replacement text")}),W=zod.z.object({path:zod.z.string().describe("The path to the document to modify"),pattern:zod.z.string().describe("The text pattern to find and replace with a link"),link_to:zod.z.string().describe("The target URI the link should point to")}),B=zod.z.object({property:zod.z.string().describe("The frontmatter property name to search for"),path:zod.z.string().optional().describe("Optional path to limit the search to a specific document. If not provided, searches all documents.")}),V=zod.z.object({path:zod.z.string().describe("The path to the document to modify"),property:zod.z.string().describe("The frontmatter property name to set"),value:zod.z.union([zod.z.string(),zod.z.array(zod.z.string()),zod.z.number(),zod.z.array(zod.z.number()),zod.z.boolean(),zod.z.array(zod.z.boolean()),zod.z.null()]).describe("The value to set. Can be a string, number, boolean, array of these types, or null to remove.")});function te(s){if(!s)return null;let e=s.match(/^L(\d+)(?:-L(\d+))?$/);if(!e||!e[1])return null;let t=parseInt(e[1],10),i=e[2]?parseInt(e[2],10):t;return t<1||i<t?null:{start:t,end:i}}function re(s,e){let t=s.split(/\r?\n/),i=e.start-1,n=e.end;return t.slice(i,n).join(`
11
+ `)}function ne({server:s,capabilities:e,config:t}){let i=new k(e.fileAccess,t?.resolverConfig);try{ie(s,e,i);}catch(n){return {success:false,error:n,reason:"Error occured during registration of tools"}}try{oe(s,e);}catch(n){return {success:false,error:n,reason:"Error occured during registration of resources"}}return {success:true}}function ie(s,e,t){e.definition&&se(s,e,t),e.references&&ae(s,e,t),e.hierarchy&&ce(s,e,t),e.edit&&pe(s,e,t),e.globalFind&&(fe(s,e),me(s,e)),e.graph&&(ge(s,e),ye(s,e)),e.frontmatter&&(be(s,e),ve(s,e));}function oe(s,e){ue(s,e),e.diagnostics&&le(s,e),e.outline&&de(s,e),e.graph&&he(s,e),e.frontmatter&&xe(s,e);}function se(s,e,t){let i=e.definition;i&&s.registerTool("goto_definition",{description:"Navigate to the definition of a symbol.",inputSchema:F,outputSchema:{snippets:zod.z.array(zod.z.object({uri:zod.z.string(),startLine:zod.z.number(),endLine:zod.z.number(),content:zod.z.string()}))}},async n=>{try{let r=m(n.uri),o={symbolName:n.symbol_name,lineHint:n.line_hint,orderHint:n.order_hint},a=await t.resolvePosition(r,o),l=(await i.provideDefinition(r,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return g({snippets:l})}catch(r){let o=r instanceof x?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function ae(s,e,t){let i=e.references;i&&s.registerTool("find_references",{description:"Find all references to a symbol. Returns a list of locations where the symbol is used.",inputSchema:F,outputSchema:{snippets:zod.z.array(zod.z.object({uri:zod.z.string(),startLine:zod.z.number(),endLine:zod.z.number(),content:zod.z.string()}))}},async n=>{try{let r=m(n.uri),o={symbolName:n.symbol_name,lineHint:n.line_hint,orderHint:n.order_hint},a=await t.resolvePosition(r,o),l=(await i.provideReferences(r,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return g({snippets:l})}catch(r){let o=r instanceof x?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function ce(s,e,t){let i=e.hierarchy;i&&s.registerTool("call_hierarchy",{description:"Get call hierarchy for a function or method. Shows incoming or outgoing calls.",inputSchema:H,outputSchema:{snippets:zod.z.array(zod.z.object({uri:zod.z.string(),startLine:zod.z.number(),endLine:zod.z.number(),content:zod.z.string()}))}},async n=>{try{let r=m(n.uri),o={symbolName:n.symbol_name,lineHint:n.line_hint,orderHint:n.order_hint},a=await t.resolvePosition(r,o),l=(await i.provideCallHierarchy(r,a,n.direction)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return g({snippets:l})}catch(r){let o=r instanceof x?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function le(s,e){let t=e.diagnostics;if(!t)return;let i=new mcp_js.ResourceTemplate("diagnostics://{+path}",{list:void 0});if(s.registerResource("diagnostics",i,{description:"Diagnostics (errors, warnings, hints) for a specific file. Use the file path after diagnostics://",mimeType:"text/markdown"},async(n,r)=>{try{let o=r.path,a=m(o),l=await t.provideDiagnostics(a),c=$(l);return {contents:[{uri:`diagnostics://${o}`,mimeType:"text/markdown",text:c}]}}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`diagnostics://${r.path}`,mimeType:"text/markdown",text:a}]}}}),t.getWorkspaceDiagnostics){let n=t.getWorkspaceDiagnostics.bind(t);s.registerResource("workspace-diagnostics","diagnostics://workspace",{description:"All diagnostics (errors, warnings, hints) across the entire workspace",mimeType:"text/markdown"},async()=>{try{let r=await n(),o=new Map;for(let l of r){let c=o.get(l.uri)??[];c.push(l),o.set(l.uri,c);}if(o.size===0)return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:"No diagnostics found in workspace."}]};let a=[];for(let[l,c]of o)a.push(`## ${l}
12
+ ${$(c)}`);return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:a.join(`
13
+
14
+ `)}]}}catch(r){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${r instanceof Error?r.message:String(r)}`}]}}});}e.onDiagnosticsChanged&&e.onDiagnosticsChanged(n=>{let r=m(n);s.server.sendResourceUpdated({uri:`diagnostics://${r}`}),t.getWorkspaceDiagnostics&&s.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function de(s,e){let t=e.outline;if(!t)return;let i=new mcp_js.ResourceTemplate("outline://{+path}",{list:void 0});s.registerResource("outline",i,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(n,r)=>{try{let o=r.path,a=m(o),l=await t.provideDocumentSymbols(a),c=D(l);return {contents:[{uri:`outline://${o}`,mimeType:"text/markdown",text:c}]}}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`outline://${r.path}`,mimeType:"text/markdown",text:a}]}}});}function pe(s,e,t){let i=e.edit;if(!i)return;let n=i.previewAndApplyEdits?.bind(i)??i.applyEdits?.bind(i);n&&s.registerTool("apply_edit",{description:"Apply a text edit to a file. The edit must be approved by the user before being applied.",inputSchema:{uri:P.shape.uri,search_text:P.shape.search_text,replace_text:P.shape.replace_text,description:P.shape.description},outputSchema:{success:zod.z.boolean(),message:zod.z.string()}},async r=>{try{let o=m(r.uri),a=await t.findExactText(o,r.search_text),l={id:M(),uri:o,edits:[{range:a,newText:r.replace_text}],description:r.description},u=await n(l)?{success:!0,message:"Edit successfully applied and saved."}:{success:!1,message:"Edit rejected by user."};return g(u)}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:a}],structuredContent:{success:false,message:a},isError:true}}});}function ue(s,e){let{readFile:t,readDirectory:i,getFileTree:n}=e.fileAccess;if(n!==void 0){let o=new mcp_js.ResourceTemplate("filetree://{+path}",{list:void 0});s.registerResource("filetree",o,{description:'Access file tree inside a relative path or use "." for root.'},async(a,{path:l})=>({contents:[{uri:a.toString(),mimeType:"application/json",text:JSON.stringify(await n(m(l))??"")}]}));}let r=new mcp_js.ResourceTemplate("files://{+path}",{list:void 0});s.registerResource("filesystem",r,{description:"Access filesystem resources. For directories: returns children (git-ignored files excluded). For files: returns file content. Supports line ranges with #L23 or #L23-L30 fragment."},async(o,a)=>{let l=o.toString();try{let c=a.path,u,f=c,h=c.indexOf("#");h!==-1&&(u=c.slice(h+1),f=c.slice(0,h));let y=m(f),v=te(u);try{let b=await t(y),C=v?re(b,v):b;return {contents:[{uri:l,mimeType:"text/plain",text:C}]}}catch{let b=await i(y);return {contents:[{uri:l,mimeType:"application/json",text:JSON.stringify(b)}]}}}catch(c){let u=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:l,mimeType:"text/plain",text:u}]}}});}function fe(s,e){let t=e.globalFind;t&&s.registerTool("global_find",{description:"Search for text across the entire workspace.",inputSchema:G,outputSchema:{matches:zod.z.array(zod.z.object({uri:zod.z.string(),line:zod.z.number(),column:zod.z.number(),matchText:zod.z.string(),context:zod.z.string()})),count:zod.z.number()}},async i=>{try{let n=i.case_sensitive??!1,r=i.exact_match??!1,o=i.regex_mode??!1,a=await t.globalFind(i.query,{caseSensitive:n,exactMatch:r,regexMode:o});return g({count:a.length,matches:a})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{error:r},isError:true}}});}function me(s,e){let t=e.globalFind;t&&s.registerTool("global_replace",{description:"Replace all occurrences of text across the entire workspace.",inputSchema:J,outputSchema:{success:zod.z.boolean(),count:zod.z.number(),message:zod.z.string().optional()}},async i=>{try{let n=i.case_sensitive??!1,r=i.exact_match??!1,o=i.regex_mode??!1,a=await t.globalReplace(i.query,i.replace_with,{caseSensitive:n,exactMatch:r,regexMode:o});return g({success:!0,count:a})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,replacementCount:0,message:r},isError:true}}});}function he(s,e){let t=e.graph;if(!t)return;let i=new mcp_js.ResourceTemplate("outlinks://{+path}",{list:void 0});s.registerResource("outlinks",i,{description:"Outgoing links from a specific file. Use the file path after outlinks://",mimeType:"application/json"},async(r,o)=>{try{let a=o.path,l=m(a),c=await t.resolveOutlinks(l);return {contents:[{uri:`outlinks://${a}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(a){let l=`Error: ${a instanceof Error?a.message:String(a)}`;return {contents:[{uri:`outlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});let n=new mcp_js.ResourceTemplate("backlinks://{+path}",{list:void 0});s.registerResource("backlinks",n,{description:"Incoming links (backlinks) to a specific file. Use the file path after backlinks://",mimeType:"application/json"},async(r,o)=>{try{let a=o.path,l=m(a),c=await t.resolveBacklinks(l);return {contents:[{uri:`backlinks://${a}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(a){let l=`Error: ${a instanceof Error?a.message:String(a)}`;return {contents:[{uri:`backlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});}function ge(s,e){let t=e.graph;t&&s.registerTool("get_link_structure",{description:"Get all links in the workspace, showing relationships between documents.",inputSchema:{},outputSchema:{links:zod.z.array(zod.z.object({sourceUri:zod.z.string(),targetUri:zod.z.string(),subpath:zod.z.string().optional(),displayText:zod.z.string().optional(),resolved:zod.z.boolean(),line:zod.z.number(),column:zod.z.number()}))}},async()=>{try{let i=await t.getLinkStructure();return g({links:i})}catch(i){let n=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:n}],structuredContent:{error:n},isError:true}}});}function ye(s,e){let t=e.graph;t&&s.registerTool("add_link",{description:"Add a link to a document by finding a text pattern and replacing it with a link to the target.",inputSchema:W,outputSchema:{success:zod.z.boolean(),message:zod.z.string().optional()}},async i=>{try{let n=m(i.path),r=m(i.link_to);return await t.addLink(n,i.pattern,r),g({success:!0,message:"Link added successfully."})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,message:r},isError:true}}});}function be(s,e){let t=e.frontmatter;t&&s.registerTool("get_frontmatter_structure",{description:"Get frontmatter property values across documents. If path is provided, searches only that document. Otherwise, searches all documents.",inputSchema:B,outputSchema:{matches:zod.z.array(zod.z.object({path:zod.z.string(),value:zod.z.unknown()}))}},async i=>{try{let n=i.path?m(i.path):void 0,r=await t.getFrontmatterStructure(i.property,n);return g({matches:r})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{error:r},isError:true}}});}function ve(s,e){let t=e.frontmatter;t&&s.registerTool("set_frontmatter",{description:"Set a frontmatter property on a document. Use null to remove the property.",inputSchema:V,outputSchema:{success:zod.z.boolean(),message:zod.z.string().optional()}},async i=>{try{let n=m(i.path),r=i.value===null?void 0:i.value;return await t.setFrontmatter(n,i.property,r),g({success:!0,message:"Frontmatter updated successfully."})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,message:r},isError:true}}});}function xe(s,e){let t=e.frontmatter;if(!t)return;let i=new mcp_js.ResourceTemplate("frontmatter://{+path}",{list:void 0});s.registerResource("frontmatter",i,{description:"Frontmatter metadata for a specific file. Use the file path after frontmatter://",mimeType:"application/json"},async(n,r)=>{try{let o=r.path,a=m(o),l=await t.getFrontmatter(a);return {contents:[{uri:`frontmatter://${o}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`frontmatter://${r.path}`,mimeType:"application/json",text:JSON.stringify({error:a})}]}}});}
15
+ exports.SymbolResolutionError=x;exports.SymbolResolver=k;exports.connectLspPipe=Y;exports.installMcpLspDriver=ne;exports.serveLspPipe=ee;
@@ -0,0 +1,604 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ /**
4
+ * Core Data Models for MCP LSP Driver SDK
5
+ *
6
+ * These types define how the LLM communicates intent versus
7
+ * how the IDE executes commands.
8
+ */
9
+ /**
10
+ * A Unified Resource Identifier.
11
+ * Must be a file system path.
12
+ */
13
+ type UnifiedUri = string;
14
+ /**
15
+ * 0-based exact coordinate system (Used internally by IDE).
16
+ */
17
+ interface ExactPosition {
18
+ /** 0-based line number */
19
+ line: number;
20
+ /** 0-based column (character offset) */
21
+ character: number;
22
+ }
23
+ /**
24
+ * The fuzzy location provided by the LLM.
25
+ * Designed to be robust against minor formatting changes or token counting errors.
26
+ */
27
+ interface FuzzyPosition {
28
+ /**
29
+ * The text of the symbol to find (e.g., function name, variable name).
30
+ */
31
+ symbolName: string;
32
+ /**
33
+ * An approximate line number where the symbol is expected.
34
+ * 1-based (Human friendly) for LLM input, converted to 0-based internally.
35
+ */
36
+ lineHint: number;
37
+ /**
38
+ * If the symbol appears multiple times on the line, which occurrence to target?
39
+ * 0-based index. Defaults to 0 (the first occurrence).
40
+ * Example: "add(a, a)" -> looking for second 'a' -> orderHint: 1.
41
+ */
42
+ orderHint?: number;
43
+ }
44
+ /**
45
+ * Represents a resolved span of text on disk.
46
+ */
47
+ interface DiskRange {
48
+ start: ExactPosition;
49
+ end: ExactPosition;
50
+ }
51
+ /**
52
+ * Represents a snippet of code read from disk.
53
+ */
54
+ interface CodeSnippet {
55
+ /** The URI of the file containing the snippet */
56
+ uri: UnifiedUri;
57
+ /** The range of the snippet in the file */
58
+ range: DiskRange;
59
+ /** The actual text read from disk */
60
+ content: string;
61
+ }
62
+ /**
63
+ * Represents a proposed change to a file.
64
+ */
65
+ interface TextEdit {
66
+ /** The range to replace */
67
+ range: DiskRange;
68
+ /** The new text to insert */
69
+ newText: string;
70
+ }
71
+ /**
72
+ * Represents a pending edit operation that awaits user approval.
73
+ */
74
+ interface PendingEditOperation {
75
+ /** Unique identifier for this operation */
76
+ id: string;
77
+ /** The URI of the file to edit */
78
+ uri: UnifiedUri;
79
+ /** The list of edits to apply */
80
+ edits: TextEdit[];
81
+ /** Optional description of the edit (e.g., "Refactor logic to handle null cases") */
82
+ description?: string;
83
+ }
84
+ /**
85
+ * The reason why an edit operation failed.
86
+ */
87
+ type EditFailureReason = 'UserRejected' | 'IOError' | 'ValidationFailed';
88
+ /**
89
+ * The result of an edit operation.
90
+ */
91
+ type EditResult = {
92
+ success: boolean;
93
+ message: string;
94
+ };
95
+ /**
96
+ * Severity level for diagnostics.
97
+ */
98
+ type DiagnosticSeverity = 'error' | 'warning' | 'information' | 'hint';
99
+ /**
100
+ * Represents a diagnostic (error, warning, etc.) from the IDE.
101
+ */
102
+ interface Diagnostic {
103
+ /** The URI of the file containing the diagnostic */
104
+ uri: UnifiedUri;
105
+ /** The range of the diagnostic */
106
+ range: DiskRange;
107
+ /** The severity of the diagnostic */
108
+ severity: DiagnosticSeverity;
109
+ /** The diagnostic message */
110
+ message: string;
111
+ /** Optional source of the diagnostic (e.g., "typescript", "eslint") */
112
+ source?: string;
113
+ /** Optional diagnostic code */
114
+ code?: string | number;
115
+ }
116
+ /**
117
+ * Symbol kind for outline items.
118
+ */
119
+ type SymbolKind = 'file' | 'module' | 'namespace' | 'package' | 'class' | 'method' | 'property' | 'field' | 'constructor' | 'enum' | 'interface' | 'function' | 'variable' | 'constant' | 'string' | 'number' | 'boolean' | 'array' | 'object' | 'key' | 'null' | 'enumMember' | 'struct' | 'event' | 'operator' | 'typeParameter';
120
+ /**
121
+ * Represents a symbol in the document outline (e.g., class, function, variable).
122
+ */
123
+ interface DocumentSymbol {
124
+ /** The name of the symbol */
125
+ name: string;
126
+ /** More detail for this symbol (e.g., signature) */
127
+ detail?: string;
128
+ /** The kind of this symbol */
129
+ kind: SymbolKind;
130
+ /** The range of the entire symbol (including body) */
131
+ range: DiskRange;
132
+ /** The range of the symbol's name */
133
+ selectionRange: DiskRange;
134
+ /** Children of this symbol (e.g., methods in a class) */
135
+ children?: DocumentSymbol[];
136
+ }
137
+ /**
138
+ * Allowed values for frontmatter properties.
139
+ */
140
+ type FrontmatterValue = string | string[] | number | number[] | boolean | boolean[] | Date | undefined;
141
+ /**
142
+ * A frontmatter object mapping property names to values.
143
+ */
144
+ type Frontmatter = {
145
+ [key: string]: FrontmatterValue;
146
+ };
147
+ /**
148
+ * A frontmatter property match from a structure query.
149
+ */
150
+ interface FrontmatterMatch {
151
+ /** The path to the document containing the frontmatter */
152
+ path: UnifiedUri;
153
+ /** The value of the frontmatter property */
154
+ value: FrontmatterValue;
155
+ }
156
+ /**
157
+ * Represents a link between documents (e.g., wiki-style links, imports, references).
158
+ */
159
+ interface Link {
160
+ /** The source URI where this link originates from */
161
+ sourceUri: UnifiedUri;
162
+ /** The target URI this link points to */
163
+ targetUri: UnifiedUri;
164
+ /** Optional subpath within the target (e.g., heading anchor like #section) */
165
+ subpath?: string;
166
+ /** The display text of the link (if different from target) */
167
+ displayText?: string;
168
+ /** Whether the link target has been resolved to an existing document */
169
+ resolved: boolean;
170
+ /** 1-based line number where the link appears */
171
+ line: number;
172
+ /** 1-based column where the link starts */
173
+ column: number;
174
+ }
175
+
176
+ /**
177
+ * Infrastructure Interfaces for MCP LSP Driver SDK
178
+ *
179
+ * The SDK consumer (Plugin Developer) must implement these interfaces
180
+ * to bridge the SDK to the specific IDE.
181
+ */
182
+
183
+ /**
184
+ * Provides access to the file system for reading files.
185
+ * Since the SDK is responsible for resolving FuzzyPosition to ExactPosition,
186
+ * it needs direct access to read files from the disk.
187
+ */
188
+ interface FileAccessProvider {
189
+ /**
190
+ * Reads the content of a file from the disk (ignoring unsaved IDE buffers).
191
+ * Used for symbol resolution and context retrieval.
192
+ *
193
+ * @param uri - The URI of the file to read
194
+ * @returns The content of the file as a string
195
+ * @throws Error if the file cannot be read
196
+ */
197
+ readFile(uri: UnifiedUri): Promise<string>;
198
+ /**
199
+ * Read children in a directory, exluding git-ignored files, similar to Unix `ls` command
200
+ * @param relativePath - The path to the folder to read
201
+ * @returns Array of file/folder paths in the directory
202
+ */
203
+ readDirectory(relativePath: UnifiedUri): Promise<string[]>;
204
+ /**
205
+ * Gets the file tree for a directory, excluding git-ignored files.
206
+ *
207
+ * @param relativePath - The path to the folder to read
208
+ * @returns Array of file/folder paths in the directory tree
209
+ */
210
+ getFileTree?: (relativePath: UnifiedUri) => Promise<string[]>;
211
+ }
212
+ /**
213
+ * Provides edit capabilities for applying changes to files.
214
+ * At least one of the methods must be implemented.
215
+ */
216
+ interface EditProvider {
217
+ /**
218
+ * Applies edits directly without user interaction.
219
+ * Use this when user approval is handled elsewhere or not needed.
220
+ *
221
+ * @param operation - The pending edit operation to apply
222
+ * @returns true if applied successfully, false if failed
223
+ */
224
+ applyEdits?(operation: PendingEditOperation): Promise<boolean>;
225
+ /**
226
+ * Displays a diff view or a confirmation dialog in the IDE.
227
+ * The user decides whether to apply the edits or discard them.
228
+ *
229
+ * @param operation - The pending edit operation to preview
230
+ * @returns true if applied, false if rejected/cancelled
231
+ */
232
+ previewAndApplyEdits?(operation: PendingEditOperation): Promise<boolean>;
233
+ }
234
+
235
+ /**
236
+ * Capability Providers for MCP LSP Driver SDK
237
+ *
238
+ * The Plugin Developer provides an implementation of IdeCapabilities.
239
+ * The SDK exposes tools based on which optional providers are defined.
240
+ *
241
+ * Note: All inputs here use ExactPosition. The SDK handles the
242
+ * Fuzzy -> Exact conversion before calling these.
243
+ */
244
+
245
+ /**
246
+ * Provides go-to-definition functionality.
247
+ */
248
+ interface DefinitionProvider {
249
+ /**
250
+ * Returns definition location reading strictly from disk context.
251
+ *
252
+ * @param uri - The URI of the file
253
+ * @param position - The exact position to find the definition for
254
+ * @returns Array of code snippets representing definition locations
255
+ */
256
+ provideDefinition(uri: UnifiedUri, position: ExactPosition): Promise<CodeSnippet[]>;
257
+ }
258
+ /**
259
+ * Provides find-references functionality.
260
+ */
261
+ interface ReferencesProvider {
262
+ /**
263
+ * Finds all references to the symbol at the given position.
264
+ *
265
+ * @param uri - The URI of the file
266
+ * @param position - The exact position to find references for
267
+ * @returns Array of code snippets representing reference locations
268
+ */
269
+ provideReferences(uri: UnifiedUri, position: ExactPosition): Promise<CodeSnippet[]>;
270
+ }
271
+ /**
272
+ * Provides call hierarchy functionality.
273
+ */
274
+ interface HierarchyProvider {
275
+ /**
276
+ * Provides call hierarchy information for the symbol at the given position.
277
+ *
278
+ * @param uri - The URI of the file
279
+ * @param position - The exact position to get call hierarchy for
280
+ * @param direction - Whether to get incoming or outgoing calls
281
+ * @returns Array of code snippets representing call hierarchy items
282
+ */
283
+ provideCallHierarchy(uri: UnifiedUri, position: ExactPosition, direction: 'incoming' | 'outgoing'): Promise<CodeSnippet[]>;
284
+ }
285
+ /**
286
+ * Provides diagnostics (errors, warnings) for a file.
287
+ */
288
+ interface DiagnosticsProvider {
289
+ /**
290
+ * Gets diagnostics for a file.
291
+ *
292
+ * @param uri - The URI of the file
293
+ * @returns Array of diagnostics for the file
294
+ */
295
+ provideDiagnostics(uri: UnifiedUri): Promise<Diagnostic[]>;
296
+ /**
297
+ * Gets diagnostics for all files in the workspace.
298
+ * If not provided, the workspace diagnostics resource will not be available.
299
+ *
300
+ * @returns Array of diagnostics for all files in the workspace
301
+ */
302
+ getWorkspaceDiagnostics?(): Promise<Diagnostic[]>;
303
+ }
304
+ /**
305
+ * Provides document outline (symbols) for a file.
306
+ */
307
+ interface OutlineProvider {
308
+ /**
309
+ * Gets the document symbols (outline) for a file.
310
+ *
311
+ * @param uri - The URI of the file
312
+ * @returns Array of document symbols representing the file's outline
313
+ */
314
+ provideDocumentSymbols(uri: UnifiedUri): Promise<DocumentSymbol[]>;
315
+ }
316
+ /**
317
+ * Search options for global find operations.
318
+ */
319
+ interface GlobalFindOptions {
320
+ /** Whether the search is case-sensitive */
321
+ caseSensitive: boolean;
322
+ /** Whether to match exact words only */
323
+ exactMatch: boolean;
324
+ /** Whether the query is a regular expression */
325
+ regexMode: boolean;
326
+ }
327
+ /**
328
+ * A match result from a global find operation.
329
+ */
330
+ interface GlobalFindMatch {
331
+ /** The URI of the file containing the match */
332
+ uri: UnifiedUri;
333
+ /** 1-based line number of the match */
334
+ line: number;
335
+ /** 1-based column of the match */
336
+ column: number;
337
+ /** The matching text */
338
+ matchText: string;
339
+ /** Context around the match (e.g., the full line) */
340
+ context: string;
341
+ }
342
+ /**
343
+ * Provides global find functionality across the workspace.
344
+ */
345
+ interface GlobalFindProvider {
346
+ /**
347
+ * Performs a global find operation across the workspace.
348
+ *
349
+ * @param query - The search query
350
+ * @param options - Search options (case sensitivity, exact match, regex mode)
351
+ * @returns Array of matches found
352
+ */
353
+ globalFind(query: string, options: GlobalFindOptions): Promise<GlobalFindMatch[]>;
354
+ /**
355
+ * Performs a global replace operation across the workspace.
356
+ * The query and options are decoded from the ID generated by globalFind.
357
+ *
358
+ * @param query - The search query (decoded from the ID)
359
+ * @param replaceWith - The replacement text
360
+ * @param options - Search options (decoded from the ID)
361
+ * @returns The number of replacements made
362
+ */
363
+ globalReplace(query: string, replaceWith: string, options: GlobalFindOptions): Promise<number>;
364
+ }
365
+ /**
366
+ * Provides graph/link functionality for document relationships.
367
+ */
368
+ interface GraphProvider {
369
+ /**
370
+ * Gets all links in the workspace.
371
+ *
372
+ * @returns Array of all links in the workspace
373
+ */
374
+ getLinkStructure(): Promise<Link[]>;
375
+ /**
376
+ * Resolves outgoing links from a specific document.
377
+ *
378
+ * @param path - The path to the document
379
+ * @returns Array of outgoing links from the document
380
+ */
381
+ resolveOutlinks(path: UnifiedUri): Promise<Link[]>;
382
+ /**
383
+ * Resolves incoming links (backlinks) to a specific document.
384
+ *
385
+ * @param path - The path to the document
386
+ * @returns Array of links pointing to this document
387
+ */
388
+ resolveBacklinks(path: UnifiedUri): Promise<Link[]>;
389
+ /**
390
+ * Adds a link to a document by finding a pattern and replacing it with a link.
391
+ * Throws an error if the operation fails (e.g., pattern not found).
392
+ *
393
+ * @param path - The path to the document to modify
394
+ * @param pattern - The text pattern to find and replace with a link
395
+ * @param linkTo - The target URI the link should point to
396
+ * @throws Error if the link cannot be added
397
+ */
398
+ addLink(path: UnifiedUri, pattern: string, linkTo: UnifiedUri): Promise<void>;
399
+ }
400
+ /**
401
+ * Provides frontmatter functionality for document metadata.
402
+ */
403
+ interface FrontmatterProvider {
404
+ /**
405
+ * Gets the frontmatter structure for a specific property across documents.
406
+ * If path is provided, searches only that document. Otherwise, searches all documents.
407
+ *
408
+ * @param property - The frontmatter property name to search for
409
+ * @param path - Optional path to limit the search to a specific document
410
+ * @returns Array of matches containing path and value
411
+ */
412
+ getFrontmatterStructure(property: string, path?: UnifiedUri): Promise<FrontmatterMatch[]>;
413
+ /**
414
+ * Gets all frontmatter for a specific document.
415
+ *
416
+ * @param path - The path to the document
417
+ * @returns The frontmatter object for the document
418
+ */
419
+ getFrontmatter(path: UnifiedUri): Promise<Frontmatter>;
420
+ /**
421
+ * Sets a frontmatter property on a document.
422
+ * Throws an error if the operation fails.
423
+ *
424
+ * @param path - The path to the document
425
+ * @param property - The property name to set
426
+ * @param value - The value to set
427
+ * @throws Error if the frontmatter cannot be updated
428
+ */
429
+ setFrontmatter(path: UnifiedUri, property: string, value: FrontmatterValue): Promise<void>;
430
+ }
431
+ /**
432
+ * Callback that gets invoked when diagnostics change.
433
+ * Used for MCP resource subscription support.
434
+ */
435
+ type OnDiagnosticsChangedCallback = (uri: UnifiedUri) => void;
436
+ /**
437
+ * The complete set of capabilities that an IDE plugin can provide.
438
+ * The SDK will automatically register tools based on which providers are defined.
439
+ */
440
+ interface IdeCapabilities {
441
+ /** Mandatory: Provides file system access for reading files from disk */
442
+ fileAccess: FileAccessProvider;
443
+ /** Optional: Provides edit capabilities for applying changes */
444
+ edit?: EditProvider;
445
+ /** Optional: Provides go-to-definition functionality */
446
+ definition?: DefinitionProvider;
447
+ /** Optional: Provides find-references functionality */
448
+ references?: ReferencesProvider;
449
+ /** Optional: Provides call hierarchy functionality */
450
+ hierarchy?: HierarchyProvider;
451
+ /** Optional: Provides diagnostics for files */
452
+ diagnostics?: DiagnosticsProvider;
453
+ /** Optional: Provides document outline (symbols) for files */
454
+ outline?: OutlineProvider;
455
+ /** Optional: Provides global find and replace functionality */
456
+ globalFind?: GlobalFindProvider;
457
+ /** Optional: Provides graph/link functionality for document relationships */
458
+ graph?: GraphProvider;
459
+ /** Optional: Provides frontmatter functionality for document metadata */
460
+ frontmatter?: FrontmatterProvider;
461
+ /**
462
+ * Optional: Called by the driver to register a callback for diagnostics changes.
463
+ * When this is provided, the diagnostics resources become subscribable.
464
+ * The plugin should call the registered callback whenever diagnostics change for a URI.
465
+ *
466
+ * @param callback - The callback to invoke when diagnostics change
467
+ */
468
+ onDiagnosticsChanged?: (callback: OnDiagnosticsChangedCallback) => void;
469
+ }
470
+
471
+ interface ConnectLspPipeOptions {
472
+ pipeName: string;
473
+ connectTimeout?: number;
474
+ }
475
+ interface LspPipeConnection {
476
+ readonly capabilities: IdeCapabilities;
477
+ readonly availableMethods: string[];
478
+ disconnect(): void;
479
+ }
480
+ declare function connectLspPipe(options: ConnectLspPipeOptions): Promise<LspPipeConnection>;
481
+
482
+ interface ServeLspPipeOptions {
483
+ capabilities: IdeCapabilities;
484
+ pipeName: string;
485
+ }
486
+ interface LspPipeServer {
487
+ readonly pipePath: string;
488
+ readonly connectionCount: number;
489
+ close(): Promise<void>;
490
+ }
491
+ declare function serveLspPipe(options: ServeLspPipeOptions): Promise<LspPipeServer>;
492
+
493
+ /**
494
+ * Smart Resolver Logic for MCP LSP Driver SDK
495
+ *
496
+ * This is the internal engine of the SDK. It translates the LLM's imprecise
497
+ * instructions into precise coordinates.
498
+ */
499
+
500
+ /**
501
+ * Configuration options for the SymbolResolver.
502
+ */
503
+ interface ResolverConfig {
504
+ /**
505
+ * Number of lines to scan above and below the lineHint if the symbol
506
+ * is not found at the exact line. Defaults to 2.
507
+ */
508
+ lineSearchRadius?: number;
509
+ }
510
+ /**
511
+ * Error thrown when a symbol cannot be resolved.
512
+ */
513
+ declare class SymbolResolutionError extends Error {
514
+ readonly symbolName: string;
515
+ readonly lineHint: number;
516
+ readonly reason: string;
517
+ constructor(symbolName: string, lineHint: number, reason: string);
518
+ }
519
+ /**
520
+ * The SymbolResolver translates fuzzy positions (as provided by an LLM)
521
+ * into exact positions that can be used by the IDE.
522
+ *
523
+ * Algorithm:
524
+ * 1. Read file content via FileAccessProvider.
525
+ * 2. Split content into lines.
526
+ * 3. Target the lineHint (converting 1-based to 0-based).
527
+ * 4. Search for symbolName in that line.
528
+ * - If orderHint is 0, find first occurrence.
529
+ * - If orderHint is N, find Nth occurrence.
530
+ * 5. Robustness Fallback:
531
+ * - If the line is empty or symbol not found at lineHint,
532
+ * scan +/- lineSearchRadius lines to handle minor line shifts.
533
+ * 6. Return ExactPosition (line, character start index).
534
+ */
535
+ declare class SymbolResolver {
536
+ private readonly fs;
537
+ private readonly lineSearchRadius;
538
+ constructor(fs: FileAccessProvider, config?: ResolverConfig);
539
+ /**
540
+ * Resolves a fuzzy position to an exact position.
541
+ *
542
+ * @param uri - The URI of the file
543
+ * @param fuzzy - The fuzzy position provided by the LLM
544
+ * @returns The exact position in the file
545
+ * @throws SymbolResolutionError if the symbol cannot be found
546
+ */
547
+ resolvePosition(uri: UnifiedUri, fuzzy: FuzzyPosition): Promise<ExactPosition>;
548
+ /**
549
+ * Finds the Nth occurrence of a symbol in a line.
550
+ *
551
+ * @param line - The line to search in (may be undefined if out of bounds)
552
+ * @param symbolName - The symbol to find
553
+ * @param orderHint - Which occurrence to find (0-based)
554
+ * @returns The character offset of the symbol, or null if not found
555
+ */
556
+ private findSymbolInLine;
557
+ /**
558
+ * Finds exact text in a file and returns its range.
559
+ * Used for search-and-replace operations.
560
+ *
561
+ * @param uri - The URI of the file
562
+ * @param searchText - The exact text to find
563
+ * @returns The range of the found text
564
+ * @throws Error if the text is not found or appears multiple times
565
+ */
566
+ findExactText(uri: UnifiedUri, searchText: string): Promise<DiskRange>;
567
+ /**
568
+ * Converts a character offset to a line/character position.
569
+ */
570
+ private offsetToPosition;
571
+ }
572
+
573
+ /**
574
+ * MCP Server Implementation for LSP Driver SDK
575
+ *
576
+ * The SDK automatically registers tools based on which capability providers
577
+ * are defined in the IdeCapabilities configuration.
578
+ */
579
+
580
+ /**
581
+ * Configuration options for the MCP LSP Driver.
582
+ */
583
+ interface McpLspDriverConfig {
584
+ /** Configuration for the symbol resolver */
585
+ resolverConfig?: ResolverConfig;
586
+ }
587
+ /**
588
+ * Register LSP-based tools and resources on the provided MCP server.
589
+ */
590
+ declare function installMcpLspDriver({ server, capabilities, config, }: {
591
+ server: McpServer;
592
+ capabilities: IdeCapabilities;
593
+ config?: McpLspDriverConfig;
594
+ }): {
595
+ success: boolean;
596
+ error: unknown;
597
+ reason: string;
598
+ } | {
599
+ success: boolean;
600
+ error?: undefined;
601
+ reason?: undefined;
602
+ };
603
+
604
+ export { type CodeSnippet, type ConnectLspPipeOptions, type DefinitionProvider, type Diagnostic, type DiagnosticSeverity, type DiagnosticsProvider, type DiskRange, type DocumentSymbol, type EditFailureReason, type EditProvider, type EditResult, type ExactPosition, type FileAccessProvider, type Frontmatter, type FrontmatterMatch, type FrontmatterProvider, type FrontmatterValue, type FuzzyPosition, type GlobalFindMatch, type GlobalFindOptions, type GlobalFindProvider, type GraphProvider, type HierarchyProvider, type IdeCapabilities, type Link, type LspPipeConnection, type LspPipeServer, type McpLspDriverConfig, type OnDiagnosticsChangedCallback, type OutlineProvider, type PendingEditOperation, type ReferencesProvider, type ResolverConfig, type ServeLspPipeOptions, type SymbolKind, SymbolResolutionError, SymbolResolver, type TextEdit, type UnifiedUri, connectLspPipe, installMcpLspDriver, serveLspPipe };
package/dist/index.d.ts CHANGED
@@ -468,6 +468,28 @@ interface IdeCapabilities {
468
468
  onDiagnosticsChanged?: (callback: OnDiagnosticsChangedCallback) => void;
469
469
  }
470
470
 
471
+ interface ConnectLspPipeOptions {
472
+ pipeName: string;
473
+ connectTimeout?: number;
474
+ }
475
+ interface LspPipeConnection {
476
+ readonly capabilities: IdeCapabilities;
477
+ readonly availableMethods: string[];
478
+ disconnect(): void;
479
+ }
480
+ declare function connectLspPipe(options: ConnectLspPipeOptions): Promise<LspPipeConnection>;
481
+
482
+ interface ServeLspPipeOptions {
483
+ capabilities: IdeCapabilities;
484
+ pipeName: string;
485
+ }
486
+ interface LspPipeServer {
487
+ readonly pipePath: string;
488
+ readonly connectionCount: number;
489
+ close(): Promise<void>;
490
+ }
491
+ declare function serveLspPipe(options: ServeLspPipeOptions): Promise<LspPipeServer>;
492
+
471
493
  /**
472
494
  * Smart Resolver Logic for MCP LSP Driver SDK
473
495
  *
@@ -579,4 +601,4 @@ declare function installMcpLspDriver({ server, capabilities, config, }: {
579
601
  reason?: undefined;
580
602
  };
581
603
 
582
- export { type CodeSnippet, type DefinitionProvider, type Diagnostic, type DiagnosticSeverity, type DiagnosticsProvider, type DiskRange, type DocumentSymbol, type EditFailureReason, type EditProvider, type EditResult, type ExactPosition, type FileAccessProvider, type Frontmatter, type FrontmatterMatch, type FrontmatterProvider, type FrontmatterValue, type FuzzyPosition, type GlobalFindMatch, type GlobalFindOptions, type GlobalFindProvider, type GraphProvider, type HierarchyProvider, type IdeCapabilities, type Link, type McpLspDriverConfig, type OnDiagnosticsChangedCallback, type OutlineProvider, type PendingEditOperation, type ReferencesProvider, type ResolverConfig, type SymbolKind, SymbolResolutionError, SymbolResolver, type TextEdit, type UnifiedUri, installMcpLspDriver };
604
+ export { type CodeSnippet, type ConnectLspPipeOptions, type DefinitionProvider, type Diagnostic, type DiagnosticSeverity, type DiagnosticsProvider, type DiskRange, type DocumentSymbol, type EditFailureReason, type EditProvider, type EditResult, type ExactPosition, type FileAccessProvider, type Frontmatter, type FrontmatterMatch, type FrontmatterProvider, type FrontmatterValue, type FuzzyPosition, type GlobalFindMatch, type GlobalFindOptions, type GlobalFindProvider, type GraphProvider, type HierarchyProvider, type IdeCapabilities, type Link, type LspPipeConnection, type LspPipeServer, type McpLspDriverConfig, type OnDiagnosticsChangedCallback, type OutlineProvider, type PendingEditOperation, type ReferencesProvider, type ResolverConfig, type ServeLspPipeOptions, type SymbolKind, SymbolResolutionError, SymbolResolver, type TextEdit, type UnifiedUri, connectLspPipe, installMcpLspDriver, serveLspPipe };
package/dist/index.js CHANGED
@@ -1,10 +1,15 @@
1
- import {ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {z as z$1}from'zod';var h=class extends Error{constructor(o,n,t){super(`Could not find symbol '${o}' at or near line ${n}. ${t}`);this.symbolName=o;this.lineHint=n;this.reason=t;this.name="SymbolResolutionError";}},b=class{constructor(e,o){this.fs=e;this.lineSearchRadius=o?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(e,o){let t=(await this.fs.readFile(e)).split(/\r?\n/),r=o.lineHint-1,i=o.orderHint??0,c=this.findSymbolInLine(t[r],o.symbolName,i);if(c!==null)return {line:r,character:c};for(let l=1;l<=this.lineSearchRadius;l++){let u=r-l;if(u>=0){let g=this.findSymbolInLine(t[u],o.symbolName,i);if(g!==null)return {line:u,character:g}}let m=r+l;if(m<t.length){let g=this.findSymbolInLine(t[m],o.symbolName,i);if(g!==null)return {line:m,character:g}}}throw new h(o.symbolName,o.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,o.lineHint-this.lineSearchRadius)} to ${Math.min(t.length,o.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(e,o,n){if(e===void 0||e.length===0)return null;let t=0,r=0;for(;t<e.length;){let i=e.indexOf(o,t);if(i===-1)break;if(r===n)return i;r++,t=i+1;}return null}async findExactText(e,o){let n=await this.fs.readFile(e),t=[],r=0;for(;r<n.length;){let m=n.indexOf(o,r);if(m===-1)break;t.push(m),r=m+1;}if(t.length===0)throw new Error(`Text not found in file: "${o.slice(0,50)}${o.length>50?"...":""}"`);if(t.length>1)throw new Error(`Text appears ${t.length} times in file. Please provide more context to uniquely identify the location.`);let i=t[0],c=i+o.length,l=this.offsetToPosition(n,i),u=this.offsetToPosition(n,c);return {start:l,end:u}}offsetToPosition(e,o){let n=0,t=0,r=0;for(let i of e){if(r===o)break;i===`
2
- `?(n++,t=0):t++,r++;}return {line:n,character:t}}};var f=s=>({content:[{type:"text",text:JSON.stringify(s??"")}],structuredContent:s});function p(s){if(s.includes(".."))throw new Error('URI could not include ".." operator');return s.replace(/\\/g,"/")}function R(){return `edit-${Date.now()}`}function w(s){return s.length===0?"No diagnostics found.":s.map(e=>{let o=e.range.start.line+1,n=e.severity.toUpperCase(),t=e.source?` [${e.source}]`:"",r=e.code!==void 0?` (${e.code})`:"";return `- **${n}**${t}${r} at line ${o}: ${e.message}`}).join(`
3
- `)}function k(s,e=0){if(s.length===0&&e===0)return "No symbols found.";let o=" ".repeat(e);return s.map(n=>{let t=n.range.start.line+1,r=n.range.end.line+1,i=t===r?`line ${t}`:`lines ${t}-${r}`,c=n.detail?` - ${n.detail}`:"",l=`${o}- **${n.kind}** \`${n.name}\`${c} (${i})`;return n.children&&n.children.length>0?`${l}
4
- ${k(n.children,e+1)}`:l}).join(`
5
- `)}var $=z$1.string().describe("The relative file path"),C=z$1.string().describe("The text of the symbol to find"),F=z$1.number().int().positive().describe("Approximate 1-based line number where the symbol is expected"),_=z$1.number().int().min(0).default(0).describe("0-based index of which occurrence to target if symbol appears multiple times"),T=z$1.object({uri:$,symbol_name:C,line_hint:F,order_hint:_}),x=z$1.object({uri:$,search_text:z$1.string().describe("Exact text to replace (must exist uniquely in the file)"),replace_text:z$1.string().describe("New text to insert"),description:z$1.string().describe("Rationale for the edit")}),I=z$1.object({uri:z$1.string().describe("The file URI or path"),symbol_name:C,line_hint:F,order_hint:_,direction:z$1.enum(["incoming","outgoing"]).describe("Direction of the call hierarchy")}),j=z$1.string().describe("The search query"),L=z$1.boolean().default(false).describe("Whether the search is case-sensitive"),D=z$1.boolean().default(false).describe("Whether to match exact words only"),M=z$1.boolean().default(false).describe("Whether the query is a regular expression"),O=z$1.object({query:j,case_sensitive:L,exact_match:D,regex_mode:M}),A=z$1.object({query:j,case_sensitive:L,exact_match:D,regex_mode:M,replace_with:z$1.string().describe("The replacement text")}),U=z$1.object({path:z$1.string().describe("The path to the document to modify"),pattern:z$1.string().describe("The text pattern to find and replace with a link"),link_to:z$1.string().describe("The target URI the link should point to")}),N=z$1.object({property:z$1.string().describe("The frontmatter property name to search for"),path:z$1.string().optional().describe("Optional path to limit the search to a specific document. If not provided, searches all documents.")}),z=z$1.object({path:z$1.string().describe("The path to the document to modify"),property:z$1.string().describe("The frontmatter property name to set"),value:z$1.union([z$1.string(),z$1.array(z$1.string()),z$1.number(),z$1.array(z$1.number()),z$1.boolean(),z$1.array(z$1.boolean()),z$1.null()]).describe("The value to set. Can be a string, number, boolean, array of these types, or null to remove.")});function H(s){if(!s)return null;let e=s.match(/^L(\d+)(?:-L(\d+))?$/);if(!e||!e[1])return null;let o=parseInt(e[1],10),n=e[2]?parseInt(e[2],10):o;return o<1||n<o?null:{start:o,end:n}}function J(s,e){let o=s.split(/\r?\n/),n=e.start-1,t=e.end;return o.slice(n,t).join(`
6
- `)}function W({server:s,capabilities:e,config:o}){let n=new b(e.fileAccess,o?.resolverConfig);try{q(s,e,n);}catch(t){return {success:false,error:t,reason:"Error occured during registration of tools"}}try{B(s,e);}catch(t){return {success:false,error:t,reason:"Error occured during registration of resources"}}return {success:true}}function q(s,e,o){e.definition&&K(s,e,o),e.references&&V(s,e,o),e.hierarchy&&Q(s,e,o),e.edit&&Z(s,e,o),e.globalFind&&(te(s,e),re(s,e)),e.graph&&(oe(s,e),ie(s,e)),e.frontmatter&&(se(s,e),ce(s,e));}function B(s,e){ee(s,e),e.diagnostics&&X(s,e),e.outline&&Y(s,e),e.graph&&ne(s,e),e.frontmatter&&ae(s,e);}function K(s,e,o){let n=e.definition;n&&s.registerTool("goto_definition",{description:"Navigate to the definition of a symbol.",inputSchema:T,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{try{let r=p(t.uri),i={symbolName:t.symbol_name,lineHint:t.line_hint,orderHint:t.order_hint},c=await o.resolvePosition(r,i),l=(await n.provideDefinition(r,c)).map(u=>({uri:u.uri,startLine:u.range.start.line+1,endLine:u.range.end.line+1,content:u.content}));return f({snippets:l})}catch(r){let i=r instanceof h?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:i}],structuredContent:{error:i},isError:true}}});}function V(s,e,o){let n=e.references;n&&s.registerTool("find_references",{description:"Find all references to a symbol. Returns a list of locations where the symbol is used.",inputSchema:T,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{try{let r=p(t.uri),i={symbolName:t.symbol_name,lineHint:t.line_hint,orderHint:t.order_hint},c=await o.resolvePosition(r,i),l=(await n.provideReferences(r,c)).map(u=>({uri:u.uri,startLine:u.range.start.line+1,endLine:u.range.end.line+1,content:u.content}));return f({snippets:l})}catch(r){let i=r instanceof h?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:i}],structuredContent:{error:i},isError:true}}});}function Q(s,e,o){let n=e.hierarchy;n&&s.registerTool("call_hierarchy",{description:"Get call hierarchy for a function or method. Shows incoming or outgoing calls.",inputSchema:I,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async t=>{try{let r=p(t.uri),i={symbolName:t.symbol_name,lineHint:t.line_hint,orderHint:t.order_hint},c=await o.resolvePosition(r,i),l=(await n.provideCallHierarchy(r,c,t.direction)).map(u=>({uri:u.uri,startLine:u.range.start.line+1,endLine:u.range.end.line+1,content:u.content}));return f({snippets:l})}catch(r){let i=r instanceof h?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:i}],structuredContent:{error:i},isError:true}}});}function X(s,e){let o=e.diagnostics;if(!o)return;let n=new ResourceTemplate("diagnostics://{+path}",{list:void 0});if(s.registerResource("file-diagnostics",n,{description:"Diagnostics (errors, warnings, hints) for a specific file. Use the file path after diagnostics://",mimeType:"text/markdown"},async(t,r)=>{try{let i=r.path,c=p(i),l=await o.provideDiagnostics(c),u=w(l);return {contents:[{uri:`diagnostics://${i}`,mimeType:"text/markdown",text:u}]}}catch(i){let c=`Error: ${i instanceof Error?i.message:String(i)}`;return {contents:[{uri:`diagnostics://${r.path}`,mimeType:"text/markdown",text:c}]}}}),o.getWorkspaceDiagnostics){let t=o.getWorkspaceDiagnostics.bind(o);s.registerResource("workspace-diagnostics","diagnostics://workspace",{description:"All diagnostics (errors, warnings, hints) across the entire workspace",mimeType:"text/markdown"},async()=>{try{let r=await t(),i=new Map;for(let l of r){let u=i.get(l.uri)??[];u.push(l),i.set(l.uri,u);}if(i.size===0)return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:"No diagnostics found in workspace."}]};let c=[];for(let[l,u]of i)c.push(`## ${l}
7
- ${w(u)}`);return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:c.join(`
1
+ import {connect,createServer}from'net';import {unlinkSync}from'fs';import {ResourceTemplate}from'@modelcontextprotocol/sdk/server/mcp.js';import {z as z$1}from'zod';var w=class{socket;requestHandler;notificationHandler;nextId=1;pending=new Map;buffer="";destroyed=false;constructor(e,t){this.socket=e,this.requestHandler=t?.onRequest,this.notificationHandler=t?.onNotification,e.on("data",i=>this.handleData(i)),e.on("close",()=>this.rejectAll(new Error("Connection closed"))),e.on("error",i=>this.rejectAll(i));}sendRequest(e,t){return this.destroyed?Promise.reject(new Error("Transport destroyed")):new Promise((i,n)=>{let r=this.nextId++;this.pending.set(r,{resolve:i,reject:n});let o={type:"request",id:r,method:e,params:t};this.socket.write(`${JSON.stringify(o)}
2
+ `);})}sendNotification(e,t){if(this.destroyed)return;let i={type:"notification",method:e,params:t};this.socket.write(`${JSON.stringify(i)}
3
+ `);}destroy(){this.destroyed||(this.destroyed=true,this.rejectAll(new Error("Transport destroyed")),this.socket.destroy());}handleData(e){this.buffer+=e.toString();let t=this.buffer.split(`
4
+ `);this.buffer=t.pop()??"";for(let i of t){let n=i.replace(/\r$/,"");if(n)try{let r=JSON.parse(n);this.dispatch(r);}catch{}}}dispatch(e){switch(e.type){case "response":{let t=this.pending.get(e.id);t&&(this.pending.delete(e.id),e.error?t.reject(new Error(e.error.message)):t.resolve(e.result));break}case "request":{this.requestHandler&&this.requestHandler(e.method,e.params).then(t=>{if(this.destroyed)return;let i={type:"response",id:e.id,result:t};this.socket.write(`${JSON.stringify(i)}
5
+ `);}).catch(t=>{if(this.destroyed)return;let i={type:"response",id:e.id,error:{message:t instanceof Error?t.message:String(t)}};this.socket.write(`${JSON.stringify(i)}
6
+ `);});break}case "notification":{this.notificationHandler?.(e.method,e.params);break}}}rejectAll(e){for(let[,t]of this.pending)t.reject(e);this.pending.clear();}};function T(s){return process.platform==="win32"?`\\\\.\\pipe\\${s}`:`/tmp/${s}.sock`}var R=[{providerKey:"fileAccess",methods:["readFile","readDirectory","getFileTree"]},{providerKey:"edit",methods:["applyEdits","previewAndApplyEdits"]},{providerKey:"definition",methods:["provideDefinition"]},{providerKey:"references",methods:["provideReferences"]},{providerKey:"hierarchy",methods:["provideCallHierarchy"]},{providerKey:"diagnostics",methods:["provideDiagnostics","getWorkspaceDiagnostics"]},{providerKey:"outline",methods:["provideDocumentSymbols"]},{providerKey:"globalFind",methods:["globalFind","globalReplace"]},{providerKey:"graph",methods:["getLinkStructure","resolveOutlinks","resolveBacklinks","addLink"]},{providerKey:"frontmatter",methods:["getFrontmatterStructure","getFrontmatter","setFrontmatter"]}];function Y(s){let{pipeName:e,connectTimeout:t=5e3}=s,i=T(e);return new Promise((n,r)=>{let o=connect(i),a=false,l=setTimeout(()=>{a||(a=true,o.destroy(),r(new Error(`Connection timeout after ${t}ms`)));},t);o.on("error",c=>{a||(a=true,clearTimeout(l),r(c));}),o.on("connect",()=>{if(clearTimeout(l),a)return;let c,u=new w(o,{onNotification:(f,h)=>{f==="onDiagnosticsChanged"&&c&&c(h[0]);}});u.sendRequest("_handshake",[]).then(f=>{if(a)return;let y=f.methods;if(!y.includes("fileAccess.readFile")||!y.includes("fileAccess.readDirectory"))throw u.destroy(),new Error("Server missing required methods: fileAccess.readFile, fileAccess.readDirectory");let v={};for(let{providerKey:b,methods:C}of R){let L=C.filter(E=>y.includes(`${b}.${E}`));if(L.length===0)continue;let _={};for(let E of L)_[E]=(...Q)=>u.sendRequest(`${b}.${E}`,Q);v[b]=_;}y.includes("onDiagnosticsChanged")&&(v.onDiagnosticsChanged=b=>{c=b;}),a=true,n({capabilities:v,availableMethods:y,disconnect(){u.destroy();}});}).catch(f=>{a||(a=true,u.destroy(),r(f instanceof Error?f:new Error(String(f))));});});})}function ee(s){let{capabilities:e,pipeName:t}=s,i=T(t),n=new Map;for(let{providerKey:l,methods:c}of R){let u=e[l];if(u)for(let f of c){let h=u[f];if(typeof h=="function"){let y=`${l}.${f}`;n.set(y,(...v)=>h.apply(u,v));}}}let r=[...n.keys()];e.onDiagnosticsChanged&&r.push("onDiagnosticsChanged");let o=new Set,a=createServer(l=>{let c=new w(l,{onRequest:async(u,f)=>{if(u==="_handshake")return {methods:r};let h=n.get(u);if(!h)throw new Error(`Unknown method: ${u}`);return h(...f)}});o.add(c),l.on("close",()=>o.delete(c));});return e.onDiagnosticsChanged&&e.onDiagnosticsChanged(l=>{for(let c of o)c.sendNotification("onDiagnosticsChanged",[l]);}),new Promise((l,c)=>{if(process.platform!=="win32")try{unlinkSync(i);}catch{}a.on("error",c),a.listen(i,()=>{a.removeListener("error",c),l({get pipePath(){return i},get connectionCount(){return o.size},async close(){for(let u of o)u.destroy();if(o.clear(),await new Promise((u,f)=>{a.close(h=>{h?f(h):u();});}),process.platform!=="win32")try{unlinkSync(i);}catch{}}});});})}var x=class extends Error{constructor(t,i,n){super(`Could not find symbol '${t}' at or near line ${i}. ${n}`);this.symbolName=t;this.lineHint=i;this.reason=n;this.name="SymbolResolutionError";}},k=class{constructor(e,t){this.fs=e;this.lineSearchRadius=t?.lineSearchRadius??2;}lineSearchRadius;async resolvePosition(e,t){let n=(await this.fs.readFile(e)).split(/\r?\n/),r=t.lineHint-1,o=t.orderHint??0,a=this.findSymbolInLine(n[r],t.symbolName,o);if(a!==null)return {line:r,character:a};for(let l=1;l<=this.lineSearchRadius;l++){let c=r-l;if(c>=0){let f=this.findSymbolInLine(n[c],t.symbolName,o);if(f!==null)return {line:c,character:f}}let u=r+l;if(u<n.length){let f=this.findSymbolInLine(n[u],t.symbolName,o);if(f!==null)return {line:u,character:f}}}throw new x(t.symbolName,t.lineHint,`Please verify the file content and try again. Searched lines ${Math.max(1,t.lineHint-this.lineSearchRadius)} to ${Math.min(n.length,t.lineHint+this.lineSearchRadius)}.`)}findSymbolInLine(e,t,i){if(e===void 0||e.length===0)return null;let n=0,r=0;for(;n<e.length;){let o=e.indexOf(t,n);if(o===-1)break;if(r===i)return o;r++,n=o+1;}return null}async findExactText(e,t){let i=await this.fs.readFile(e),n=[],r=0;for(;r<i.length;){let u=i.indexOf(t,r);if(u===-1)break;n.push(u),r=u+1;}if(n.length===0)throw new Error(`Text not found in file: "${t.slice(0,50)}${t.length>50?"...":""}"`);if(n.length>1)throw new Error(`Text appears ${n.length} times in file. Please provide more context to uniquely identify the location.`);let o=n[0],a=o+t.length,l=this.offsetToPosition(i,o),c=this.offsetToPosition(i,a);return {start:l,end:c}}offsetToPosition(e,t){let i=0,n=0,r=0;for(let o of e){if(r===t)break;o===`
7
+ `?(i++,n=0):n++,r++;}return {line:i,character:n}}};var g=s=>({content:[{type:"text",text:JSON.stringify(s??"")}],structuredContent:s});function m(s){if(s.includes(".."))throw new Error('URI could not include ".." operator');return s.replace(/\\/g,"/")}function M(){return `edit-${Date.now()}`}function $(s){return s.length===0?"No diagnostics found.":s.map(e=>{let t=e.range.start.line+1,i=e.severity.toUpperCase(),n=e.source?` [${e.source}]`:"",r=e.code!==void 0?` (${e.code})`:"";return `- **${i}**${n}${r} at line ${t}: ${e.message}`}).join(`
8
+ `)}function D(s,e=0){if(s.length===0&&e===0)return "No symbols found.";let t=" ".repeat(e);return s.map(i=>{let n=i.range.start.line+1,r=i.range.end.line+1,o=n===r?`line ${n}`:`lines ${n}-${r}`,a=i.detail?` - ${i.detail}`:"",l=`${t}- **${i.kind}** \`${i.name}\`${a} (${o})`;return i.children&&i.children.length>0?`${l}
9
+ ${D(i.children,e+1)}`:l}).join(`
10
+ `)}var j=z$1.string().describe("The relative file path"),O=z$1.string().describe("The text of the symbol to find"),N=z$1.number().int().positive().describe("Approximate 1-based line number where the symbol is expected"),A=z$1.number().int().min(0).default(0).describe("0-based index of which occurrence to target if symbol appears multiple times"),F=z$1.object({uri:j,symbol_name:O,line_hint:N,order_hint:A}),P=z$1.object({uri:j,search_text:z$1.string().describe("Exact text to replace (must exist uniquely in the file)"),replace_text:z$1.string().describe("New text to insert"),description:z$1.string().describe("Rationale for the edit")}),H=z$1.object({uri:z$1.string().describe("The file URI or path"),symbol_name:O,line_hint:N,order_hint:A,direction:z$1.enum(["incoming","outgoing"]).describe("Direction of the call hierarchy")}),U=z$1.string().describe("The search query"),q=z$1.boolean().default(false).describe("Whether the search is case-sensitive"),z=z$1.boolean().default(false).describe("Whether to match exact words only"),K=z$1.boolean().default(false).describe("Whether the query is a regular expression"),G=z$1.object({query:U,case_sensitive:q,exact_match:z,regex_mode:K}),J=z$1.object({query:U,case_sensitive:q,exact_match:z,regex_mode:K,replace_with:z$1.string().describe("The replacement text")}),W=z$1.object({path:z$1.string().describe("The path to the document to modify"),pattern:z$1.string().describe("The text pattern to find and replace with a link"),link_to:z$1.string().describe("The target URI the link should point to")}),B=z$1.object({property:z$1.string().describe("The frontmatter property name to search for"),path:z$1.string().optional().describe("Optional path to limit the search to a specific document. If not provided, searches all documents.")}),V=z$1.object({path:z$1.string().describe("The path to the document to modify"),property:z$1.string().describe("The frontmatter property name to set"),value:z$1.union([z$1.string(),z$1.array(z$1.string()),z$1.number(),z$1.array(z$1.number()),z$1.boolean(),z$1.array(z$1.boolean()),z$1.null()]).describe("The value to set. Can be a string, number, boolean, array of these types, or null to remove.")});function te(s){if(!s)return null;let e=s.match(/^L(\d+)(?:-L(\d+))?$/);if(!e||!e[1])return null;let t=parseInt(e[1],10),i=e[2]?parseInt(e[2],10):t;return t<1||i<t?null:{start:t,end:i}}function re(s,e){let t=s.split(/\r?\n/),i=e.start-1,n=e.end;return t.slice(i,n).join(`
11
+ `)}function ne({server:s,capabilities:e,config:t}){let i=new k(e.fileAccess,t?.resolverConfig);try{ie(s,e,i);}catch(n){return {success:false,error:n,reason:"Error occured during registration of tools"}}try{oe(s,e);}catch(n){return {success:false,error:n,reason:"Error occured during registration of resources"}}return {success:true}}function ie(s,e,t){e.definition&&se(s,e,t),e.references&&ae(s,e,t),e.hierarchy&&ce(s,e,t),e.edit&&pe(s,e,t),e.globalFind&&(fe(s,e),me(s,e)),e.graph&&(ge(s,e),ye(s,e)),e.frontmatter&&(be(s,e),ve(s,e));}function oe(s,e){ue(s,e),e.diagnostics&&le(s,e),e.outline&&de(s,e),e.graph&&he(s,e),e.frontmatter&&xe(s,e);}function se(s,e,t){let i=e.definition;i&&s.registerTool("goto_definition",{description:"Navigate to the definition of a symbol.",inputSchema:F,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async n=>{try{let r=m(n.uri),o={symbolName:n.symbol_name,lineHint:n.line_hint,orderHint:n.order_hint},a=await t.resolvePosition(r,o),l=(await i.provideDefinition(r,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return g({snippets:l})}catch(r){let o=r instanceof x?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function ae(s,e,t){let i=e.references;i&&s.registerTool("find_references",{description:"Find all references to a symbol. Returns a list of locations where the symbol is used.",inputSchema:F,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async n=>{try{let r=m(n.uri),o={symbolName:n.symbol_name,lineHint:n.line_hint,orderHint:n.order_hint},a=await t.resolvePosition(r,o),l=(await i.provideReferences(r,a)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return g({snippets:l})}catch(r){let o=r instanceof x?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function ce(s,e,t){let i=e.hierarchy;i&&s.registerTool("call_hierarchy",{description:"Get call hierarchy for a function or method. Shows incoming or outgoing calls.",inputSchema:H,outputSchema:{snippets:z$1.array(z$1.object({uri:z$1.string(),startLine:z$1.number(),endLine:z$1.number(),content:z$1.string()}))}},async n=>{try{let r=m(n.uri),o={symbolName:n.symbol_name,lineHint:n.line_hint,orderHint:n.order_hint},a=await t.resolvePosition(r,o),l=(await i.provideCallHierarchy(r,a,n.direction)).map(c=>({uri:c.uri,startLine:c.range.start.line+1,endLine:c.range.end.line+1,content:c.content}));return g({snippets:l})}catch(r){let o=r instanceof x?r.message:`Error: ${r instanceof Error?r.message:String(r)}`;return {content:[{type:"text",text:o}],structuredContent:{error:o},isError:true}}});}function le(s,e){let t=e.diagnostics;if(!t)return;let i=new ResourceTemplate("diagnostics://{+path}",{list:void 0});if(s.registerResource("diagnostics",i,{description:"Diagnostics (errors, warnings, hints) for a specific file. Use the file path after diagnostics://",mimeType:"text/markdown"},async(n,r)=>{try{let o=r.path,a=m(o),l=await t.provideDiagnostics(a),c=$(l);return {contents:[{uri:`diagnostics://${o}`,mimeType:"text/markdown",text:c}]}}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`diagnostics://${r.path}`,mimeType:"text/markdown",text:a}]}}}),t.getWorkspaceDiagnostics){let n=t.getWorkspaceDiagnostics.bind(t);s.registerResource("workspace-diagnostics","diagnostics://workspace",{description:"All diagnostics (errors, warnings, hints) across the entire workspace",mimeType:"text/markdown"},async()=>{try{let r=await n(),o=new Map;for(let l of r){let c=o.get(l.uri)??[];c.push(l),o.set(l.uri,c);}if(o.size===0)return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:"No diagnostics found in workspace."}]};let a=[];for(let[l,c]of o)a.push(`## ${l}
12
+ ${$(c)}`);return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:a.join(`
8
13
 
9
- `)}]}}catch(r){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${r instanceof Error?r.message:String(r)}`}]}}});}e.onDiagnosticsChanged&&e.onDiagnosticsChanged(t=>{let r=p(t);s.server.sendResourceUpdated({uri:`diagnostics://${r}`}),o.getWorkspaceDiagnostics&&s.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function Y(s,e){let o=e.outline;if(!o)return;let n=new ResourceTemplate("outline://{+path}",{list:void 0});s.registerResource("file-outline",n,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(t,r)=>{try{let i=r.path,c=p(i),l=await o.provideDocumentSymbols(c),u=k(l);return {contents:[{uri:`outline://${i}`,mimeType:"text/markdown",text:u}]}}catch(i){let c=`Error: ${i instanceof Error?i.message:String(i)}`;return {contents:[{uri:`outline://${r.path}`,mimeType:"text/markdown",text:c}]}}});}function Z(s,e,o){let n=e.edit;if(!n)return;let t=n.previewAndApplyEdits?.bind(n)??n.applyEdits?.bind(n);t&&s.registerTool("apply_edit",{description:"Apply a text edit to a file. The edit must be approved by the user before being applied.",inputSchema:{uri:x.shape.uri,search_text:x.shape.search_text,replace_text:x.shape.replace_text,description:x.shape.description},outputSchema:{success:z$1.boolean(),message:z$1.string()}},async r=>{try{let i=p(r.uri),c=await o.findExactText(i,r.search_text),l={id:R(),uri:i,edits:[{range:c,newText:r.replace_text}],description:r.description},m=await t(l)?{success:!0,message:"Edit successfully applied and saved."}:{success:!1,message:"Edit rejected by user."};return f(m)}catch(i){let c=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:c}],structuredContent:{success:false,message:c},isError:true}}});}function ee(s,e){let{readFile:o,readDirectory:n,getFileTree:t}=e.fileAccess;if(t!==void 0){let i=new ResourceTemplate("filetree://{+path}",{list:void 0});s.registerResource("fileTree",i,{description:'Access file tree inside a relative path or use "." for root.'},async(c,{path:l})=>({contents:[{uri:c.toString(),mimeType:"application/json",text:JSON.stringify(await t(p(l))??"")}]}));}let r=new ResourceTemplate("files://{+path}",{list:void 0});s.registerResource("filesystem",r,{description:"Access filesystem resources. For directories: returns children (git-ignored files excluded). For files: returns file content. Supports line ranges with #L23 or #L23-L30 fragment."},async(i,c)=>{let l=i.toString();try{let u=c.path,m,g=u,v=u.indexOf("#");v!==-1&&(m=u.slice(v+1),g=u.slice(0,v));let E=p(g),P=H(m);try{let S=await o(E),G=P?J(S,P):S;return {contents:[{uri:l,mimeType:"text/plain",text:G}]}}catch{let S=await n(E);return {contents:[{uri:l,mimeType:"application/json",text:JSON.stringify(S)}]}}}catch(u){let m=`Error: ${u instanceof Error?u.message:String(u)}`;return {contents:[{uri:l,mimeType:"text/plain",text:m}]}}});}function te(s,e){let o=e.globalFind;o&&s.registerTool("global_find",{description:"Search for text across the entire workspace.",inputSchema:O,outputSchema:{matches:z$1.array(z$1.object({uri:z$1.string(),line:z$1.number(),column:z$1.number(),matchText:z$1.string(),context:z$1.string()})),count:z$1.number()}},async n=>{try{let t=n.case_sensitive??!1,r=n.exact_match??!1,i=n.regex_mode??!1,c=await o.globalFind(n.query,{caseSensitive:t,exactMatch:r,regexMode:i});return f({count:c.length,matches:c})}catch(t){let r=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:r}],structuredContent:{error:r},isError:true}}});}function re(s,e){let o=e.globalFind;o&&s.registerTool("global_replace",{description:"Replace all occurrences of text across the entire workspace.",inputSchema:A,outputSchema:{success:z$1.boolean(),count:z$1.number(),message:z$1.string().optional()}},async n=>{try{let t=n.case_sensitive??!1,r=n.exact_match??!1,i=n.regex_mode??!1,c=await o.globalReplace(n.query,n.replace_with,{caseSensitive:t,exactMatch:r,regexMode:i});return f({success:!0,count:c})}catch(t){let r=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,replacementCount:0,message:r},isError:true}}});}function ne(s,e){let o=e.graph;if(!o)return;let n=new ResourceTemplate("outlinks://{+path}",{list:void 0});s.registerResource("outlinks",n,{description:"Outgoing links from a specific file. Use the file path after outlinks://",mimeType:"application/json"},async(r,i)=>{try{let c=i.path,l=p(c),u=await o.resolveOutlinks(l);return {contents:[{uri:`outlinks://${c}`,mimeType:"application/json",text:JSON.stringify(u,null,2)}]}}catch(c){let l=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:`outlinks://${i.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});let t=new ResourceTemplate("backlinks://{+path}",{list:void 0});s.registerResource("backlinks",t,{description:"Incoming links (backlinks) to a specific file. Use the file path after backlinks://",mimeType:"application/json"},async(r,i)=>{try{let c=i.path,l=p(c),u=await o.resolveBacklinks(l);return {contents:[{uri:`backlinks://${c}`,mimeType:"application/json",text:JSON.stringify(u,null,2)}]}}catch(c){let l=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:`backlinks://${i.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});}function oe(s,e){let o=e.graph;o&&s.registerTool("get_link_structure",{description:"Get all links in the workspace, showing relationships between documents.",inputSchema:{},outputSchema:{links:z$1.array(z$1.object({sourceUri:z$1.string(),targetUri:z$1.string(),subpath:z$1.string().optional(),displayText:z$1.string().optional(),resolved:z$1.boolean(),line:z$1.number(),column:z$1.number()}))}},async()=>{try{let n=await o.getLinkStructure();return f({links:n})}catch(n){let t=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:t}],structuredContent:{error:t},isError:true}}});}function ie(s,e){let o=e.graph;o&&s.registerTool("add_link",{description:"Add a link to a document by finding a text pattern and replacing it with a link to the target.",inputSchema:U,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async n=>{try{let t=p(n.path),r=p(n.link_to);return await o.addLink(t,n.pattern,r),f({success:!0,message:"Link added successfully."})}catch(t){let r=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,message:r},isError:true}}});}function se(s,e){let o=e.frontmatter;o&&s.registerTool("get_frontmatter_structure",{description:"Get frontmatter property values across documents. If path is provided, searches only that document. Otherwise, searches all documents.",inputSchema:N,outputSchema:{matches:z$1.array(z$1.object({path:z$1.string(),value:z$1.unknown()}))}},async n=>{try{let t=n.path?p(n.path):void 0,r=await o.getFrontmatterStructure(n.property,t);return f({matches:r})}catch(t){let r=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:r}],structuredContent:{error:r},isError:true}}});}function ce(s,e){let o=e.frontmatter;o&&s.registerTool("set_frontmatter",{description:"Set a frontmatter property on a document. Use null to remove the property.",inputSchema:z,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async n=>{try{let t=p(n.path),r=n.value===null?void 0:n.value;return await o.setFrontmatter(t,n.property,r),f({success:!0,message:"Frontmatter updated successfully."})}catch(t){let r=`Error: ${t instanceof Error?t.message:String(t)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,message:r},isError:true}}});}function ae(s,e){let o=e.frontmatter;if(!o)return;let n=new ResourceTemplate("frontmatter://{+path}",{list:void 0});s.registerResource("frontmatter",n,{description:"Frontmatter metadata for a specific file. Use the file path after frontmatter://",mimeType:"application/json"},async(t,r)=>{try{let i=r.path,c=p(i),l=await o.getFrontmatter(c);return {contents:[{uri:`frontmatter://${i}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(i){let c=`Error: ${i instanceof Error?i.message:String(i)}`;return {contents:[{uri:`frontmatter://${r.path}`,mimeType:"application/json",text:JSON.stringify({error:c})}]}}});}
10
- export{h as SymbolResolutionError,b as SymbolResolver,W as installMcpLspDriver};
14
+ `)}]}}catch(r){return {contents:[{uri:"diagnostics://workspace",mimeType:"text/markdown",text:`Error: ${r instanceof Error?r.message:String(r)}`}]}}});}e.onDiagnosticsChanged&&e.onDiagnosticsChanged(n=>{let r=m(n);s.server.sendResourceUpdated({uri:`diagnostics://${r}`}),t.getWorkspaceDiagnostics&&s.server.sendResourceUpdated({uri:"diagnostics://workspace"});});}function de(s,e){let t=e.outline;if(!t)return;let i=new ResourceTemplate("outline://{+path}",{list:void 0});s.registerResource("outline",i,{description:"Document outline (symbols like classes, functions, variables) for a specific file. Use the file path after outline://",mimeType:"text/markdown"},async(n,r)=>{try{let o=r.path,a=m(o),l=await t.provideDocumentSymbols(a),c=D(l);return {contents:[{uri:`outline://${o}`,mimeType:"text/markdown",text:c}]}}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`outline://${r.path}`,mimeType:"text/markdown",text:a}]}}});}function pe(s,e,t){let i=e.edit;if(!i)return;let n=i.previewAndApplyEdits?.bind(i)??i.applyEdits?.bind(i);n&&s.registerTool("apply_edit",{description:"Apply a text edit to a file. The edit must be approved by the user before being applied.",inputSchema:{uri:P.shape.uri,search_text:P.shape.search_text,replace_text:P.shape.replace_text,description:P.shape.description},outputSchema:{success:z$1.boolean(),message:z$1.string()}},async r=>{try{let o=m(r.uri),a=await t.findExactText(o,r.search_text),l={id:M(),uri:o,edits:[{range:a,newText:r.replace_text}],description:r.description},u=await n(l)?{success:!0,message:"Edit successfully applied and saved."}:{success:!1,message:"Edit rejected by user."};return g(u)}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {content:[{type:"text",text:a}],structuredContent:{success:false,message:a},isError:true}}});}function ue(s,e){let{readFile:t,readDirectory:i,getFileTree:n}=e.fileAccess;if(n!==void 0){let o=new ResourceTemplate("filetree://{+path}",{list:void 0});s.registerResource("filetree",o,{description:'Access file tree inside a relative path or use "." for root.'},async(a,{path:l})=>({contents:[{uri:a.toString(),mimeType:"application/json",text:JSON.stringify(await n(m(l))??"")}]}));}let r=new ResourceTemplate("files://{+path}",{list:void 0});s.registerResource("filesystem",r,{description:"Access filesystem resources. For directories: returns children (git-ignored files excluded). For files: returns file content. Supports line ranges with #L23 or #L23-L30 fragment."},async(o,a)=>{let l=o.toString();try{let c=a.path,u,f=c,h=c.indexOf("#");h!==-1&&(u=c.slice(h+1),f=c.slice(0,h));let y=m(f),v=te(u);try{let b=await t(y),C=v?re(b,v):b;return {contents:[{uri:l,mimeType:"text/plain",text:C}]}}catch{let b=await i(y);return {contents:[{uri:l,mimeType:"application/json",text:JSON.stringify(b)}]}}}catch(c){let u=`Error: ${c instanceof Error?c.message:String(c)}`;return {contents:[{uri:l,mimeType:"text/plain",text:u}]}}});}function fe(s,e){let t=e.globalFind;t&&s.registerTool("global_find",{description:"Search for text across the entire workspace.",inputSchema:G,outputSchema:{matches:z$1.array(z$1.object({uri:z$1.string(),line:z$1.number(),column:z$1.number(),matchText:z$1.string(),context:z$1.string()})),count:z$1.number()}},async i=>{try{let n=i.case_sensitive??!1,r=i.exact_match??!1,o=i.regex_mode??!1,a=await t.globalFind(i.query,{caseSensitive:n,exactMatch:r,regexMode:o});return g({count:a.length,matches:a})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{error:r},isError:true}}});}function me(s,e){let t=e.globalFind;t&&s.registerTool("global_replace",{description:"Replace all occurrences of text across the entire workspace.",inputSchema:J,outputSchema:{success:z$1.boolean(),count:z$1.number(),message:z$1.string().optional()}},async i=>{try{let n=i.case_sensitive??!1,r=i.exact_match??!1,o=i.regex_mode??!1,a=await t.globalReplace(i.query,i.replace_with,{caseSensitive:n,exactMatch:r,regexMode:o});return g({success:!0,count:a})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,replacementCount:0,message:r},isError:true}}});}function he(s,e){let t=e.graph;if(!t)return;let i=new ResourceTemplate("outlinks://{+path}",{list:void 0});s.registerResource("outlinks",i,{description:"Outgoing links from a specific file. Use the file path after outlinks://",mimeType:"application/json"},async(r,o)=>{try{let a=o.path,l=m(a),c=await t.resolveOutlinks(l);return {contents:[{uri:`outlinks://${a}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(a){let l=`Error: ${a instanceof Error?a.message:String(a)}`;return {contents:[{uri:`outlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});let n=new ResourceTemplate("backlinks://{+path}",{list:void 0});s.registerResource("backlinks",n,{description:"Incoming links (backlinks) to a specific file. Use the file path after backlinks://",mimeType:"application/json"},async(r,o)=>{try{let a=o.path,l=m(a),c=await t.resolveBacklinks(l);return {contents:[{uri:`backlinks://${a}`,mimeType:"application/json",text:JSON.stringify(c,null,2)}]}}catch(a){let l=`Error: ${a instanceof Error?a.message:String(a)}`;return {contents:[{uri:`backlinks://${o.path}`,mimeType:"application/json",text:JSON.stringify({error:l})}]}}});}function ge(s,e){let t=e.graph;t&&s.registerTool("get_link_structure",{description:"Get all links in the workspace, showing relationships between documents.",inputSchema:{},outputSchema:{links:z$1.array(z$1.object({sourceUri:z$1.string(),targetUri:z$1.string(),subpath:z$1.string().optional(),displayText:z$1.string().optional(),resolved:z$1.boolean(),line:z$1.number(),column:z$1.number()}))}},async()=>{try{let i=await t.getLinkStructure();return g({links:i})}catch(i){let n=`Error: ${i instanceof Error?i.message:String(i)}`;return {content:[{type:"text",text:n}],structuredContent:{error:n},isError:true}}});}function ye(s,e){let t=e.graph;t&&s.registerTool("add_link",{description:"Add a link to a document by finding a text pattern and replacing it with a link to the target.",inputSchema:W,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async i=>{try{let n=m(i.path),r=m(i.link_to);return await t.addLink(n,i.pattern,r),g({success:!0,message:"Link added successfully."})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,message:r},isError:true}}});}function be(s,e){let t=e.frontmatter;t&&s.registerTool("get_frontmatter_structure",{description:"Get frontmatter property values across documents. If path is provided, searches only that document. Otherwise, searches all documents.",inputSchema:B,outputSchema:{matches:z$1.array(z$1.object({path:z$1.string(),value:z$1.unknown()}))}},async i=>{try{let n=i.path?m(i.path):void 0,r=await t.getFrontmatterStructure(i.property,n);return g({matches:r})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{error:r},isError:true}}});}function ve(s,e){let t=e.frontmatter;t&&s.registerTool("set_frontmatter",{description:"Set a frontmatter property on a document. Use null to remove the property.",inputSchema:V,outputSchema:{success:z$1.boolean(),message:z$1.string().optional()}},async i=>{try{let n=m(i.path),r=i.value===null?void 0:i.value;return await t.setFrontmatter(n,i.property,r),g({success:!0,message:"Frontmatter updated successfully."})}catch(n){let r=`Error: ${n instanceof Error?n.message:String(n)}`;return {content:[{type:"text",text:r}],structuredContent:{success:false,message:r},isError:true}}});}function xe(s,e){let t=e.frontmatter;if(!t)return;let i=new ResourceTemplate("frontmatter://{+path}",{list:void 0});s.registerResource("frontmatter",i,{description:"Frontmatter metadata for a specific file. Use the file path after frontmatter://",mimeType:"application/json"},async(n,r)=>{try{let o=r.path,a=m(o),l=await t.getFrontmatter(a);return {contents:[{uri:`frontmatter://${o}`,mimeType:"application/json",text:JSON.stringify(l,null,2)}]}}catch(o){let a=`Error: ${o instanceof Error?o.message:String(o)}`;return {contents:[{uri:`frontmatter://${r.path}`,mimeType:"application/json",text:JSON.stringify({error:a})}]}}});}
15
+ export{x as SymbolResolutionError,k as SymbolResolver,Y as connectLspPipe,ne as installMcpLspDriver,ee as serveLspPipe};
package/package.json CHANGED
@@ -1,19 +1,27 @@
1
1
  {
2
2
  "name": "mcp-lsp-driver",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "MCP LSP Driver for IDE plugins to easily expose LSP features via an MCP server.",
5
5
  "type": "module",
6
- "main": "dist/index.js",
6
+ "main": "dist/index.cjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "import": "./dist/index.js",
11
- "types": "./dist/index.d.ts"
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
12
18
  }
13
19
  },
14
20
  "files": [
15
21
  "dist/**/*.js",
22
+ "dist/**/*.cjs",
16
23
  "dist/**/*.d.ts",
24
+ "dist/**/*.d.cts",
17
25
  "LICENSE"
18
26
  ],
19
27
  "keywords": [