Merge branch 'svelte-support'
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
|
||||
**30% fewer tokens • 25% fewer tool calls • 100% local**
|
||||
|
||||
**Works on Windows, macOS, and Linux**
|
||||
|
||||
[](https://www.npmjs.com/package/@colbymchenry/codegraph)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://nodejs.org/)
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@colbymchenry/codegraph",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@colbymchenry/codegraph",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.3",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@colbymchenry/codegraph",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.3",
|
||||
"description": "Supercharge Claude Code with semantic code intelligence. 30% fewer tokens, 25% fewer tool calls, 100% local.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
+59
-28
@@ -15,6 +15,7 @@
|
||||
* ```
|
||||
*/
|
||||
|
||||
import * as path from 'path';
|
||||
import CodeGraph, { findNearestCodeGraphRoot } from '../index';
|
||||
import { StdioTransport, JsonRpcRequest, JsonRpcNotification, ErrorCodes } from './transport';
|
||||
import { tools, ToolHandler } from './tools';
|
||||
@@ -22,6 +23,25 @@ import { initSentry, captureException } from '../sentry';
|
||||
|
||||
initSentry({ processName: 'codegraph-mcp' });
|
||||
|
||||
/**
|
||||
* Convert a file:// URI to a filesystem path.
|
||||
* Handles URL encoding and Windows drive letter paths.
|
||||
*/
|
||||
function fileUriToPath(uri: string): string {
|
||||
try {
|
||||
const url = new URL(uri);
|
||||
let filePath = decodeURIComponent(url.pathname);
|
||||
// On Windows, file:///C:/path produces pathname /C:/path — strip leading /
|
||||
if (process.platform === 'win32' && /^\/[a-zA-Z]:/.test(filePath)) {
|
||||
filePath = filePath.slice(1);
|
||||
}
|
||||
return path.resolve(filePath);
|
||||
} catch {
|
||||
// Fallback for non-standard URIs
|
||||
return uri.replace(/^file:\/\/\/?/, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MCP Server Info
|
||||
*/
|
||||
@@ -44,13 +64,14 @@ const PROTOCOL_VERSION = '2024-11-05';
|
||||
export class MCPServer {
|
||||
private transport: StdioTransport;
|
||||
private cg: CodeGraph | null = null;
|
||||
private toolHandler: ToolHandler | null = null;
|
||||
private toolHandler: ToolHandler;
|
||||
private projectPath: string | null;
|
||||
private initError: string | null = null;
|
||||
|
||||
constructor(projectPath?: string) {
|
||||
this.projectPath = projectPath || null;
|
||||
this.transport = new StdioTransport();
|
||||
// Create ToolHandler eagerly — cross-project queries work even without a default project
|
||||
this.toolHandler = new ToolHandler(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,18 +91,21 @@ export class MCPServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize CodeGraph for the project
|
||||
* Try to initialize CodeGraph for the default project.
|
||||
*
|
||||
* Walks up parent directories to find the nearest .codegraph/ folder,
|
||||
* similar to how git finds .git/ directories.
|
||||
*
|
||||
* If initialization fails, the error is recorded but the server continues
|
||||
* to work — cross-project queries and retries on subsequent tool calls
|
||||
* are still possible.
|
||||
*/
|
||||
private async initializeCodeGraph(projectPath: string): Promise<void> {
|
||||
private async tryInitializeDefault(projectPath: string): Promise<void> {
|
||||
// Walk up parent directories to find nearest .codegraph/
|
||||
const resolvedRoot = findNearestCodeGraphRoot(projectPath);
|
||||
|
||||
if (!resolvedRoot) {
|
||||
this.projectPath = projectPath;
|
||||
this.initError = `CodeGraph not initialized in ${projectPath}. Run 'codegraph init' first.`;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,11 +113,31 @@ export class MCPServer {
|
||||
|
||||
try {
|
||||
this.cg = await CodeGraph.open(resolvedRoot);
|
||||
this.toolHandler = new ToolHandler(this.cg);
|
||||
this.initError = null;
|
||||
this.toolHandler.setDefaultCodeGraph(this.cg);
|
||||
} catch (err) {
|
||||
captureException(err);
|
||||
this.initError = `Failed to open CodeGraph: ${err instanceof Error ? err.message : String(err)}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retry initialization of the default project if it previously failed.
|
||||
* Called lazily on tool calls that need the default project.
|
||||
*/
|
||||
private retryInitIfNeeded(): void {
|
||||
// Already initialized successfully
|
||||
if (this.toolHandler.hasDefaultCodeGraph()) return;
|
||||
// No project path to retry with
|
||||
if (!this.projectPath) return;
|
||||
|
||||
const resolvedRoot = findNearestCodeGraphRoot(this.projectPath);
|
||||
if (!resolvedRoot) return;
|
||||
|
||||
try {
|
||||
this.cg = CodeGraph.openSync(resolvedRoot);
|
||||
this.projectPath = resolvedRoot;
|
||||
this.toolHandler.setDefaultCodeGraph(this.cg);
|
||||
} catch {
|
||||
// Still failing — will retry on next tool call
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +146,7 @@ export class MCPServer {
|
||||
*/
|
||||
stop(): void {
|
||||
// Close all cached cross-project connections first
|
||||
if (this.toolHandler) {
|
||||
this.toolHandler.closeAll();
|
||||
}
|
||||
// Close the main CodeGraph instance
|
||||
if (this.cg) {
|
||||
this.cg.close();
|
||||
@@ -175,10 +217,9 @@ export class MCPServer {
|
||||
let projectPath = this.projectPath;
|
||||
|
||||
if (params?.rootUri) {
|
||||
// Convert file:// URI to path
|
||||
projectPath = params.rootUri.replace(/^file:\/\//, '');
|
||||
projectPath = fileUriToPath(params.rootUri);
|
||||
} else if (params?.workspaceFolders?.[0]?.uri) {
|
||||
projectPath = params.workspaceFolders[0].uri.replace(/^file:\/\//, '');
|
||||
projectPath = fileUriToPath(params.workspaceFolders[0].uri);
|
||||
}
|
||||
|
||||
// Fall back to current working directory if no path provided
|
||||
@@ -186,8 +227,8 @@ export class MCPServer {
|
||||
projectPath = process.cwd();
|
||||
}
|
||||
|
||||
// Initialize CodeGraph if we have a project path
|
||||
await this.initializeCodeGraph(projectPath);
|
||||
// Try to initialize the default project (non-fatal if it fails)
|
||||
await this.tryInitializeDefault(projectPath);
|
||||
|
||||
// We accept the client's protocol version but respond with our supported version
|
||||
this.transport.sendResult(request.id, {
|
||||
@@ -240,19 +281,9 @@ export class MCPServer {
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the tool
|
||||
if (!this.toolHandler) {
|
||||
const errorMsg = this.initError ||
|
||||
(this.projectPath
|
||||
? `CodeGraph not initialized in ${this.projectPath}. Run 'codegraph init' first.`
|
||||
: 'No project path provided. Ensure Claude Code is running in a project directory.');
|
||||
this.transport.sendError(
|
||||
request.id,
|
||||
ErrorCodes.InternalError,
|
||||
errorMsg
|
||||
);
|
||||
return;
|
||||
}
|
||||
// If the default project isn't initialized yet, retry in case it was
|
||||
// initialized after the MCP server started (e.g. user ran codegraph init)
|
||||
this.retryInitIfNeeded();
|
||||
|
||||
const result = await this.toolHandler.execute(toolName, toolArgs);
|
||||
|
||||
|
||||
+18
-1
@@ -259,7 +259,21 @@ export class ToolHandler {
|
||||
// Cache of opened CodeGraph instances for cross-project queries
|
||||
private projectCache: Map<string, CodeGraph> = new Map();
|
||||
|
||||
constructor(private cg: CodeGraph) {}
|
||||
constructor(private cg: CodeGraph | null) {}
|
||||
|
||||
/**
|
||||
* Update the default CodeGraph instance (e.g. after lazy initialization)
|
||||
*/
|
||||
setDefaultCodeGraph(cg: CodeGraph): void {
|
||||
this.cg = cg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a default CodeGraph instance is available
|
||||
*/
|
||||
hasDefaultCodeGraph(): boolean {
|
||||
return this.cg !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CodeGraph instance for a project
|
||||
@@ -272,6 +286,9 @@ export class ToolHandler {
|
||||
*/
|
||||
private getCodeGraph(projectPath?: string): CodeGraph {
|
||||
if (!projectPath) {
|
||||
if (!this.cg) {
|
||||
throw new Error('CodeGraph not initialized for this project. Run \'codegraph init\' first.');
|
||||
}
|
||||
return this.cg;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user