@optave/codegraph 1.1.0 → 1.3.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/LICENSE +190 -190
- package/README.md +480 -311
- package/grammars/tree-sitter-c_sharp.wasm +0 -0
- package/grammars/tree-sitter-go.wasm +0 -0
- package/grammars/tree-sitter-hcl.wasm +0 -0
- package/grammars/tree-sitter-java.wasm +0 -0
- package/grammars/tree-sitter-javascript.wasm +0 -0
- package/grammars/tree-sitter-php.wasm +0 -0
- package/grammars/tree-sitter-python.wasm +0 -0
- package/grammars/tree-sitter-ruby.wasm +0 -0
- package/grammars/tree-sitter-rust.wasm +0 -0
- package/grammars/tree-sitter-tsx.wasm +0 -0
- package/grammars/tree-sitter-typescript.wasm +0 -0
- package/package.json +90 -69
- package/src/builder.js +161 -162
- package/src/cli.js +284 -224
- package/src/config.js +61 -55
- package/src/constants.js +41 -28
- package/src/cycles.js +125 -104
- package/src/db.js +129 -117
- package/src/embedder.js +253 -59
- package/src/export.js +150 -138
- package/src/index.js +50 -39
- package/src/logger.js +24 -20
- package/src/mcp.js +145 -139
- package/src/native.js +68 -0
- package/src/parser.js +2214 -573
- package/src/queries.js +304 -128
- package/src/resolve.js +171 -0
- package/src/watcher.js +81 -53
package/src/mcp.js
CHANGED
|
@@ -1,139 +1,145 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP (Model Context Protocol) server for codegraph.
|
|
3
|
-
* Exposes codegraph queries as tools that AI coding assistants can call.
|
|
4
|
-
*
|
|
5
|
-
* Requires: npm install @modelcontextprotocol/sdk
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createRequire } from 'node:module';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
const TOOLS = [
|
|
13
|
-
{
|
|
14
|
-
name: 'query_function',
|
|
15
|
-
description: 'Find callers and callees of a function by name',
|
|
16
|
-
inputSchema: {
|
|
17
|
-
type: 'object',
|
|
18
|
-
properties: {
|
|
19
|
-
name: { type: 'string', description: 'Function name to query (supports partial match)' },
|
|
20
|
-
depth: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
case '
|
|
115
|
-
result =
|
|
116
|
-
break;
|
|
117
|
-
case '
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
result =
|
|
122
|
-
break;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* MCP (Model Context Protocol) server for codegraph.
|
|
3
|
+
* Exposes codegraph queries as tools that AI coding assistants can call.
|
|
4
|
+
*
|
|
5
|
+
* Requires: npm install @modelcontextprotocol/sdk
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createRequire } from 'node:module';
|
|
9
|
+
import { findCycles } from './cycles.js';
|
|
10
|
+
import { findDbPath } from './db.js';
|
|
11
|
+
|
|
12
|
+
const TOOLS = [
|
|
13
|
+
{
|
|
14
|
+
name: 'query_function',
|
|
15
|
+
description: 'Find callers and callees of a function by name',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
name: { type: 'string', description: 'Function name to query (supports partial match)' },
|
|
20
|
+
depth: {
|
|
21
|
+
type: 'number',
|
|
22
|
+
description: 'Traversal depth for transitive callers',
|
|
23
|
+
default: 2,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
required: ['name'],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'file_deps',
|
|
31
|
+
description: 'Show what a file imports and what imports it',
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: 'object',
|
|
34
|
+
properties: {
|
|
35
|
+
file: { type: 'string', description: 'File path (partial match supported)' },
|
|
36
|
+
},
|
|
37
|
+
required: ['file'],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'impact_analysis',
|
|
42
|
+
description: 'Show files affected by changes to a given file (transitive)',
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
file: { type: 'string', description: 'File path to analyze' },
|
|
47
|
+
},
|
|
48
|
+
required: ['file'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'find_cycles',
|
|
53
|
+
description: 'Detect circular dependencies in the codebase',
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'module_map',
|
|
61
|
+
description: 'Get high-level overview of most-connected files',
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: 'object',
|
|
64
|
+
properties: {
|
|
65
|
+
limit: { type: 'number', description: 'Number of top files to show', default: 20 },
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
export { TOOLS };
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Start the MCP server.
|
|
75
|
+
* This function requires @modelcontextprotocol/sdk to be installed.
|
|
76
|
+
*/
|
|
77
|
+
export async function startMCPServer(customDbPath) {
|
|
78
|
+
let Server, StdioServerTransport;
|
|
79
|
+
try {
|
|
80
|
+
const sdk = await import('@modelcontextprotocol/sdk/server/index.js');
|
|
81
|
+
Server = sdk.Server;
|
|
82
|
+
const transport = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
83
|
+
StdioServerTransport = transport.StdioServerTransport;
|
|
84
|
+
} catch {
|
|
85
|
+
console.error(
|
|
86
|
+
'MCP server requires @modelcontextprotocol/sdk.\n' +
|
|
87
|
+
'Install it with: npm install @modelcontextprotocol/sdk',
|
|
88
|
+
);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Lazy import query functions to avoid circular deps at module load
|
|
93
|
+
const { queryNameData, impactAnalysisData, moduleMapData, fileDepsData } = await import(
|
|
94
|
+
'./queries.js'
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const require = createRequire(import.meta.url);
|
|
98
|
+
const Database = require('better-sqlite3');
|
|
99
|
+
|
|
100
|
+
const server = new Server(
|
|
101
|
+
{ name: 'codegraph', version: '1.0.0' },
|
|
102
|
+
{ capabilities: { tools: {} } },
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
server.setRequestHandler('tools/list', async () => ({ tools: TOOLS }));
|
|
106
|
+
|
|
107
|
+
server.setRequestHandler('tools/call', async (request) => {
|
|
108
|
+
const { name, arguments: args } = request.params;
|
|
109
|
+
const dbPath = customDbPath || undefined;
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
let result;
|
|
113
|
+
switch (name) {
|
|
114
|
+
case 'query_function':
|
|
115
|
+
result = queryNameData(args.name, dbPath);
|
|
116
|
+
break;
|
|
117
|
+
case 'file_deps':
|
|
118
|
+
result = fileDepsData(args.file, dbPath);
|
|
119
|
+
break;
|
|
120
|
+
case 'impact_analysis':
|
|
121
|
+
result = impactAnalysisData(args.file, dbPath);
|
|
122
|
+
break;
|
|
123
|
+
case 'find_cycles': {
|
|
124
|
+
const db = new Database(findDbPath(dbPath), { readonly: true });
|
|
125
|
+
const cycles = findCycles(db);
|
|
126
|
+
db.close();
|
|
127
|
+
result = { cycles, count: cycles.length };
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case 'module_map':
|
|
131
|
+
result = moduleMapData(dbPath, args.limit || 20);
|
|
132
|
+
break;
|
|
133
|
+
default:
|
|
134
|
+
return { content: [{ type: 'text', text: `Unknown tool: ${name}` }], isError: true };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
138
|
+
} catch (err) {
|
|
139
|
+
return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const transport = new StdioServerTransport();
|
|
144
|
+
await server.connect(transport);
|
|
145
|
+
}
|
package/src/native.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native addon loader with graceful fallback to WASM.
|
|
3
|
+
*
|
|
4
|
+
* Tries to load the platform-specific napi-rs binary built from
|
|
5
|
+
* crates/codegraph-core. If unavailable the caller should fall back
|
|
6
|
+
* to the existing WASM pipeline.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
|
|
12
|
+
let _cached; // undefined = not yet tried, null = failed, object = module
|
|
13
|
+
let _loadError = null;
|
|
14
|
+
|
|
15
|
+
/** Map of (platform-arch) → npm package name. */
|
|
16
|
+
const PLATFORM_PACKAGES = {
|
|
17
|
+
'linux-x64': '@optave/codegraph-linux-x64-gnu',
|
|
18
|
+
'darwin-arm64': '@optave/codegraph-darwin-arm64',
|
|
19
|
+
'darwin-x64': '@optave/codegraph-darwin-x64',
|
|
20
|
+
'win32-x64': '@optave/codegraph-win32-x64-msvc',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Try to load the native napi addon.
|
|
25
|
+
* Returns the module on success, null on failure.
|
|
26
|
+
*/
|
|
27
|
+
export function loadNative() {
|
|
28
|
+
if (_cached !== undefined) return _cached;
|
|
29
|
+
|
|
30
|
+
const require = createRequire(import.meta.url);
|
|
31
|
+
|
|
32
|
+
const key = `${os.platform()}-${os.arch()}`;
|
|
33
|
+
const pkg = PLATFORM_PACKAGES[key];
|
|
34
|
+
if (pkg) {
|
|
35
|
+
try {
|
|
36
|
+
_cached = require(pkg);
|
|
37
|
+
return _cached;
|
|
38
|
+
} catch (err) {
|
|
39
|
+
_loadError = err;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
_loadError = new Error(`Unsupported platform: ${key}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_cached = null;
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check whether the native engine is available on this platform.
|
|
51
|
+
*/
|
|
52
|
+
export function isNativeAvailable() {
|
|
53
|
+
return loadNative() !== null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Return the native module or throw if not available.
|
|
58
|
+
*/
|
|
59
|
+
export function getNative() {
|
|
60
|
+
const mod = loadNative();
|
|
61
|
+
if (!mod) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Native codegraph-core not available: ${_loadError?.message || 'unknown error'}. ` +
|
|
64
|
+
'Install the platform package or use --engine wasm.',
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return mod;
|
|
68
|
+
}
|