@grafema/mcp 0.2.5-beta → 0.2.6-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -25
- package/dist/analysis-worker.js +8 -4
- package/dist/analysis-worker.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +15 -3
- package/dist/config.js.map +1 -1
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +69 -0
- package/dist/definitions.js.map +1 -1
- package/dist/handlers/analysis-handlers.d.ts +9 -0
- package/dist/handlers/analysis-handlers.d.ts.map +1 -0
- package/dist/handlers/analysis-handlers.js +73 -0
- package/dist/handlers/analysis-handlers.js.map +1 -0
- package/dist/handlers/context-handlers.d.ts +21 -0
- package/dist/handlers/context-handlers.d.ts.map +1 -0
- package/dist/handlers/context-handlers.js +330 -0
- package/dist/handlers/context-handlers.js.map +1 -0
- package/dist/handlers/coverage-handlers.d.ts +6 -0
- package/dist/handlers/coverage-handlers.d.ts.map +1 -0
- package/dist/handlers/coverage-handlers.js +42 -0
- package/dist/handlers/coverage-handlers.js.map +1 -0
- package/dist/handlers/dataflow-handlers.d.ts +8 -0
- package/dist/handlers/dataflow-handlers.d.ts.map +1 -0
- package/dist/handlers/dataflow-handlers.js +140 -0
- package/dist/handlers/dataflow-handlers.js.map +1 -0
- package/dist/handlers/documentation-handlers.d.ts +6 -0
- package/dist/handlers/documentation-handlers.d.ts.map +1 -0
- package/dist/handlers/documentation-handlers.js +79 -0
- package/dist/handlers/documentation-handlers.js.map +1 -0
- package/dist/handlers/guarantee-handlers.d.ts +21 -0
- package/dist/handlers/guarantee-handlers.d.ts.map +1 -0
- package/dist/handlers/guarantee-handlers.js +251 -0
- package/dist/handlers/guarantee-handlers.js.map +1 -0
- package/dist/handlers/guard-handlers.d.ts +14 -0
- package/dist/handlers/guard-handlers.d.ts.map +1 -0
- package/dist/handlers/guard-handlers.js +77 -0
- package/dist/handlers/guard-handlers.js.map +1 -0
- package/dist/handlers/index.d.ts +14 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +14 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/issue-handlers.d.ts +6 -0
- package/dist/handlers/issue-handlers.d.ts.map +1 -0
- package/dist/handlers/issue-handlers.js +66 -0
- package/dist/handlers/issue-handlers.js.map +1 -0
- package/dist/handlers/project-handlers.d.ts +7 -0
- package/dist/handlers/project-handlers.d.ts.map +1 -0
- package/dist/handlers/project-handlers.js +153 -0
- package/dist/handlers/project-handlers.js.map +1 -0
- package/dist/handlers/query-handlers.d.ts +8 -0
- package/dist/handlers/query-handlers.d.ts.map +1 -0
- package/dist/handlers/query-handlers.js +171 -0
- package/dist/handlers/query-handlers.js.map +1 -0
- package/dist/handlers.d.ts +3 -1
- package/dist/handlers.d.ts.map +1 -1
- package/dist/handlers.js +199 -4
- package/dist/handlers.js.map +1 -1
- package/dist/server.js +7 -1
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/analysis-worker.ts +10 -2
- package/src/config.ts +24 -0
- package/src/definitions.ts +70 -0
- package/src/handlers/analysis-handlers.ts +105 -0
- package/src/handlers/context-handlers.ts +410 -0
- package/src/handlers/coverage-handlers.ts +56 -0
- package/src/handlers/dataflow-handlers.ts +193 -0
- package/src/handlers/documentation-handlers.ts +89 -0
- package/src/handlers/guarantee-handlers.ts +278 -0
- package/src/handlers/guard-handlers.ts +100 -0
- package/src/handlers/index.ts +14 -0
- package/src/handlers/issue-handlers.ts +81 -0
- package/src/handlers/project-handlers.ts +200 -0
- package/src/handlers/query-handlers.ts +232 -0
- package/src/server.ts +13 -1
- package/src/types.ts +15 -0
- package/src/handlers.ts +0 -1373
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Project Handlers
|
|
3
|
+
*/
|
|
4
|
+
import { getProjectPath } from '../state.js';
|
|
5
|
+
import { validateServices, validatePatterns, validateWorkspace, GRAFEMA_VERSION, getSchemaVersion } from '@grafema/core';
|
|
6
|
+
import { existsSync, readdirSync, statSync, writeFileSync, mkdirSync } from 'fs';
|
|
7
|
+
import { join, basename } from 'path';
|
|
8
|
+
import { stringify as stringifyYAML } from 'yaml';
|
|
9
|
+
import { textResult, errorResult, } from '../utils.js';
|
|
10
|
+
// === PROJECT STRUCTURE (REG-173) ===
|
|
11
|
+
export async function handleReadProjectStructure(args) {
|
|
12
|
+
const projectPath = getProjectPath();
|
|
13
|
+
const subPath = args.path || '.';
|
|
14
|
+
const maxDepth = Math.min(Math.max(1, args.depth || 3), 5);
|
|
15
|
+
const includeFiles = args.include_files !== false;
|
|
16
|
+
const targetPath = join(projectPath, subPath);
|
|
17
|
+
if (!existsSync(targetPath)) {
|
|
18
|
+
return errorResult(`Path does not exist: ${subPath}`);
|
|
19
|
+
}
|
|
20
|
+
if (!statSync(targetPath).isDirectory()) {
|
|
21
|
+
return errorResult(`Path is not a directory: ${subPath}`);
|
|
22
|
+
}
|
|
23
|
+
const EXCLUDED = new Set([
|
|
24
|
+
'node_modules', '.git', 'dist', 'build', '.grafema',
|
|
25
|
+
'coverage', '.next', '.nuxt', '.cache', '.output',
|
|
26
|
+
'__pycache__', '.tox', 'target',
|
|
27
|
+
]);
|
|
28
|
+
const lines = [];
|
|
29
|
+
function walk(dir, prefix, depth) {
|
|
30
|
+
if (depth > maxDepth)
|
|
31
|
+
return;
|
|
32
|
+
let entries;
|
|
33
|
+
try {
|
|
34
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const dirs = [];
|
|
40
|
+
const files = [];
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
if (EXCLUDED.has(entry.name))
|
|
43
|
+
continue;
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
dirs.push(entry.name);
|
|
46
|
+
}
|
|
47
|
+
else if (includeFiles) {
|
|
48
|
+
files.push(entry.name);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
dirs.sort();
|
|
52
|
+
files.sort();
|
|
53
|
+
const allEntries = [
|
|
54
|
+
...dirs.map(d => ({ name: d, isDir: true })),
|
|
55
|
+
...files.map(f => ({ name: f, isDir: false })),
|
|
56
|
+
];
|
|
57
|
+
for (let i = 0; i < allEntries.length; i++) {
|
|
58
|
+
const entry = allEntries[i];
|
|
59
|
+
const isLast = i === allEntries.length - 1;
|
|
60
|
+
const connector = isLast ? '└── ' : '├── ';
|
|
61
|
+
const childPrefix = isLast ? ' ' : '│ ';
|
|
62
|
+
if (entry.isDir) {
|
|
63
|
+
lines.push(`${prefix}${connector}${entry.name}/`);
|
|
64
|
+
walk(join(dir, entry.name), prefix + childPrefix, depth + 1);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
lines.push(`${prefix}${connector}${entry.name}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
lines.push(subPath === '.' ? basename(projectPath) + '/' : subPath + '/');
|
|
72
|
+
walk(targetPath, '', 1);
|
|
73
|
+
if (lines.length === 1) {
|
|
74
|
+
return textResult(`Directory is empty or contains only excluded entries: ${subPath}`);
|
|
75
|
+
}
|
|
76
|
+
return textResult(lines.join('\n'));
|
|
77
|
+
}
|
|
78
|
+
// === WRITE CONFIG (REG-173) ===
|
|
79
|
+
export async function handleWriteConfig(args) {
|
|
80
|
+
const projectPath = getProjectPath();
|
|
81
|
+
const grafemaDir = join(projectPath, '.grafema');
|
|
82
|
+
const configPath = join(grafemaDir, 'config.yaml');
|
|
83
|
+
try {
|
|
84
|
+
if (args.services) {
|
|
85
|
+
validateServices(args.services, projectPath);
|
|
86
|
+
}
|
|
87
|
+
if (args.include !== undefined || args.exclude !== undefined) {
|
|
88
|
+
const warnings = [];
|
|
89
|
+
validatePatterns(args.include, args.exclude, {
|
|
90
|
+
warn: (msg) => warnings.push(msg),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (args.workspace) {
|
|
94
|
+
validateWorkspace(args.workspace, projectPath);
|
|
95
|
+
}
|
|
96
|
+
const config = {
|
|
97
|
+
version: getSchemaVersion(GRAFEMA_VERSION),
|
|
98
|
+
};
|
|
99
|
+
if (args.services && args.services.length > 0) {
|
|
100
|
+
config.services = args.services;
|
|
101
|
+
}
|
|
102
|
+
if (args.plugins) {
|
|
103
|
+
config.plugins = args.plugins;
|
|
104
|
+
}
|
|
105
|
+
if (args.include) {
|
|
106
|
+
config.include = args.include;
|
|
107
|
+
}
|
|
108
|
+
if (args.exclude) {
|
|
109
|
+
config.exclude = args.exclude;
|
|
110
|
+
}
|
|
111
|
+
if (args.workspace) {
|
|
112
|
+
config.workspace = args.workspace;
|
|
113
|
+
}
|
|
114
|
+
const yaml = stringifyYAML(config, { lineWidth: 0 });
|
|
115
|
+
const content = '# Grafema Configuration\n' +
|
|
116
|
+
'# Generated by Grafema onboarding\n' +
|
|
117
|
+
'# Documentation: https://github.com/grafema/grafema#configuration\n\n' +
|
|
118
|
+
yaml;
|
|
119
|
+
if (!existsSync(grafemaDir)) {
|
|
120
|
+
mkdirSync(grafemaDir, { recursive: true });
|
|
121
|
+
}
|
|
122
|
+
writeFileSync(configPath, content);
|
|
123
|
+
const summary = ['Configuration written to .grafema/config.yaml'];
|
|
124
|
+
if (args.services && args.services.length > 0) {
|
|
125
|
+
summary.push(`Services: ${args.services.map(s => s.name).join(', ')}`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
summary.push('Services: using auto-discovery (none explicitly configured)');
|
|
129
|
+
}
|
|
130
|
+
if (args.plugins) {
|
|
131
|
+
summary.push('Plugins: custom configuration');
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
summary.push('Plugins: using defaults');
|
|
135
|
+
}
|
|
136
|
+
if (args.include) {
|
|
137
|
+
summary.push(`Include patterns: ${args.include.join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
if (args.exclude) {
|
|
140
|
+
summary.push(`Exclude patterns: ${args.exclude.join(', ')}`);
|
|
141
|
+
}
|
|
142
|
+
if (args.workspace?.roots) {
|
|
143
|
+
summary.push(`Workspace roots: ${args.workspace.roots.join(', ')}`);
|
|
144
|
+
}
|
|
145
|
+
summary.push('\nNext step: run analyze_project to build the graph.');
|
|
146
|
+
return textResult(summary.join('\n'));
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
150
|
+
return errorResult(`Failed to write config: ${message}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=project-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-handlers.js","sourceRoot":"","sources":["../../src/handlers/project-handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Query Handlers
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolResult, QueryGraphArgs, FindCallsArgs, FindNodesArgs } from '../types.js';
|
|
5
|
+
export declare function handleQueryGraph(args: QueryGraphArgs): Promise<ToolResult>;
|
|
6
|
+
export declare function handleFindCalls(args: FindCallsArgs): Promise<ToolResult>;
|
|
7
|
+
export declare function handleFindNodes(args: FindNodesArgs): Promise<ToolResult>;
|
|
8
|
+
//# sourceMappingURL=query-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-handlers.d.ts","sourceRoot":"","sources":["../../src/handlers/query-handlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EAId,MAAM,aAAa,CAAC;AAIrB,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA8EhF;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CA0E9E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAiD9E"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Query Handlers
|
|
3
|
+
*/
|
|
4
|
+
import { ensureAnalyzed } from '../analysis.js';
|
|
5
|
+
import { normalizeLimit, formatPaginationInfo, guardResponseSize, serializeBigInt, findSimilarTypes, textResult, errorResult, } from '../utils.js';
|
|
6
|
+
// === QUERY HANDLERS ===
|
|
7
|
+
export async function handleQueryGraph(args) {
|
|
8
|
+
const db = await ensureAnalyzed();
|
|
9
|
+
const { query, limit: requestedLimit, offset: requestedOffset, format: _format, explain: _explain } = args;
|
|
10
|
+
const limit = normalizeLimit(requestedLimit);
|
|
11
|
+
const offset = Math.max(0, requestedOffset || 0);
|
|
12
|
+
try {
|
|
13
|
+
// Check if backend supports Datalog queries
|
|
14
|
+
if (!('checkGuarantee' in db)) {
|
|
15
|
+
return errorResult('Backend does not support Datalog queries');
|
|
16
|
+
}
|
|
17
|
+
const checkFn = db.checkGuarantee;
|
|
18
|
+
const results = await checkFn(query);
|
|
19
|
+
const total = results.length;
|
|
20
|
+
if (total === 0) {
|
|
21
|
+
const nodeCounts = await db.countNodesByType();
|
|
22
|
+
const totalNodes = Object.values(nodeCounts).reduce((a, b) => a + b, 0);
|
|
23
|
+
const typeMatch = query.match(/node\([^,]+,\s*"([^"]+)"\)/);
|
|
24
|
+
const queriedType = typeMatch ? typeMatch[1] : null;
|
|
25
|
+
let hint = '';
|
|
26
|
+
if (queriedType && !nodeCounts[queriedType]) {
|
|
27
|
+
const availableTypes = Object.keys(nodeCounts);
|
|
28
|
+
const similar = findSimilarTypes(queriedType, availableTypes);
|
|
29
|
+
if (similar.length > 0) {
|
|
30
|
+
hint = `\n💡 Did you mean: ${similar.join(', ')}?`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
hint = `\n💡 Available types: ${availableTypes.slice(0, 10).join(', ')}${availableTypes.length > 10 ? '...' : ''}`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return textResult(`Query returned no results.${hint}\n📊 Graph: ${totalNodes.toLocaleString()} nodes`);
|
|
37
|
+
}
|
|
38
|
+
const paginatedResults = results.slice(offset, offset + limit);
|
|
39
|
+
const hasMore = offset + limit < total;
|
|
40
|
+
const enrichedResults = [];
|
|
41
|
+
for (const result of paginatedResults) {
|
|
42
|
+
const nodeId = result.bindings?.find((b) => b.name === 'X')?.value;
|
|
43
|
+
if (nodeId) {
|
|
44
|
+
const node = await db.getNode(nodeId);
|
|
45
|
+
if (node) {
|
|
46
|
+
enrichedResults.push({
|
|
47
|
+
...node,
|
|
48
|
+
id: nodeId,
|
|
49
|
+
file: node.file,
|
|
50
|
+
line: node.line,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const paginationInfo = formatPaginationInfo({
|
|
56
|
+
limit,
|
|
57
|
+
offset,
|
|
58
|
+
returned: enrichedResults.length,
|
|
59
|
+
total,
|
|
60
|
+
hasMore,
|
|
61
|
+
});
|
|
62
|
+
const responseText = `Found ${total} result(s):${paginationInfo}\n\n${JSON.stringify(serializeBigInt(enrichedResults), null, 2)}`;
|
|
63
|
+
return textResult(guardResponseSize(responseText));
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
67
|
+
return errorResult(message);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export async function handleFindCalls(args) {
|
|
71
|
+
const db = await ensureAnalyzed();
|
|
72
|
+
const { target: name, limit: requestedLimit, offset: requestedOffset, className } = args;
|
|
73
|
+
const limit = normalizeLimit(requestedLimit);
|
|
74
|
+
const offset = Math.max(0, requestedOffset || 0);
|
|
75
|
+
const calls = [];
|
|
76
|
+
let skipped = 0;
|
|
77
|
+
let totalMatched = 0;
|
|
78
|
+
for await (const node of db.queryNodes({ type: 'CALL' })) {
|
|
79
|
+
if (node.name !== name && node['method'] !== name)
|
|
80
|
+
continue;
|
|
81
|
+
if (className && node['object'] !== className)
|
|
82
|
+
continue;
|
|
83
|
+
totalMatched++;
|
|
84
|
+
if (skipped < offset) {
|
|
85
|
+
skipped++;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (calls.length >= limit)
|
|
89
|
+
continue;
|
|
90
|
+
const callsEdges = await db.getOutgoingEdges(node.id, ['CALLS']);
|
|
91
|
+
const isResolved = callsEdges.length > 0;
|
|
92
|
+
let target = null;
|
|
93
|
+
if (isResolved) {
|
|
94
|
+
const targetNode = await db.getNode(callsEdges[0].dst);
|
|
95
|
+
target = targetNode
|
|
96
|
+
? {
|
|
97
|
+
type: targetNode.type,
|
|
98
|
+
name: targetNode.name ?? '',
|
|
99
|
+
file: targetNode.file,
|
|
100
|
+
line: targetNode.line,
|
|
101
|
+
}
|
|
102
|
+
: null;
|
|
103
|
+
}
|
|
104
|
+
calls.push({
|
|
105
|
+
id: node.id,
|
|
106
|
+
name: node.name,
|
|
107
|
+
object: node['object'],
|
|
108
|
+
file: node.file,
|
|
109
|
+
line: node.line,
|
|
110
|
+
resolved: isResolved,
|
|
111
|
+
target,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (totalMatched === 0) {
|
|
115
|
+
return textResult(`No calls found for "${className ? className + '.' : ''}${name}"`);
|
|
116
|
+
}
|
|
117
|
+
const resolved = calls.filter(c => c.resolved).length;
|
|
118
|
+
const unresolved = calls.length - resolved;
|
|
119
|
+
const hasMore = offset + calls.length < totalMatched;
|
|
120
|
+
const paginationInfo = formatPaginationInfo({
|
|
121
|
+
limit,
|
|
122
|
+
offset,
|
|
123
|
+
returned: calls.length,
|
|
124
|
+
total: totalMatched,
|
|
125
|
+
hasMore,
|
|
126
|
+
});
|
|
127
|
+
const responseText = `Found ${totalMatched} call(s) to "${className ? className + '.' : ''}${name}":${paginationInfo}\n` +
|
|
128
|
+
`- Resolved: ${resolved}\n` +
|
|
129
|
+
`- Unresolved: ${unresolved}\n\n` +
|
|
130
|
+
JSON.stringify(serializeBigInt(calls), null, 2);
|
|
131
|
+
return textResult(guardResponseSize(responseText));
|
|
132
|
+
}
|
|
133
|
+
export async function handleFindNodes(args) {
|
|
134
|
+
const db = await ensureAnalyzed();
|
|
135
|
+
const { type, name, file, limit: requestedLimit, offset: requestedOffset } = args;
|
|
136
|
+
const limit = normalizeLimit(requestedLimit);
|
|
137
|
+
const offset = Math.max(0, requestedOffset || 0);
|
|
138
|
+
const filter = {};
|
|
139
|
+
if (type)
|
|
140
|
+
filter.type = type;
|
|
141
|
+
if (name)
|
|
142
|
+
filter.name = name;
|
|
143
|
+
if (file)
|
|
144
|
+
filter.file = file;
|
|
145
|
+
const nodes = [];
|
|
146
|
+
let skipped = 0;
|
|
147
|
+
let totalMatched = 0;
|
|
148
|
+
for await (const node of db.queryNodes(filter)) {
|
|
149
|
+
totalMatched++;
|
|
150
|
+
if (skipped < offset) {
|
|
151
|
+
skipped++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (nodes.length < limit) {
|
|
155
|
+
nodes.push(node);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (totalMatched === 0) {
|
|
159
|
+
return textResult('No nodes found matching criteria');
|
|
160
|
+
}
|
|
161
|
+
const hasMore = offset + nodes.length < totalMatched;
|
|
162
|
+
const paginationInfo = formatPaginationInfo({
|
|
163
|
+
limit,
|
|
164
|
+
offset,
|
|
165
|
+
returned: nodes.length,
|
|
166
|
+
total: totalMatched,
|
|
167
|
+
hasMore,
|
|
168
|
+
});
|
|
169
|
+
return textResult(`Found ${totalMatched} node(s):${paginationInfo}\n\n${JSON.stringify(serializeBigInt(nodes), null, 2)}`);
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=query-handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-handlers.js","sourceRoot":"","sources":["../../src/handlers/query-handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/handlers.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Tool Handlers
|
|
3
3
|
*/
|
|
4
|
-
import type { ToolResult, QueryGraphArgs, FindCallsArgs, FindNodesArgs, TraceAliasArgs, TraceDataFlowArgs, CheckInvariantArgs, AnalyzeProjectArgs, GetSchemaArgs, CreateGuaranteeArgs, CheckGuaranteesArgs, DeleteGuaranteeArgs, GetCoverageArgs, GetDocumentationArgs, FindGuardsArgs, GetFunctionDetailsArgs, ReportIssueArgs, ReadProjectStructureArgs, WriteConfigArgs } from './types.js';
|
|
4
|
+
import type { ToolResult, QueryGraphArgs, FindCallsArgs, FindNodesArgs, TraceAliasArgs, TraceDataFlowArgs, CheckInvariantArgs, AnalyzeProjectArgs, GetSchemaArgs, CreateGuaranteeArgs, CheckGuaranteesArgs, DeleteGuaranteeArgs, GetCoverageArgs, GetDocumentationArgs, FindGuardsArgs, GetFunctionDetailsArgs, GetContextArgs, GetFileOverviewArgs, ReportIssueArgs, ReadProjectStructureArgs, WriteConfigArgs } from './types.js';
|
|
5
5
|
export declare function handleQueryGraph(args: QueryGraphArgs): Promise<ToolResult>;
|
|
6
6
|
export declare function handleFindCalls(args: FindCallsArgs): Promise<ToolResult>;
|
|
7
7
|
export declare function handleFindNodes(args: FindNodesArgs): Promise<ToolResult>;
|
|
@@ -53,7 +53,9 @@ export declare function handleFindGuards(args: FindGuardsArgs): Promise<ToolResu
|
|
|
53
53
|
* Use transitive=true to follow call chains (A -> B -> C).
|
|
54
54
|
*/
|
|
55
55
|
export declare function handleGetFunctionDetails(args: GetFunctionDetailsArgs): Promise<ToolResult>;
|
|
56
|
+
export declare function handleGetContext(args: GetContextArgs): Promise<ToolResult>;
|
|
56
57
|
export declare function handleReportIssue(args: ReportIssueArgs): Promise<ToolResult>;
|
|
57
58
|
export declare function handleReadProjectStructure(args: ReadProjectStructureArgs): Promise<ToolResult>;
|
|
58
59
|
export declare function handleWriteConfig(args: WriteConfigArgs): Promise<ToolResult>;
|
|
60
|
+
export declare function handleGetFileOverview(args: GetFileOverviewArgs): Promise<ToolResult>;
|
|
59
61
|
//# sourceMappingURL=handlers.d.ts.map
|
package/dist/handlers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,cAAc,EAEd,sBAAsB,
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../src/handlers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,cAAc,EAEd,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EAInB,eAAe,EACf,wBAAwB,EACxB,eAAe,EAChB,MAAM,YAAY,CAAC;AAKpB,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA8EhF;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CA0E9E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAiD9E;AAID,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CA2DhF;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CA+DtF;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6CxF;AAID,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BxF;AAED,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC,CAYnE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC,CAe1D;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAwB9E;AAID;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CA8D1F;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,UAAU,CAAC,CA0ChE;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAyG1F;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CA+B1F;AAID,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAsClF;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAyE5F;AAID;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAyEhF;AAID;;;;;;;;;;;;GAYG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,UAAU,CAAC,CA6ErB;AA+CD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,UAAU,CAAC,CA4HrB;AAID,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC,CAkElF;AAID,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,wBAAwB,GAC7B,OAAO,CAAC,UAAU,CAAC,CA8ErB;AAID,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,UAAU,CAAC,CA2FrB;AAID,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,UAAU,CAAC,CA2GrB"}
|
package/dist/handlers.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { ensureAnalyzed } from './analysis.js';
|
|
5
5
|
import { getProjectPath, getAnalysisStatus, getOrCreateBackend, getGuaranteeManager, getGuaranteeAPI, isAnalysisRunning } from './state.js';
|
|
6
|
-
import { CoverageAnalyzer, findCallsInFunction, findContainingFunction, validateServices, validatePatterns, validateWorkspace, getOnboardingInstruction } from '@grafema/core';
|
|
7
|
-
import { existsSync, readdirSync, statSync, writeFileSync, mkdirSync } from 'fs';
|
|
8
|
-
import { join, basename } from 'path';
|
|
6
|
+
import { CoverageAnalyzer, findCallsInFunction, findContainingFunction, validateServices, validatePatterns, validateWorkspace, getOnboardingInstruction, GRAFEMA_VERSION, getSchemaVersion, FileOverview, buildNodeContext, getNodeDisplayName, formatEdgeMetadata, STRUCTURAL_EDGE_TYPES } from '@grafema/core';
|
|
7
|
+
import { existsSync, readFileSync, readdirSync, statSync, writeFileSync, mkdirSync, realpathSync } from 'fs';
|
|
8
|
+
import { join, basename, relative } from 'path';
|
|
9
9
|
import { stringify as stringifyYAML } from 'yaml';
|
|
10
10
|
import { normalizeLimit, formatPaginationInfo, guardResponseSize, serializeBigInt, findSimilarTypes, textResult, errorResult, } from './utils.js';
|
|
11
11
|
import { isGuaranteeType } from '@grafema/core';
|
|
@@ -910,6 +910,116 @@ function formatCallsForDisplay(calls) {
|
|
|
910
910
|
}
|
|
911
911
|
return lines;
|
|
912
912
|
}
|
|
913
|
+
// === NODE CONTEXT (REG-406) ===
|
|
914
|
+
export async function handleGetContext(args) {
|
|
915
|
+
const db = await ensureAnalyzed();
|
|
916
|
+
const { semanticId, contextLines: ctxLines = 3, edgeType } = args;
|
|
917
|
+
// 1. Look up node
|
|
918
|
+
const node = await db.getNode(semanticId);
|
|
919
|
+
if (!node) {
|
|
920
|
+
return errorResult(`Node not found: "${semanticId}"\n` +
|
|
921
|
+
`Use find_nodes or query_graph to find the correct semantic ID.`);
|
|
922
|
+
}
|
|
923
|
+
const edgeTypeFilter = edgeType
|
|
924
|
+
? new Set(edgeType.split(',').map(t => t.trim().toUpperCase()))
|
|
925
|
+
: null;
|
|
926
|
+
// 2. Build context using shared logic
|
|
927
|
+
const ctx = await buildNodeContext(db, node, {
|
|
928
|
+
contextLines: ctxLines,
|
|
929
|
+
edgeTypeFilter,
|
|
930
|
+
});
|
|
931
|
+
// 3. Format text output
|
|
932
|
+
const projectPath = getProjectPath();
|
|
933
|
+
const relFile = node.file ? relative(projectPath, node.file) : undefined;
|
|
934
|
+
const lines = [];
|
|
935
|
+
lines.push(`[${node.type}] ${getNodeDisplayName(node)}`);
|
|
936
|
+
lines.push(` ID: ${node.id}`);
|
|
937
|
+
if (relFile) {
|
|
938
|
+
lines.push(` Location: ${relFile}${node.line ? `:${node.line}` : ''}`);
|
|
939
|
+
}
|
|
940
|
+
// Source
|
|
941
|
+
if (ctx.source) {
|
|
942
|
+
lines.push('');
|
|
943
|
+
lines.push(` Source (lines ${ctx.source.startLine}-${ctx.source.endLine}):`);
|
|
944
|
+
const maxLineNum = ctx.source.endLine;
|
|
945
|
+
const lineNumWidth = String(maxLineNum).length;
|
|
946
|
+
for (let i = 0; i < ctx.source.lines.length; i++) {
|
|
947
|
+
const lineNum = ctx.source.startLine + i;
|
|
948
|
+
const paddedNum = String(lineNum).padStart(lineNumWidth, ' ');
|
|
949
|
+
const prefix = lineNum === node.line ? '>' : ' ';
|
|
950
|
+
const displayLine = ctx.source.lines[i].length > 120
|
|
951
|
+
? ctx.source.lines[i].slice(0, 117) + '...'
|
|
952
|
+
: ctx.source.lines[i];
|
|
953
|
+
lines.push(` ${prefix}${paddedNum} | ${displayLine}`);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
const formatEdgeSection = (groups, dir) => {
|
|
957
|
+
for (const group of groups) {
|
|
958
|
+
const isStructural = STRUCTURAL_EDGE_TYPES.has(group.edgeType);
|
|
959
|
+
lines.push(` ${group.edgeType} (${group.edges.length}):`);
|
|
960
|
+
for (const { edge, node: connNode } of group.edges) {
|
|
961
|
+
if (!connNode) {
|
|
962
|
+
const danglingId = dir === '->' ? edge.dst : edge.src;
|
|
963
|
+
lines.push(` ${dir} [dangling] ${danglingId}`);
|
|
964
|
+
continue;
|
|
965
|
+
}
|
|
966
|
+
const nFile = connNode.file ? relative(projectPath, connNode.file) : '';
|
|
967
|
+
const nLoc = nFile ? (connNode.line ? `${nFile}:${connNode.line}` : nFile) : '';
|
|
968
|
+
const locStr = nLoc ? ` (${nLoc})` : '';
|
|
969
|
+
const metaStr = formatEdgeMetadata(edge);
|
|
970
|
+
lines.push(` ${dir} [${connNode.type}] ${getNodeDisplayName(connNode)}${locStr}${metaStr}`);
|
|
971
|
+
// Code context for non-structural edges
|
|
972
|
+
if (!isStructural && connNode.file && connNode.line && ctxLines > 0) {
|
|
973
|
+
if (existsSync(connNode.file)) {
|
|
974
|
+
try {
|
|
975
|
+
const content = readFileSync(connNode.file, 'utf-8');
|
|
976
|
+
const allFileLines = content.split('\n');
|
|
977
|
+
const nLine = connNode.line;
|
|
978
|
+
const sLine = Math.max(1, nLine - Math.min(ctxLines, 2));
|
|
979
|
+
const eLine = Math.min(allFileLines.length, nLine + Math.min(ctxLines, 2));
|
|
980
|
+
const w = String(eLine).length;
|
|
981
|
+
for (let i = sLine; i <= eLine; i++) {
|
|
982
|
+
const p = i === nLine ? '>' : ' ';
|
|
983
|
+
const ln = String(i).padStart(w, ' ');
|
|
984
|
+
const displayLn = allFileLines[i - 1].length > 120
|
|
985
|
+
? allFileLines[i - 1].slice(0, 117) + '...'
|
|
986
|
+
: allFileLines[i - 1];
|
|
987
|
+
lines.push(` ${p}${ln} | ${displayLn}`);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
catch { /* ignore */ }
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
if (ctx.outgoing.length > 0) {
|
|
997
|
+
lines.push('');
|
|
998
|
+
lines.push(' Outgoing edges:');
|
|
999
|
+
formatEdgeSection(ctx.outgoing, '->');
|
|
1000
|
+
}
|
|
1001
|
+
if (ctx.incoming.length > 0) {
|
|
1002
|
+
lines.push('');
|
|
1003
|
+
lines.push(' Incoming edges:');
|
|
1004
|
+
formatEdgeSection(ctx.incoming, '<-');
|
|
1005
|
+
}
|
|
1006
|
+
if (ctx.outgoing.length === 0 && ctx.incoming.length === 0) {
|
|
1007
|
+
lines.push('');
|
|
1008
|
+
lines.push(' No edges found.');
|
|
1009
|
+
}
|
|
1010
|
+
// Build JSON result alongside text
|
|
1011
|
+
const jsonResult = {
|
|
1012
|
+
node: { id: node.id, type: node.type, name: node.name, file: relFile, line: node.line },
|
|
1013
|
+
source: ctx.source ? {
|
|
1014
|
+
startLine: ctx.source.startLine,
|
|
1015
|
+
endLine: ctx.source.endLine,
|
|
1016
|
+
lines: ctx.source.lines,
|
|
1017
|
+
} : null,
|
|
1018
|
+
outgoing: Object.fromEntries(ctx.outgoing.map(g => [g.edgeType, g.edges])),
|
|
1019
|
+
incoming: Object.fromEntries(ctx.incoming.map(g => [g.edgeType, g.edges])),
|
|
1020
|
+
};
|
|
1021
|
+
return textResult(lines.join('\n') + '\n\n' + JSON.stringify(serializeBigInt(jsonResult), null, 2));
|
|
1022
|
+
}
|
|
913
1023
|
// === BUG REPORTING ===
|
|
914
1024
|
export async function handleReportIssue(args) {
|
|
915
1025
|
const { title, description, context, labels = ['bug'] } = args;
|
|
@@ -1057,7 +1167,9 @@ export async function handleWriteConfig(args) {
|
|
|
1057
1167
|
if (args.workspace) {
|
|
1058
1168
|
validateWorkspace(args.workspace, projectPath);
|
|
1059
1169
|
}
|
|
1060
|
-
const config = {
|
|
1170
|
+
const config = {
|
|
1171
|
+
version: getSchemaVersion(GRAFEMA_VERSION),
|
|
1172
|
+
};
|
|
1061
1173
|
if (args.services && args.services.length > 0) {
|
|
1062
1174
|
config.services = args.services;
|
|
1063
1175
|
}
|
|
@@ -1112,4 +1224,87 @@ export async function handleWriteConfig(args) {
|
|
|
1112
1224
|
return errorResult(`Failed to write config: ${message}`);
|
|
1113
1225
|
}
|
|
1114
1226
|
}
|
|
1227
|
+
// === FILE OVERVIEW (REG-412) ===
|
|
1228
|
+
export async function handleGetFileOverview(args) {
|
|
1229
|
+
const db = await ensureAnalyzed();
|
|
1230
|
+
const projectPath = getProjectPath();
|
|
1231
|
+
const { file, include_edges: includeEdges = true } = args;
|
|
1232
|
+
let filePath = file;
|
|
1233
|
+
if (!filePath.startsWith('/')) {
|
|
1234
|
+
filePath = join(projectPath, filePath);
|
|
1235
|
+
}
|
|
1236
|
+
if (!existsSync(filePath)) {
|
|
1237
|
+
return errorResult(`File not found: ${file}\n` +
|
|
1238
|
+
`Resolved to: ${filePath}\n` +
|
|
1239
|
+
`Project root: ${projectPath}`);
|
|
1240
|
+
}
|
|
1241
|
+
const absolutePath = realpathSync(filePath);
|
|
1242
|
+
const relativePath = relative(projectPath, absolutePath);
|
|
1243
|
+
try {
|
|
1244
|
+
const overview = new FileOverview(db);
|
|
1245
|
+
const result = await overview.getOverview(absolutePath, {
|
|
1246
|
+
includeEdges,
|
|
1247
|
+
});
|
|
1248
|
+
result.file = relativePath;
|
|
1249
|
+
if (result.status === 'NOT_ANALYZED') {
|
|
1250
|
+
return textResult(`File not analyzed: ${relativePath}\n` +
|
|
1251
|
+
`Run analyze_project to build the graph.`);
|
|
1252
|
+
}
|
|
1253
|
+
const lines = [];
|
|
1254
|
+
lines.push(`Module: ${result.file}`);
|
|
1255
|
+
if (result.imports.length > 0) {
|
|
1256
|
+
const sources = result.imports.map(i => i.source);
|
|
1257
|
+
lines.push(`Imports: ${sources.join(', ')}`);
|
|
1258
|
+
}
|
|
1259
|
+
if (result.exports.length > 0) {
|
|
1260
|
+
const names = result.exports.map(e => e.isDefault ? `${e.name} (default)` : e.name);
|
|
1261
|
+
lines.push(`Exports: ${names.join(', ')}`);
|
|
1262
|
+
}
|
|
1263
|
+
if (result.classes.length > 0) {
|
|
1264
|
+
lines.push('');
|
|
1265
|
+
lines.push('Classes:');
|
|
1266
|
+
for (const cls of result.classes) {
|
|
1267
|
+
const ext = cls.extends ? ` extends ${cls.extends}` : '';
|
|
1268
|
+
lines.push(` ${cls.name}${ext} (line ${cls.line ?? '?'})`);
|
|
1269
|
+
for (const m of cls.methods) {
|
|
1270
|
+
const calls = m.calls.length > 0
|
|
1271
|
+
? ` -> ${m.calls.join(', ')}`
|
|
1272
|
+
: '';
|
|
1273
|
+
const params = m.params
|
|
1274
|
+
? `(${m.params.join(', ')})`
|
|
1275
|
+
: '()';
|
|
1276
|
+
lines.push(` ${m.name}${params}${calls}`);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
if (result.functions.length > 0) {
|
|
1281
|
+
lines.push('');
|
|
1282
|
+
lines.push('Functions:');
|
|
1283
|
+
for (const fn of result.functions) {
|
|
1284
|
+
const calls = fn.calls.length > 0
|
|
1285
|
+
? ` -> ${fn.calls.join(', ')}`
|
|
1286
|
+
: '';
|
|
1287
|
+
const params = fn.params
|
|
1288
|
+
? `(${fn.params.join(', ')})`
|
|
1289
|
+
: '()';
|
|
1290
|
+
const asyncStr = fn.async ? 'async ' : '';
|
|
1291
|
+
lines.push(` ${asyncStr}${fn.name}${params}${calls} (line ${fn.line ?? '?'})`);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
if (result.variables.length > 0) {
|
|
1295
|
+
lines.push('');
|
|
1296
|
+
lines.push('Variables:');
|
|
1297
|
+
for (const v of result.variables) {
|
|
1298
|
+
const assign = v.assignedFrom ? ` = ${v.assignedFrom}` : '';
|
|
1299
|
+
lines.push(` ${v.kind} ${v.name}${assign} (line ${v.line ?? '?'})`);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
return textResult(lines.join('\n') + '\n\n' +
|
|
1303
|
+
JSON.stringify(serializeBigInt(result), null, 2));
|
|
1304
|
+
}
|
|
1305
|
+
catch (error) {
|
|
1306
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1307
|
+
return errorResult(`Failed to get file overview: ${message}`);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1115
1310
|
//# sourceMappingURL=handlers.js.map
|