@grafema/mcp 0.1.0-alpha.1
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 -0
- package/README.md +67 -0
- package/dist/analysis-worker.d.ts +9 -0
- package/dist/analysis-worker.d.ts.map +1 -0
- package/dist/analysis-worker.js +194 -0
- package/dist/analysis.d.ts +13 -0
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +116 -0
- package/dist/config.d.ts +34 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +165 -0
- package/dist/definitions.d.ts +23 -0
- package/dist/definitions.d.ts.map +1 -0
- package/dist/definitions.js +419 -0
- package/dist/handlers.d.ts +34 -0
- package/dist/handlers.d.ts.map +1 -0
- package/dist/handlers.js +747 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +122 -0
- package/dist/state.d.ts +23 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +138 -0
- package/dist/types.d.ts +197 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/utils.d.ts +24 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +180 -0
- package/package.json +53 -0
- package/src/.rfguard/current-session.txt +1 -0
- package/src/analysis-worker.ts +286 -0
- package/src/analysis.ts +158 -0
- package/src/config.ts +240 -0
- package/src/definitions.ts +438 -0
- package/src/handlers.ts +918 -0
- package/src/server.ts +178 -0
- package/src/state.ts +169 -0
- package/src/types.ts +245 -0
- package/src/utils.ts +204 -0
package/src/server.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Grafema MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Provides code analysis tools via Model Context Protocol.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
|
+
import {
|
|
11
|
+
CallToolRequestSchema,
|
|
12
|
+
ListToolsRequestSchema,
|
|
13
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
14
|
+
|
|
15
|
+
import { TOOLS } from './definitions.js';
|
|
16
|
+
import { initializeFromArgs, setupLogging, getProjectPath } from './state.js';
|
|
17
|
+
import { textResult, errorResult, log } from './utils.js';
|
|
18
|
+
import { ensureAnalyzed, discoverServices } from './analysis.js';
|
|
19
|
+
import {
|
|
20
|
+
handleQueryGraph,
|
|
21
|
+
handleFindCalls,
|
|
22
|
+
handleFindNodes,
|
|
23
|
+
handleTraceAlias,
|
|
24
|
+
handleTraceDataFlow,
|
|
25
|
+
handleCheckInvariant,
|
|
26
|
+
handleAnalyzeProject,
|
|
27
|
+
handleGetAnalysisStatus,
|
|
28
|
+
handleGetStats,
|
|
29
|
+
handleGetSchema,
|
|
30
|
+
handleCreateGuarantee,
|
|
31
|
+
handleListGuarantees,
|
|
32
|
+
handleCheckGuarantees,
|
|
33
|
+
handleDeleteGuarantee,
|
|
34
|
+
handleGetCoverage,
|
|
35
|
+
handleGetDocumentation,
|
|
36
|
+
handleReportIssue,
|
|
37
|
+
} from './handlers.js';
|
|
38
|
+
import type { ToolResult, ReportIssueArgs, GetDocumentationArgs } from './types.js';
|
|
39
|
+
|
|
40
|
+
// Initialize from command line args
|
|
41
|
+
initializeFromArgs();
|
|
42
|
+
setupLogging();
|
|
43
|
+
|
|
44
|
+
const projectPath = getProjectPath();
|
|
45
|
+
log(`[Grafema MCP] Starting server for project: ${projectPath}`);
|
|
46
|
+
|
|
47
|
+
// Create MCP server
|
|
48
|
+
const server = new Server(
|
|
49
|
+
{
|
|
50
|
+
name: 'grafema-mcp',
|
|
51
|
+
version: '0.1.0',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
capabilities: {
|
|
55
|
+
tools: {},
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// List available tools
|
|
61
|
+
server.setRequestHandler(ListToolsRequestSchema, async (_request, _extra) => {
|
|
62
|
+
return { tools: TOOLS };
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Handle tool calls
|
|
66
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
67
|
+
void extra; // suppress unused warning
|
|
68
|
+
const { name, arguments: args } = request.params;
|
|
69
|
+
|
|
70
|
+
const startTime = Date.now();
|
|
71
|
+
const argsPreview = args ? JSON.stringify(args).slice(0, 200) : '{}';
|
|
72
|
+
log(`[Grafema MCP] ▶ ${name} args=${argsPreview}`);
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
let result: ToolResult;
|
|
76
|
+
|
|
77
|
+
switch (name) {
|
|
78
|
+
case 'query_graph':
|
|
79
|
+
result = await handleQueryGraph(args as any);
|
|
80
|
+
break;
|
|
81
|
+
|
|
82
|
+
case 'find_calls':
|
|
83
|
+
result = await handleFindCalls(args as any);
|
|
84
|
+
break;
|
|
85
|
+
|
|
86
|
+
case 'find_nodes':
|
|
87
|
+
result = await handleFindNodes(args as any);
|
|
88
|
+
break;
|
|
89
|
+
|
|
90
|
+
case 'trace_alias':
|
|
91
|
+
result = await handleTraceAlias(args as any);
|
|
92
|
+
break;
|
|
93
|
+
|
|
94
|
+
case 'trace_dataflow':
|
|
95
|
+
result = await handleTraceDataFlow(args as any);
|
|
96
|
+
break;
|
|
97
|
+
|
|
98
|
+
case 'check_invariant':
|
|
99
|
+
result = await handleCheckInvariant(args as any);
|
|
100
|
+
break;
|
|
101
|
+
|
|
102
|
+
case 'discover_services':
|
|
103
|
+
const services = await discoverServices();
|
|
104
|
+
result = textResult(`Found ${services.length} service(s):\n${JSON.stringify(services, null, 2)}`);
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case 'analyze_project':
|
|
108
|
+
result = await handleAnalyzeProject(args as any);
|
|
109
|
+
break;
|
|
110
|
+
|
|
111
|
+
case 'get_analysis_status':
|
|
112
|
+
result = await handleGetAnalysisStatus();
|
|
113
|
+
break;
|
|
114
|
+
|
|
115
|
+
case 'get_stats':
|
|
116
|
+
result = await handleGetStats();
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case 'get_schema':
|
|
120
|
+
result = await handleGetSchema(args as any);
|
|
121
|
+
break;
|
|
122
|
+
|
|
123
|
+
case 'create_guarantee':
|
|
124
|
+
result = await handleCreateGuarantee(args as any);
|
|
125
|
+
break;
|
|
126
|
+
|
|
127
|
+
case 'list_guarantees':
|
|
128
|
+
result = await handleListGuarantees();
|
|
129
|
+
break;
|
|
130
|
+
|
|
131
|
+
case 'check_guarantees':
|
|
132
|
+
result = await handleCheckGuarantees(args as any);
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
case 'delete_guarantee':
|
|
136
|
+
result = await handleDeleteGuarantee(args as any);
|
|
137
|
+
break;
|
|
138
|
+
|
|
139
|
+
case 'get_coverage':
|
|
140
|
+
result = await handleGetCoverage(args as any);
|
|
141
|
+
break;
|
|
142
|
+
|
|
143
|
+
case 'get_documentation':
|
|
144
|
+
result = await handleGetDocumentation(args as GetDocumentationArgs);
|
|
145
|
+
break;
|
|
146
|
+
|
|
147
|
+
case 'report_issue':
|
|
148
|
+
result = await handleReportIssue(args as unknown as ReportIssueArgs);
|
|
149
|
+
break;
|
|
150
|
+
|
|
151
|
+
default:
|
|
152
|
+
result = errorResult(`Unknown tool: ${name}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const duration = Date.now() - startTime;
|
|
156
|
+
const resultSize = JSON.stringify(result).length;
|
|
157
|
+
const status = result.isError ? '✗' : '✓';
|
|
158
|
+
log(`[Grafema MCP] ${status} ${name} completed in ${duration}ms (${resultSize} bytes)`);
|
|
159
|
+
|
|
160
|
+
return result;
|
|
161
|
+
} catch (error) {
|
|
162
|
+
const duration = Date.now() - startTime;
|
|
163
|
+
log(`[Grafema MCP] ✗ ${name} FAILED after ${duration}ms: ${(error as Error).message}`);
|
|
164
|
+
return errorResult((error as Error).message);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Main entry point
|
|
169
|
+
async function main(): Promise<void> {
|
|
170
|
+
const transport = new StdioServerTransport();
|
|
171
|
+
await server.connect(transport);
|
|
172
|
+
log('[Grafema MCP] Server connected via stdio');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
main().catch((error) => {
|
|
176
|
+
log(`[Grafema MCP] Fatal error: ${error.message}`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
});
|
package/src/state.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server State Management
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
7
|
+
import { RFDBServerBackend, GuaranteeManager, GuaranteeAPI } from '@grafema/core';
|
|
8
|
+
import type { GuaranteeGraphBackend, GuaranteeGraph } from '@grafema/core';
|
|
9
|
+
import { loadConfig } from './config.js';
|
|
10
|
+
import { log, initLogger } from './utils.js';
|
|
11
|
+
import type { AnalysisStatus } from './types.js';
|
|
12
|
+
import type { GraphBackend } from '@grafema/types';
|
|
13
|
+
|
|
14
|
+
// === GLOBAL STATE ===
|
|
15
|
+
let projectPath: string = process.cwd();
|
|
16
|
+
let backend: GraphBackend | null = null;
|
|
17
|
+
let isAnalyzed: boolean = false;
|
|
18
|
+
let backgroundPid: number | null = null;
|
|
19
|
+
|
|
20
|
+
// Guarantee managers
|
|
21
|
+
let guaranteeManager: GuaranteeManager | null = null;
|
|
22
|
+
let guaranteeAPI: GuaranteeAPI | null = null;
|
|
23
|
+
|
|
24
|
+
let analysisStatus: AnalysisStatus = {
|
|
25
|
+
running: false,
|
|
26
|
+
phase: null,
|
|
27
|
+
message: null,
|
|
28
|
+
servicesDiscovered: 0,
|
|
29
|
+
servicesAnalyzed: 0,
|
|
30
|
+
startTime: null,
|
|
31
|
+
endTime: null,
|
|
32
|
+
error: null,
|
|
33
|
+
timings: {
|
|
34
|
+
discovery: null,
|
|
35
|
+
indexing: null,
|
|
36
|
+
analysis: null,
|
|
37
|
+
enrichment: null,
|
|
38
|
+
validation: null,
|
|
39
|
+
total: null,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// === GETTERS ===
|
|
44
|
+
export function getProjectPath(): string {
|
|
45
|
+
return projectPath;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function getIsAnalyzed(): boolean {
|
|
49
|
+
return isAnalyzed;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getAnalysisStatus(): AnalysisStatus {
|
|
53
|
+
return analysisStatus;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getBackgroundPid(): number | null {
|
|
57
|
+
return backgroundPid;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function getGuaranteeManager(): GuaranteeManager | null {
|
|
61
|
+
return guaranteeManager;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function getGuaranteeAPI(): GuaranteeAPI | null {
|
|
65
|
+
return guaranteeAPI;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// === SETTERS ===
|
|
69
|
+
export function setProjectPath(path: string): void {
|
|
70
|
+
projectPath = path;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function setIsAnalyzed(value: boolean): void {
|
|
74
|
+
isAnalyzed = value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function setAnalysisStatus(status: Partial<AnalysisStatus>): void {
|
|
78
|
+
analysisStatus = { ...analysisStatus, ...status };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function setBackgroundPid(pid: number | null): void {
|
|
82
|
+
backgroundPid = pid;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function updateAnalysisTimings(timings: Partial<AnalysisStatus['timings']>): void {
|
|
86
|
+
analysisStatus.timings = { ...analysisStatus.timings, ...timings };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// === BACKEND ===
|
|
90
|
+
export async function getOrCreateBackend(): Promise<GraphBackend> {
|
|
91
|
+
if (backend) return backend;
|
|
92
|
+
|
|
93
|
+
const grafemaDir = join(projectPath, '.grafema');
|
|
94
|
+
const dbPath = join(grafemaDir, 'graph.rfdb');
|
|
95
|
+
|
|
96
|
+
if (!existsSync(grafemaDir)) {
|
|
97
|
+
mkdirSync(grafemaDir, { recursive: true });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const config = loadConfig(projectPath);
|
|
101
|
+
// Socket path from config, or let RFDBServerBackend derive it from dbPath
|
|
102
|
+
const socketPath = (config as any).analysis?.parallel?.socketPath;
|
|
103
|
+
|
|
104
|
+
log(`[Grafema MCP] Using RFDB server backend: socket=${socketPath || 'auto'}, db=${dbPath}`);
|
|
105
|
+
|
|
106
|
+
const rfdbBackend = new RFDBServerBackend({ socketPath, dbPath });
|
|
107
|
+
await rfdbBackend.connect();
|
|
108
|
+
backend = rfdbBackend as unknown as GraphBackend;
|
|
109
|
+
|
|
110
|
+
const nodeCount = await backend.nodeCount();
|
|
111
|
+
if (nodeCount > 0) {
|
|
112
|
+
isAnalyzed = true;
|
|
113
|
+
log(`[Grafema MCP] Connected to existing database: ${nodeCount} nodes`);
|
|
114
|
+
} else {
|
|
115
|
+
log(`[Grafema MCP] Empty database, analysis needed`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Initialize guarantee managers
|
|
119
|
+
initializeGuaranteeManagers(rfdbBackend);
|
|
120
|
+
|
|
121
|
+
return backend;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Initialize GuaranteeManager (Datalog-based) and GuaranteeAPI (contract-based)
|
|
126
|
+
*/
|
|
127
|
+
function initializeGuaranteeManagers(rfdbBackend: RFDBServerBackend): void {
|
|
128
|
+
// GuaranteeManager for Datalog-based guarantees
|
|
129
|
+
// Cast to GuaranteeGraph interface expected by GuaranteeManager
|
|
130
|
+
const guaranteeGraph = rfdbBackend as unknown as GuaranteeGraph;
|
|
131
|
+
guaranteeManager = new GuaranteeManager(guaranteeGraph, projectPath);
|
|
132
|
+
log(`[Grafema MCP] GuaranteeManager initialized`);
|
|
133
|
+
|
|
134
|
+
// GuaranteeAPI for contract-based guarantees
|
|
135
|
+
const guaranteeGraphBackend = rfdbBackend as unknown as GuaranteeGraphBackend;
|
|
136
|
+
guaranteeAPI = new GuaranteeAPI(guaranteeGraphBackend);
|
|
137
|
+
log(`[Grafema MCP] GuaranteeAPI initialized`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function getBackendIfExists(): GraphBackend | null {
|
|
141
|
+
return backend;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// === LOGGING SETUP ===
|
|
145
|
+
export function setupLogging(): void {
|
|
146
|
+
const grafemaDir = join(projectPath, '.grafema');
|
|
147
|
+
if (!existsSync(grafemaDir)) {
|
|
148
|
+
mkdirSync(grafemaDir, { recursive: true });
|
|
149
|
+
}
|
|
150
|
+
initLogger(grafemaDir);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// === INITIALIZATION ===
|
|
154
|
+
export function initializeFromArgs(): void {
|
|
155
|
+
const args = process.argv.slice(2);
|
|
156
|
+
for (let i = 0; i < args.length; i++) {
|
|
157
|
+
if (args[i] === '--project' && args[i + 1]) {
|
|
158
|
+
projectPath = args[i + 1];
|
|
159
|
+
i++;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// === CLEANUP ===
|
|
165
|
+
export async function cleanup(): Promise<void> {
|
|
166
|
+
if (backend && 'close' in backend && typeof backend.close === 'function') {
|
|
167
|
+
await backend.close();
|
|
168
|
+
}
|
|
169
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { WriteStream } from 'fs';
|
|
6
|
+
|
|
7
|
+
// === ANALYSIS STATUS ===
|
|
8
|
+
export interface AnalysisTimings {
|
|
9
|
+
discovery: number | null;
|
|
10
|
+
indexing: number | null;
|
|
11
|
+
analysis: number | null;
|
|
12
|
+
enrichment: number | null;
|
|
13
|
+
validation: number | null;
|
|
14
|
+
total: number | null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface AnalysisStatus {
|
|
18
|
+
running: boolean;
|
|
19
|
+
phase: string | null;
|
|
20
|
+
message: string | null;
|
|
21
|
+
servicesDiscovered: number;
|
|
22
|
+
servicesAnalyzed: number;
|
|
23
|
+
startTime: number | null;
|
|
24
|
+
endTime: number | null;
|
|
25
|
+
error: string | null;
|
|
26
|
+
timings: AnalysisTimings;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// === PAGINATION ===
|
|
30
|
+
export interface PaginationParams {
|
|
31
|
+
limit: number;
|
|
32
|
+
offset: number;
|
|
33
|
+
returned: number;
|
|
34
|
+
total?: number;
|
|
35
|
+
hasMore: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// === CONFIG ===
|
|
39
|
+
export interface GrafemaConfig {
|
|
40
|
+
project_path?: string;
|
|
41
|
+
backend?: 'local' | 'rfdb';
|
|
42
|
+
rfdb_socket?: string;
|
|
43
|
+
plugins?: string[];
|
|
44
|
+
ignore_patterns?: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// === TOOL ARGUMENTS ===
|
|
48
|
+
export interface QueryGraphArgs {
|
|
49
|
+
query: string;
|
|
50
|
+
limit?: number;
|
|
51
|
+
offset?: number;
|
|
52
|
+
format?: 'table' | 'json' | 'tree';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface FindCallsArgs {
|
|
56
|
+
target: string;
|
|
57
|
+
limit?: number;
|
|
58
|
+
offset?: number;
|
|
59
|
+
include_indirect?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface TraceAliasArgs {
|
|
63
|
+
identifier: string;
|
|
64
|
+
file?: string;
|
|
65
|
+
max_depth?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface TraceDataFlowArgs {
|
|
69
|
+
source: string;
|
|
70
|
+
file?: string;
|
|
71
|
+
direction?: 'forward' | 'backward' | 'both';
|
|
72
|
+
max_depth?: number;
|
|
73
|
+
limit?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface CheckInvariantArgs {
|
|
77
|
+
rule: string;
|
|
78
|
+
name?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface GetSchemaArgs {
|
|
82
|
+
type?: 'nodes' | 'edges' | 'all';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface GetValueSetArgs {
|
|
86
|
+
node_id: string;
|
|
87
|
+
property?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface FindNodesArgs {
|
|
91
|
+
type?: string;
|
|
92
|
+
name?: string;
|
|
93
|
+
file?: string;
|
|
94
|
+
limit?: number;
|
|
95
|
+
offset?: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface AnalyzeProjectArgs {
|
|
99
|
+
service?: string;
|
|
100
|
+
force?: boolean;
|
|
101
|
+
index_only?: boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface GetCoverageArgs {
|
|
105
|
+
path?: string;
|
|
106
|
+
depth?: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface GetDocumentationArgs {
|
|
110
|
+
topic?: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// === GUARANTEE ARGS ===
|
|
114
|
+
|
|
115
|
+
// Priority levels for contract-based guarantees
|
|
116
|
+
export type GuaranteePriority = 'critical' | 'important' | 'observed' | 'tracked';
|
|
117
|
+
|
|
118
|
+
// Lifecycle status for contract-based guarantees
|
|
119
|
+
export type GuaranteeStatus = 'discovered' | 'reviewed' | 'active' | 'changing' | 'deprecated';
|
|
120
|
+
|
|
121
|
+
export interface CreateGuaranteeArgs {
|
|
122
|
+
name: string;
|
|
123
|
+
// Datalog-based guarantee fields (optional for contract-based)
|
|
124
|
+
rule?: string;
|
|
125
|
+
description?: string;
|
|
126
|
+
severity?: 'error' | 'warning' | 'info';
|
|
127
|
+
// Contract-based guarantee fields
|
|
128
|
+
type?: 'guarantee:queue' | 'guarantee:api' | 'guarantee:permission';
|
|
129
|
+
priority?: GuaranteePriority;
|
|
130
|
+
status?: GuaranteeStatus;
|
|
131
|
+
owner?: string;
|
|
132
|
+
schema?: Record<string, unknown>;
|
|
133
|
+
condition?: string;
|
|
134
|
+
governs?: string[]; // Node IDs that this guarantee governs
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface CheckGuaranteesArgs {
|
|
138
|
+
names?: string[];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface DeleteGuaranteeArgs {
|
|
142
|
+
name: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface ExportGuaranteesArgs {
|
|
146
|
+
format?: 'json' | 'yaml';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export interface ImportGuaranteesArgs {
|
|
150
|
+
guarantees: Array<{
|
|
151
|
+
name: string;
|
|
152
|
+
rule: string;
|
|
153
|
+
description?: string;
|
|
154
|
+
severity?: string;
|
|
155
|
+
}>;
|
|
156
|
+
merge?: boolean;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface GuaranteeDriftArgs {
|
|
160
|
+
baseline?: string;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface CheckGuaranteeFeasibilityArgs {
|
|
164
|
+
rule: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// === TOOL RESULT ===
|
|
168
|
+
export interface ToolResult {
|
|
169
|
+
[x: string]: unknown;
|
|
170
|
+
content: Array<{
|
|
171
|
+
type: 'text';
|
|
172
|
+
text: string;
|
|
173
|
+
}>;
|
|
174
|
+
isError?: boolean;
|
|
175
|
+
_meta?: Record<string, unknown>;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// === BACKEND INTERFACE (minimal) ===
|
|
179
|
+
export interface GraphBackend {
|
|
180
|
+
nodeCount(): Promise<number>;
|
|
181
|
+
edgeCount(): Promise<number>;
|
|
182
|
+
countNodesByType(types?: string[] | null): Promise<Record<string, number>>;
|
|
183
|
+
countEdgesByType(types?: string[] | null): Promise<Record<string, number>>;
|
|
184
|
+
getNode(id: string): Promise<GraphNode | null>;
|
|
185
|
+
findByType(type: string): Promise<string[]>;
|
|
186
|
+
findByAttr(query: Record<string, unknown>): Promise<string[]>;
|
|
187
|
+
getOutgoingEdges(id: string, types?: string[] | null): Promise<GraphEdge[]>;
|
|
188
|
+
getIncomingEdges(id: string, types?: string[] | null): Promise<GraphEdge[]>;
|
|
189
|
+
queryNodes(filter: Record<string, unknown>): AsyncIterable<GraphNode>;
|
|
190
|
+
getAllNodes(filter?: Record<string, unknown>): Promise<GraphNode[]>;
|
|
191
|
+
runDatalogQuery?(query: string): Promise<unknown[]>;
|
|
192
|
+
close?(): Promise<void>;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface GraphNode {
|
|
196
|
+
id: string;
|
|
197
|
+
type: string;
|
|
198
|
+
name: string;
|
|
199
|
+
file?: string;
|
|
200
|
+
line?: number;
|
|
201
|
+
[key: string]: unknown;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface GraphEdge {
|
|
205
|
+
src: string;
|
|
206
|
+
dst: string;
|
|
207
|
+
type: string;
|
|
208
|
+
edgeType?: string;
|
|
209
|
+
[key: string]: unknown;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// === GLOBAL STATE ===
|
|
213
|
+
export interface MCPState {
|
|
214
|
+
projectPath: string;
|
|
215
|
+
backend: GraphBackend | null;
|
|
216
|
+
isAnalyzed: boolean;
|
|
217
|
+
analysisStatus: AnalysisStatus;
|
|
218
|
+
logStream: WriteStream | null;
|
|
219
|
+
backgroundPid: number | null;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// === FILE CLASSIFICATION ===
|
|
223
|
+
export interface FileClassification {
|
|
224
|
+
category: 'source' | 'config' | 'test' | 'doc' | 'asset' | 'generated' | 'other';
|
|
225
|
+
language?: string;
|
|
226
|
+
framework?: string;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface ExtensionGroup {
|
|
230
|
+
[ext: string]: string[];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export interface AnalyzerSuggestion {
|
|
234
|
+
name: string;
|
|
235
|
+
reason: string;
|
|
236
|
+
priority: number;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// === BUG REPORTING ===
|
|
240
|
+
export interface ReportIssueArgs {
|
|
241
|
+
title: string;
|
|
242
|
+
description: string;
|
|
243
|
+
context?: string;
|
|
244
|
+
labels?: string[];
|
|
245
|
+
}
|