@grafema/mcp 0.2.11 → 0.3.0-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/dist/analysis-worker.d.ts +4 -3
- package/dist/analysis-worker.d.ts.map +1 -1
- package/dist/analysis-worker.js +8 -203
- package/dist/analysis-worker.js.map +1 -1
- package/dist/analysis.d.ts +10 -3
- package/dist/analysis.d.ts.map +1 -1
- package/dist/analysis.js +130 -62
- package/dist/analysis.js.map +1 -1
- package/dist/config.d.ts +5 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -128
- package/dist/config.js.map +1 -1
- package/dist/definitions/analysis-tools.d.ts +6 -0
- package/dist/definitions/analysis-tools.d.ts.map +1 -0
- package/dist/definitions/analysis-tools.js +125 -0
- package/dist/definitions/analysis-tools.js.map +1 -0
- package/dist/definitions/context-tools.d.ts +6 -0
- package/dist/definitions/context-tools.d.ts.map +1 -0
- package/dist/definitions/context-tools.js +144 -0
- package/dist/definitions/context-tools.js.map +1 -0
- package/dist/definitions/graph-tools.d.ts +7 -0
- package/dist/definitions/graph-tools.d.ts.map +1 -0
- package/dist/definitions/graph-tools.js +124 -0
- package/dist/definitions/graph-tools.js.map +1 -0
- package/dist/definitions/graphql-tools.d.ts +6 -0
- package/dist/definitions/graphql-tools.d.ts.map +1 -0
- package/dist/definitions/graphql-tools.js +62 -0
- package/dist/definitions/graphql-tools.js.map +1 -0
- package/dist/definitions/guarantee-tools.d.ts +6 -0
- package/dist/definitions/guarantee-tools.d.ts.map +1 -0
- package/dist/definitions/guarantee-tools.js +136 -0
- package/dist/definitions/guarantee-tools.js.map +1 -0
- package/dist/definitions/index.d.ts +7 -0
- package/dist/definitions/index.d.ts.map +1 -0
- package/dist/definitions/index.js +24 -0
- package/dist/definitions/index.js.map +1 -0
- package/dist/definitions/knowledge-tools.d.ts +10 -0
- package/dist/definitions/knowledge-tools.d.ts.map +1 -0
- package/dist/definitions/knowledge-tools.js +300 -0
- package/dist/definitions/knowledge-tools.js.map +1 -0
- package/dist/definitions/notation-tools.d.ts +9 -0
- package/dist/definitions/notation-tools.d.ts.map +1 -0
- package/dist/definitions/notation-tools.js +62 -0
- package/dist/definitions/notation-tools.js.map +1 -0
- package/dist/definitions/project-tools.d.ts +6 -0
- package/dist/definitions/project-tools.d.ts.map +1 -0
- package/dist/definitions/project-tools.js +181 -0
- package/dist/definitions/project-tools.js.map +1 -0
- package/dist/definitions/query-tools.d.ts +6 -0
- package/dist/definitions/query-tools.d.ts.map +1 -0
- package/dist/definitions/query-tools.js +245 -0
- package/dist/definitions/query-tools.js.map +1 -0
- package/dist/definitions/types.d.ts +21 -0
- package/dist/definitions/types.d.ts.map +1 -0
- package/dist/definitions/types.js +5 -0
- package/dist/definitions/types.js.map +1 -0
- package/dist/dev-proxy.d.ts +29 -0
- package/dist/dev-proxy.d.ts.map +1 -0
- package/dist/dev-proxy.js +267 -0
- package/dist/dev-proxy.js.map +1 -0
- package/dist/handlers/analysis-handlers.d.ts.map +1 -1
- package/dist/handlers/analysis-handlers.js +34 -4
- package/dist/handlers/analysis-handlers.js.map +1 -1
- package/dist/handlers/context-handlers.d.ts +5 -6
- package/dist/handlers/context-handlers.d.ts.map +1 -1
- package/dist/handlers/context-handlers.js +19 -16
- package/dist/handlers/context-handlers.js.map +1 -1
- package/dist/handlers/coverage-handlers.js +1 -1
- package/dist/handlers/dataflow-handlers.d.ts +2 -0
- package/dist/handlers/dataflow-handlers.d.ts.map +1 -1
- package/dist/handlers/dataflow-handlers.js +68 -46
- package/dist/handlers/dataflow-handlers.js.map +1 -1
- package/dist/handlers/documentation-handlers.d.ts.map +1 -1
- package/dist/handlers/documentation-handlers.js +56 -2
- package/dist/handlers/documentation-handlers.js.map +1 -1
- package/dist/handlers/graph-handlers.d.ts +23 -0
- package/dist/handlers/graph-handlers.d.ts.map +1 -0
- package/dist/handlers/graph-handlers.js +155 -0
- package/dist/handlers/graph-handlers.js.map +1 -0
- package/dist/handlers/graphql-handlers.d.ts +9 -0
- package/dist/handlers/graphql-handlers.d.ts.map +1 -0
- package/dist/handlers/graphql-handlers.js +57 -0
- package/dist/handlers/graphql-handlers.js.map +1 -0
- package/dist/handlers/guarantee-handlers.js +1 -1
- package/dist/handlers/guard-handlers.d.ts.map +1 -1
- package/dist/handlers/guard-handlers.js +6 -3
- package/dist/handlers/guard-handlers.js.map +1 -1
- package/dist/handlers/index.d.ts +4 -0
- package/dist/handlers/index.d.ts.map +1 -1
- package/dist/handlers/index.js +6 -0
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/issue-handlers.d.ts.map +1 -1
- package/dist/handlers/issue-handlers.js +10 -15
- package/dist/handlers/issue-handlers.js.map +1 -1
- package/dist/handlers/knowledge-handlers.d.ts +25 -0
- package/dist/handlers/knowledge-handlers.d.ts.map +1 -0
- package/dist/handlers/knowledge-handlers.js +208 -0
- package/dist/handlers/knowledge-handlers.js.map +1 -0
- package/dist/handlers/notation-handlers.d.ts +6 -0
- package/dist/handlers/notation-handlers.d.ts.map +1 -0
- package/dist/handlers/notation-handlers.js +53 -0
- package/dist/handlers/notation-handlers.js.map +1 -0
- package/dist/handlers/project-handlers.js +1 -1
- package/dist/handlers/query-handlers.d.ts.map +1 -1
- package/dist/handlers/query-handlers.js +166 -20
- package/dist/handlers/query-handlers.js.map +1 -1
- package/dist/prompts.js +1 -1
- package/dist/server.d.ts +19 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +93 -3
- package/dist/server.js.map +1 -1
- package/dist/state.d.ts +10 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +61 -8
- package/dist/state.js.map +1 -1
- package/dist/types.d.ts +75 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +18 -1
- package/dist/utils.js.map +1 -1
- package/package.json +4 -3
- package/src/analysis-worker.ts +9 -301
- package/src/analysis.ts +151 -77
- package/src/config.ts +6 -193
- package/src/definitions/analysis-tools.ts +127 -0
- package/src/definitions/context-tools.ts +147 -0
- package/src/definitions/graph-tools.ts +126 -0
- package/src/definitions/graphql-tools.ts +64 -0
- package/src/definitions/guarantee-tools.ts +138 -0
- package/src/definitions/index.ts +28 -0
- package/src/definitions/knowledge-tools.ts +302 -0
- package/src/definitions/notation-tools.ts +64 -0
- package/src/definitions/project-tools.ts +183 -0
- package/src/definitions/query-tools.ts +247 -0
- package/src/definitions/types.ts +22 -0
- package/src/dev-proxy.ts +336 -0
- package/src/handlers/analysis-handlers.ts +35 -4
- package/src/handlers/context-handlers.ts +19 -15
- package/src/handlers/coverage-handlers.ts +1 -1
- package/src/handlers/dataflow-handlers.ts +74 -56
- package/src/handlers/documentation-handlers.ts +56 -2
- package/src/handlers/graph-handlers.ts +212 -0
- package/src/handlers/graphql-handlers.ts +70 -0
- package/src/handlers/guarantee-handlers.ts +1 -1
- package/src/handlers/guard-handlers.ts +7 -3
- package/src/handlers/index.ts +6 -0
- package/src/handlers/issue-handlers.ts +10 -15
- package/src/handlers/knowledge-handlers.ts +242 -0
- package/src/handlers/notation-handlers.ts +71 -0
- package/src/handlers/project-handlers.ts +1 -1
- package/src/handlers/query-handlers.ts +186 -22
- package/src/prompts.ts +1 -1
- package/src/server.ts +126 -2
- package/src/state.ts +68 -8
- package/src/types.ts +98 -3
- package/src/utils.ts +22 -1
- package/src/definitions.ts +0 -665
package/src/server.ts
CHANGED
|
@@ -2,7 +2,25 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Grafema MCP Server
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Graph-driven code analysis for AI agents. Query the code graph instead of reading files.
|
|
6
|
+
*
|
|
7
|
+
* Use Grafema when you need to:
|
|
8
|
+
* - Navigate code structure (find callers, trace data flow, understand impact)
|
|
9
|
+
* - Answer "who calls this?", "where is this used?", "what does this affect?"
|
|
10
|
+
* - Analyze untyped/dynamic codebases where static analysis falls short
|
|
11
|
+
* - Track relationships across files without manual grep
|
|
12
|
+
*
|
|
13
|
+
* Core capabilities:
|
|
14
|
+
* - Datalog queries for pattern matching (query_graph)
|
|
15
|
+
* - Call graph navigation (find_calls, get_function_details)
|
|
16
|
+
* - Data flow tracing (trace_dataflow, trace_alias)
|
|
17
|
+
* - Graph traversal primitives (get_node, get_neighbors, traverse_graph)
|
|
18
|
+
* - Code guarantees/invariants (create_guarantee, check_guarantees)
|
|
19
|
+
*
|
|
20
|
+
* Workflow:
|
|
21
|
+
* 1. discover_services — identify project structure
|
|
22
|
+
* 2. analyze_project — build the graph
|
|
23
|
+
* 3. Use query tools to explore code relationships
|
|
6
24
|
*/
|
|
7
25
|
|
|
8
26
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
@@ -15,7 +33,7 @@ import {
|
|
|
15
33
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
16
34
|
import { PROMPTS, getPrompt } from './prompts.js';
|
|
17
35
|
|
|
18
|
-
import { TOOLS } from './definitions.js';
|
|
36
|
+
import { TOOLS } from './definitions/index.js';
|
|
19
37
|
import { initializeFromArgs, setupLogging, getProjectPath } from './state.js';
|
|
20
38
|
import { textResult, errorResult, log } from './utils.js';
|
|
21
39
|
import { discoverServices } from './analysis.js';
|
|
@@ -43,6 +61,21 @@ import {
|
|
|
43
61
|
handleReadProjectStructure,
|
|
44
62
|
handleWriteConfig,
|
|
45
63
|
handleGetFileOverview,
|
|
64
|
+
handleGetNode,
|
|
65
|
+
handleGetNeighbors,
|
|
66
|
+
handleTraverseGraph,
|
|
67
|
+
handleAddKnowledge,
|
|
68
|
+
handleQueryKnowledge,
|
|
69
|
+
handleQueryDecisions,
|
|
70
|
+
handleSupersedeFact,
|
|
71
|
+
handleGetKnowledgeStats,
|
|
72
|
+
// Disabled: requires git-ingest (US-17). See US-17 in AI-AGENT-STORIES.md
|
|
73
|
+
// handleGitChurn,
|
|
74
|
+
// handleGitCoChange,
|
|
75
|
+
// handleGitOwnership,
|
|
76
|
+
// handleGitArchaeology,
|
|
77
|
+
handleDescribe,
|
|
78
|
+
handleGraphQLQuery,
|
|
46
79
|
} from './handlers/index.js';
|
|
47
80
|
import type {
|
|
48
81
|
ToolResult,
|
|
@@ -66,6 +99,20 @@ import type {
|
|
|
66
99
|
ReadProjectStructureArgs,
|
|
67
100
|
WriteConfigArgs,
|
|
68
101
|
GetFileOverviewArgs,
|
|
102
|
+
GetNodeArgs,
|
|
103
|
+
GetNeighborsArgs,
|
|
104
|
+
TraverseGraphArgs,
|
|
105
|
+
AddKnowledgeArgs,
|
|
106
|
+
QueryKnowledgeArgs,
|
|
107
|
+
QueryDecisionsArgs,
|
|
108
|
+
SupersedeFactArgs,
|
|
109
|
+
// Disabled: requires git-ingest (US-17). See US-17 in AI-AGENT-STORIES.md
|
|
110
|
+
// GitChurnArgs,
|
|
111
|
+
// GitCoChangeArgs,
|
|
112
|
+
// GitOwnershipArgs,
|
|
113
|
+
// GitArchaeologyArgs,
|
|
114
|
+
DescribeArgs,
|
|
115
|
+
GraphQLQueryArgs,
|
|
69
116
|
} from './types.js';
|
|
70
117
|
|
|
71
118
|
/**
|
|
@@ -89,12 +136,32 @@ const server = new Server(
|
|
|
89
136
|
{
|
|
90
137
|
name: 'grafema-mcp',
|
|
91
138
|
version: '0.1.0',
|
|
139
|
+
description: 'Graph-driven code analysis. Query the code graph instead of reading files. Navigate call graphs, trace data flow, verify guarantees. For AI agents working with untyped/dynamic codebases.',
|
|
92
140
|
},
|
|
93
141
|
{
|
|
94
142
|
capabilities: {
|
|
95
143
|
tools: {},
|
|
96
144
|
prompts: {},
|
|
97
145
|
},
|
|
146
|
+
instructions: `Grafema is a code graph — use it instead of reading files.
|
|
147
|
+
|
|
148
|
+
START HERE: call get_stats to check if the graph is loaded (nodeCount > 0).
|
|
149
|
+
If nodeCount is 0, call analyze_project first.
|
|
150
|
+
|
|
151
|
+
EXPLORATION WORKFLOW:
|
|
152
|
+
1. To understand a file → get_file_overview (shows imports, exports, functions, classes with relationships)
|
|
153
|
+
2. To find functions/classes/modules → find_nodes (filter by type, name, or file pattern)
|
|
154
|
+
3. To find who calls a function → find_calls (returns call sites with resolution status)
|
|
155
|
+
4. To understand data flow → trace_dataflow (forward: where does this value go? backward: where does it come from?)
|
|
156
|
+
5. To understand full context of a node → get_context (shows surrounding code, scope chain, relationships)
|
|
157
|
+
6. For complex pattern queries → query_graph with Datalog (call get_documentation topic="queries" for syntax)
|
|
158
|
+
7. To query architectural decisions and facts → query_knowledge, query_decisions, get_knowledge_stats
|
|
159
|
+
8. To get a compact visual summary → describe (renders DSL notation with archetype-grouped operators)
|
|
160
|
+
9. For DSL syntax reference → get_documentation topic="notation"
|
|
161
|
+
|
|
162
|
+
KEY INSIGHT: find_nodes supports partial matching on name and file fields.
|
|
163
|
+
Example: find_nodes(file="auth/") returns all nodes in files matching "auth/".
|
|
164
|
+
Example: find_nodes(name="redis", type="CALL") finds all calls containing "redis".`,
|
|
98
165
|
}
|
|
99
166
|
);
|
|
100
167
|
|
|
@@ -223,6 +290,63 @@ server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
|
223
290
|
result = await handleWriteConfig(asArgs<WriteConfigArgs>(args));
|
|
224
291
|
break;
|
|
225
292
|
|
|
293
|
+
case 'get_node':
|
|
294
|
+
result = await handleGetNode(asArgs<GetNodeArgs>(args));
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
case 'get_neighbors':
|
|
298
|
+
result = await handleGetNeighbors(asArgs<GetNeighborsArgs>(args));
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
case 'traverse_graph':
|
|
302
|
+
result = await handleTraverseGraph(asArgs<TraverseGraphArgs>(args));
|
|
303
|
+
break;
|
|
304
|
+
|
|
305
|
+
case 'add_knowledge':
|
|
306
|
+
result = await handleAddKnowledge(asArgs<AddKnowledgeArgs>(args));
|
|
307
|
+
break;
|
|
308
|
+
|
|
309
|
+
case 'query_knowledge':
|
|
310
|
+
result = await handleQueryKnowledge(asArgs<QueryKnowledgeArgs>(args));
|
|
311
|
+
break;
|
|
312
|
+
|
|
313
|
+
case 'query_decisions':
|
|
314
|
+
result = await handleQueryDecisions(asArgs<QueryDecisionsArgs>(args));
|
|
315
|
+
break;
|
|
316
|
+
|
|
317
|
+
case 'supersede_fact':
|
|
318
|
+
result = await handleSupersedeFact(asArgs<SupersedeFactArgs>(args));
|
|
319
|
+
break;
|
|
320
|
+
|
|
321
|
+
case 'get_knowledge_stats':
|
|
322
|
+
result = await handleGetKnowledgeStats();
|
|
323
|
+
break;
|
|
324
|
+
|
|
325
|
+
// Disabled: requires git-ingest (US-17). See US-17 in AI-AGENT-STORIES.md
|
|
326
|
+
// case 'git_churn':
|
|
327
|
+
// result = await handleGitChurn(asArgs<GitChurnArgs>(args));
|
|
328
|
+
// break;
|
|
329
|
+
//
|
|
330
|
+
// case 'git_cochange':
|
|
331
|
+
// result = await handleGitCoChange(asArgs<GitCoChangeArgs>(args));
|
|
332
|
+
// break;
|
|
333
|
+
//
|
|
334
|
+
// case 'git_ownership':
|
|
335
|
+
// result = await handleGitOwnership(asArgs<GitOwnershipArgs>(args));
|
|
336
|
+
// break;
|
|
337
|
+
//
|
|
338
|
+
// case 'git_archaeology':
|
|
339
|
+
// result = await handleGitArchaeology(asArgs<GitArchaeologyArgs>(args));
|
|
340
|
+
// break;
|
|
341
|
+
|
|
342
|
+
case 'describe':
|
|
343
|
+
result = await handleDescribe(asArgs<DescribeArgs>(args));
|
|
344
|
+
break;
|
|
345
|
+
|
|
346
|
+
case 'query_graphql':
|
|
347
|
+
result = await handleGraphQLQuery(asArgs<GraphQLQueryArgs>(args));
|
|
348
|
+
break;
|
|
349
|
+
|
|
226
350
|
default:
|
|
227
351
|
result = errorResult(`Unknown tool: ${name}`);
|
|
228
352
|
}
|
package/src/state.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { join } from 'path';
|
|
6
6
|
import { existsSync, mkdirSync } from 'fs';
|
|
7
|
-
import { RFDBServerBackend, GuaranteeManager, GuaranteeAPI } from '@grafema/
|
|
8
|
-
import type { GuaranteeGraphBackend, GuaranteeGraph } from '@grafema/
|
|
7
|
+
import { RFDBServerBackend, GuaranteeManager, GuaranteeAPI, KnowledgeBase } from '@grafema/util';
|
|
8
|
+
import type { GuaranteeGraphBackend, GuaranteeGraph, ResolverBackend } from '@grafema/util';
|
|
9
9
|
import { loadConfig } from './config.js';
|
|
10
10
|
import { log, initLogger } from './utils.js';
|
|
11
11
|
import type { AnalysisStatus } from './types.js';
|
|
@@ -21,6 +21,9 @@ let backgroundPid: number | null = null;
|
|
|
21
21
|
let guaranteeManager: GuaranteeManager | null = null;
|
|
22
22
|
let guaranteeAPI: GuaranteeAPI | null = null;
|
|
23
23
|
|
|
24
|
+
// Knowledge base
|
|
25
|
+
let knowledgeBase: KnowledgeBase | null = null;
|
|
26
|
+
|
|
24
27
|
let analysisStatus: AnalysisStatus = {
|
|
25
28
|
running: false,
|
|
26
29
|
phase: null,
|
|
@@ -112,6 +115,10 @@ export function getGuaranteeAPI(): GuaranteeAPI | null {
|
|
|
112
115
|
return guaranteeAPI;
|
|
113
116
|
}
|
|
114
117
|
|
|
118
|
+
export function getKnowledgeBase(): KnowledgeBase | null {
|
|
119
|
+
return knowledgeBase;
|
|
120
|
+
}
|
|
121
|
+
|
|
115
122
|
// === SETTERS ===
|
|
116
123
|
export function setProjectPath(path: string): void {
|
|
117
124
|
projectPath = path;
|
|
@@ -213,9 +220,28 @@ export async function waitForAnalysis(): Promise<void> {
|
|
|
213
220
|
}
|
|
214
221
|
}
|
|
215
222
|
|
|
216
|
-
// ===
|
|
223
|
+
// === RESET ===
|
|
224
|
+
export function resetBackend(): void {
|
|
225
|
+
backend = null;
|
|
226
|
+
isAnalyzed = false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function resetKnowledgeBase(): void {
|
|
230
|
+
knowledgeBase = null;
|
|
231
|
+
}
|
|
232
|
+
|
|
217
233
|
export async function getOrCreateBackend(): Promise<GraphBackend> {
|
|
218
|
-
if
|
|
234
|
+
// Check if existing backend is still connected
|
|
235
|
+
if (backend) {
|
|
236
|
+
const rfdb = backend as unknown as RFDBServerBackend;
|
|
237
|
+
if (rfdb.connected) return backend;
|
|
238
|
+
// Connection died — reset and recreate
|
|
239
|
+
log('[Grafema MCP] Backend disconnected, reconnecting...');
|
|
240
|
+
backend = null;
|
|
241
|
+
isAnalyzed = false;
|
|
242
|
+
guaranteeManager = null;
|
|
243
|
+
guaranteeAPI = null;
|
|
244
|
+
}
|
|
219
245
|
|
|
220
246
|
const grafemaDir = join(projectPath, '.grafema');
|
|
221
247
|
const dbPath = join(grafemaDir, 'graph.rfdb');
|
|
@@ -230,7 +256,7 @@ export async function getOrCreateBackend(): Promise<GraphBackend> {
|
|
|
230
256
|
|
|
231
257
|
log(`[Grafema MCP] Using RFDB server backend: socket=${socketPath || 'auto'}, db=${dbPath}`);
|
|
232
258
|
|
|
233
|
-
const rfdbBackend = new RFDBServerBackend({ socketPath, dbPath });
|
|
259
|
+
const rfdbBackend = new RFDBServerBackend({ socketPath, dbPath, clientName: 'mcp' });
|
|
234
260
|
await rfdbBackend.connect();
|
|
235
261
|
backend = rfdbBackend as unknown as GraphBackend;
|
|
236
262
|
|
|
@@ -243,21 +269,32 @@ export async function getOrCreateBackend(): Promise<GraphBackend> {
|
|
|
243
269
|
}
|
|
244
270
|
|
|
245
271
|
// Initialize guarantee managers
|
|
246
|
-
initializeGuaranteeManagers(rfdbBackend);
|
|
272
|
+
await initializeGuaranteeManagers(rfdbBackend);
|
|
247
273
|
|
|
248
274
|
return backend;
|
|
249
275
|
}
|
|
250
276
|
|
|
251
277
|
/**
|
|
252
|
-
* Initialize GuaranteeManager (Datalog-based) and GuaranteeAPI (contract-based)
|
|
278
|
+
* Initialize GuaranteeManager (Datalog-based) and GuaranteeAPI (contract-based).
|
|
279
|
+
* Loads guarantees from .grafema/guarantees.yaml if the file exists.
|
|
253
280
|
*/
|
|
254
|
-
function initializeGuaranteeManagers(rfdbBackend: RFDBServerBackend): void {
|
|
281
|
+
async function initializeGuaranteeManagers(rfdbBackend: RFDBServerBackend): Promise<void> {
|
|
255
282
|
// GuaranteeManager for Datalog-based guarantees
|
|
256
283
|
// Cast to GuaranteeGraph interface expected by GuaranteeManager
|
|
257
284
|
const guaranteeGraph = rfdbBackend as unknown as GuaranteeGraph;
|
|
258
285
|
guaranteeManager = new GuaranteeManager(guaranteeGraph, projectPath);
|
|
259
286
|
log(`[Grafema MCP] GuaranteeManager initialized`);
|
|
260
287
|
|
|
288
|
+
// Load guarantees from YAML (idempotent, skips existing)
|
|
289
|
+
try {
|
|
290
|
+
const result = await guaranteeManager.loadFromYaml();
|
|
291
|
+
if (result.imported > 0 || result.skipped > 0) {
|
|
292
|
+
log(`[Grafema MCP] Guarantees loaded from YAML: ${result.imported} imported, ${result.skipped} skipped`);
|
|
293
|
+
}
|
|
294
|
+
} catch (err) {
|
|
295
|
+
log(`[Grafema MCP] Warning: failed to load guarantees from YAML: ${err instanceof Error ? err.message : String(err)}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
261
298
|
// GuaranteeAPI for contract-based guarantees
|
|
262
299
|
const guaranteeGraphBackend = rfdbBackend as unknown as GuaranteeGraphBackend;
|
|
263
300
|
guaranteeAPI = new GuaranteeAPI(guaranteeGraphBackend);
|
|
@@ -277,6 +314,29 @@ export function setupLogging(): void {
|
|
|
277
314
|
initLogger(grafemaDir);
|
|
278
315
|
}
|
|
279
316
|
|
|
317
|
+
// === KNOWLEDGE BASE ===
|
|
318
|
+
/**
|
|
319
|
+
* Get or create the KnowledgeBase singleton.
|
|
320
|
+
* Lazy-initializes from knowledge/ directory on first access.
|
|
321
|
+
* If a backend is available, wires up the SemanticAddressResolver.
|
|
322
|
+
*/
|
|
323
|
+
export async function getOrCreateKnowledgeBase(): Promise<KnowledgeBase> {
|
|
324
|
+
if (knowledgeBase) return knowledgeBase;
|
|
325
|
+
|
|
326
|
+
const kbDir = join(projectPath, 'knowledge');
|
|
327
|
+
knowledgeBase = new KnowledgeBase(kbDir);
|
|
328
|
+
await knowledgeBase.load();
|
|
329
|
+
log(`[Grafema MCP] KnowledgeBase loaded from ${kbDir}`);
|
|
330
|
+
|
|
331
|
+
// Wire up resolver with backend if available (cast to ResolverBackend — RFDBServerBackend has getAllNodes)
|
|
332
|
+
if (backend) {
|
|
333
|
+
knowledgeBase.setBackend(backend as unknown as ResolverBackend);
|
|
334
|
+
log(`[Grafema MCP] KnowledgeBase resolver wired to backend`);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return knowledgeBase;
|
|
338
|
+
}
|
|
339
|
+
|
|
280
340
|
// === INITIALIZATION ===
|
|
281
341
|
export function initializeFromArgs(): void {
|
|
282
342
|
const args = process.argv.slice(2);
|
package/src/types.ts
CHANGED
|
@@ -36,20 +36,23 @@ export interface PaginationParams {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// === CONFIG ===
|
|
39
|
-
export type { GrafemaConfig } from '@grafema/
|
|
39
|
+
export type { GrafemaConfig } from '@grafema/util';
|
|
40
40
|
export type { MCPConfig } from './config.js';
|
|
41
41
|
|
|
42
42
|
// === TOOL ARGUMENTS ===
|
|
43
43
|
export interface QueryGraphArgs {
|
|
44
44
|
query: string;
|
|
45
|
+
language?: 'datalog' | 'cypher';
|
|
45
46
|
limit?: number;
|
|
46
47
|
offset?: number;
|
|
47
48
|
format?: 'table' | 'json' | 'tree';
|
|
48
49
|
explain?: boolean;
|
|
50
|
+
/** When true, returns only the count of matching results instead of the full result list */
|
|
51
|
+
count?: boolean;
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
export interface FindCallsArgs {
|
|
52
|
-
|
|
55
|
+
name: string;
|
|
53
56
|
limit?: number;
|
|
54
57
|
offset?: number;
|
|
55
58
|
include_indirect?: boolean;
|
|
@@ -68,6 +71,7 @@ export interface TraceDataFlowArgs {
|
|
|
68
71
|
direction?: 'forward' | 'backward' | 'both';
|
|
69
72
|
max_depth?: number;
|
|
70
73
|
limit?: number;
|
|
74
|
+
detail?: 'summary' | 'normal' | 'full';
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
export interface CheckInvariantArgs {
|
|
@@ -265,7 +269,7 @@ export interface GetFunctionDetailsArgs {
|
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
// Re-export types from core for convenience
|
|
268
|
-
export type { CallInfo, CallerInfo, FindCallsOptions } from '@grafema/
|
|
272
|
+
export type { CallInfo, CallerInfo, FindCallsOptions } from '@grafema/util';
|
|
269
273
|
|
|
270
274
|
/**
|
|
271
275
|
* Datalog query result binding
|
|
@@ -343,3 +347,94 @@ export interface WriteConfigArgs {
|
|
|
343
347
|
roots?: string[];
|
|
344
348
|
};
|
|
345
349
|
}
|
|
350
|
+
|
|
351
|
+
// === Graph traversal tools (REG-521) ===
|
|
352
|
+
|
|
353
|
+
export interface GetNodeArgs {
|
|
354
|
+
semanticId: string;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export interface GetNeighborsArgs {
|
|
358
|
+
semanticId: string;
|
|
359
|
+
direction?: 'outgoing' | 'incoming' | 'both';
|
|
360
|
+
edgeTypes?: string[];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface TraverseGraphArgs {
|
|
364
|
+
startNodeIds: string[];
|
|
365
|
+
edgeTypes: string[];
|
|
366
|
+
maxDepth?: number;
|
|
367
|
+
direction?: 'outgoing' | 'incoming';
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// === KNOWLEDGE ARGS (REG-626) ===
|
|
371
|
+
|
|
372
|
+
export interface AddKnowledgeArgs {
|
|
373
|
+
type: string;
|
|
374
|
+
content: string;
|
|
375
|
+
slug?: string;
|
|
376
|
+
subtype?: string;
|
|
377
|
+
scope?: string;
|
|
378
|
+
relates_to?: string[];
|
|
379
|
+
projections?: string[];
|
|
380
|
+
status?: string;
|
|
381
|
+
confidence?: string;
|
|
382
|
+
effective_from?: string;
|
|
383
|
+
applies_to?: string[];
|
|
384
|
+
task_id?: string;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export interface QueryKnowledgeArgs {
|
|
388
|
+
type?: string;
|
|
389
|
+
projection?: string;
|
|
390
|
+
relates_to?: string;
|
|
391
|
+
text?: string;
|
|
392
|
+
include_dangling_only?: boolean;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export interface QueryDecisionsArgs {
|
|
396
|
+
module?: string;
|
|
397
|
+
status?: string;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export interface SupersedeFactArgs {
|
|
401
|
+
old_id: string;
|
|
402
|
+
new_content: string;
|
|
403
|
+
new_slug?: string;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// === DESCRIBE ARGS (DSL notation) ===
|
|
407
|
+
|
|
408
|
+
export interface DescribeArgs {
|
|
409
|
+
target: string;
|
|
410
|
+
depth?: number;
|
|
411
|
+
perspective?: string;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// === GIT QUERY ARGS (REG-628) ===
|
|
415
|
+
|
|
416
|
+
export interface GitChurnArgs {
|
|
417
|
+
limit?: number;
|
|
418
|
+
since?: string;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export interface GitCoChangeArgs {
|
|
422
|
+
file: string;
|
|
423
|
+
min_support?: number;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export interface GitOwnershipArgs {
|
|
427
|
+
file: string;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export interface GitArchaeologyArgs {
|
|
431
|
+
file: string;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// === GRAPHQL ARGS (REG-666) ===
|
|
435
|
+
|
|
436
|
+
export interface GraphQLQueryArgs {
|
|
437
|
+
query: string;
|
|
438
|
+
variables?: Record<string, unknown>;
|
|
439
|
+
operationName?: string;
|
|
440
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -108,7 +108,7 @@ export function findSimilarTypes(
|
|
|
108
108
|
|
|
109
109
|
for (const type of availableTypes) {
|
|
110
110
|
const dist = levenshtein(queriedLower, type.toLowerCase());
|
|
111
|
-
if (dist
|
|
111
|
+
if (dist <= maxDistance && (dist > 0 || queriedType !== type)) {
|
|
112
112
|
similar.push(type);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
@@ -116,6 +116,27 @@ export function findSimilarTypes(
|
|
|
116
116
|
return similar;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
export function extractQueriedTypes(query: string): { nodeTypes: string[]; edgeTypes: string[] } {
|
|
120
|
+
const nodeTypes: string[] = [];
|
|
121
|
+
const edgeTypes: string[] = [];
|
|
122
|
+
|
|
123
|
+
// Match node(VAR, "TYPE") and type(VAR, "TYPE") — both are valid node predicates.
|
|
124
|
+
// type() is an alias for node(), added in REG-518.
|
|
125
|
+
const nodeRegex = /\b(?:node|type)\([^,)]+,\s*"([^"]+)"\)/g;
|
|
126
|
+
let m: RegExpExecArray | null;
|
|
127
|
+
while ((m = nodeRegex.exec(query)) !== null) {
|
|
128
|
+
nodeTypes.push(m[1]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Match edge(SRC, DST, "TYPE") and incoming(DST, SRC, "TYPE")
|
|
132
|
+
const edgeRegex = /\b(?:edge|incoming)\([^,)]+,\s*[^,)]+,\s*"([^"]+)"\)/g;
|
|
133
|
+
while ((m = edgeRegex.exec(query)) !== null) {
|
|
134
|
+
edgeTypes.push(m[1]);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return { nodeTypes, edgeTypes };
|
|
138
|
+
}
|
|
139
|
+
|
|
119
140
|
// Levenshtein distance implementation
|
|
120
141
|
export function levenshtein(a: string, b: string): number {
|
|
121
142
|
const m = a.length;
|