@rigstate/mcp 0.7.4 → 0.7.6
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/index.js +285 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/arch-analysis.ts +171 -0
- package/src/lib/curator/actions/submit.ts +8 -9
- package/src/lib/curator/schemas.ts +10 -4
- package/src/lib/project-context-utils.ts +139 -0
- package/src/lib/schemas.ts +10 -10
- package/src/lib/types-roadmap.ts +43 -0
- package/src/lib/types.ts +41 -25
- package/src/server/types.ts +1 -1
- package/src/tools/analyze-database-performance.ts +12 -0
- package/src/tools/archaeological-scan.ts +37 -214
- package/src/tools/audit-integrity-gate.ts +16 -4
- package/src/tools/check-agent-bridge.ts +11 -0
- package/src/tools/check-rules-sync.ts +13 -0
- package/src/tools/complete-roadmap-task.ts +12 -0
- package/src/tools/generate-professional-pdf.ts +17 -2
- package/src/tools/get-next-roadmap-step.ts +5 -1
- package/src/tools/get-project-context.ts +17 -79
- package/src/tools/list-features.ts +13 -3
- package/src/tools/list-roadmap-tasks.ts +6 -1
- package/src/tools/pending-tasks.ts +22 -0
- package/src/tools/query-brain.ts +8 -9
- package/src/tools/research-tools.ts +9 -8
- package/src/tools/run-architecture-audit.ts +8 -9
- package/src/tools/save-decision.ts +15 -9
- package/src/tools/security-tools.ts +26 -2
- package/src/tools/submit-idea.ts +15 -9
- package/src/tools/sync-ide-rules.ts +16 -3
- package/src/tools/teacher-mode.ts +6 -7
- package/src/tools/update-roadmap.ts +14 -8
|
@@ -48,8 +48,19 @@ export interface UpdateTaskStatusResponse {
|
|
|
48
48
|
*/
|
|
49
49
|
export async function getPendingTasks(
|
|
50
50
|
supabase: SupabaseClient,
|
|
51
|
+
userId: string,
|
|
51
52
|
projectId: string
|
|
52
53
|
): Promise<GetPendingTasksResponse> {
|
|
54
|
+
// 0. Verify project access
|
|
55
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
56
|
+
.rpc('check_project_access_secure', {
|
|
57
|
+
p_project_id: projectId,
|
|
58
|
+
p_user_id: userId
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (accessError || !hasAccess) {
|
|
62
|
+
throw new Error('Project not found or access denied');
|
|
63
|
+
}
|
|
53
64
|
|
|
54
65
|
// Fetch APPROVED tasks that are ready for execution
|
|
55
66
|
const { data: tasks, error } = await supabase
|
|
@@ -143,11 +154,22 @@ export async function getPendingTasks(
|
|
|
143
154
|
*/
|
|
144
155
|
export async function updateTaskStatus(
|
|
145
156
|
supabase: SupabaseClient,
|
|
157
|
+
userId: string,
|
|
146
158
|
projectId: string,
|
|
147
159
|
taskId: string,
|
|
148
160
|
newStatus: 'EXECUTING' | 'COMPLETED' | 'FAILED',
|
|
149
161
|
executionSummary?: string
|
|
150
162
|
): Promise<UpdateTaskStatusResponse> {
|
|
163
|
+
// 0. Verify project access
|
|
164
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
165
|
+
.rpc('check_project_access_secure', {
|
|
166
|
+
p_project_id: projectId,
|
|
167
|
+
p_user_id: userId
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (accessError || !hasAccess) {
|
|
171
|
+
throw new Error('Project not found or access denied');
|
|
172
|
+
}
|
|
151
173
|
|
|
152
174
|
// 1. Fetch the current task state
|
|
153
175
|
const { data: currentTask, error: fetchError } = await supabase
|
package/src/tools/query-brain.ts
CHANGED
|
@@ -75,15 +75,14 @@ export async function queryBrain(
|
|
|
75
75
|
limit: number = 8,
|
|
76
76
|
threshold: number = 0.5
|
|
77
77
|
): Promise<BrainQueryResponse> {
|
|
78
|
-
// First, verify project
|
|
79
|
-
const { data:
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (projectError || !project) {
|
|
78
|
+
// First, verify project access
|
|
79
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
80
|
+
.rpc('check_project_access_secure', {
|
|
81
|
+
p_project_id: projectId,
|
|
82
|
+
p_user_id: userId
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
if (accessError || !hasAccess) {
|
|
87
86
|
throw new Error('Project not found or access denied');
|
|
88
87
|
}
|
|
89
88
|
|
|
@@ -13,14 +13,15 @@ export async function queryProjectBrain(
|
|
|
13
13
|
const { projectId, query, limit = 5 } = input;
|
|
14
14
|
|
|
15
15
|
// Verify access
|
|
16
|
-
const { data:
|
|
17
|
-
.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
17
|
+
.rpc('check_project_access_secure', {
|
|
18
|
+
p_project_id: projectId,
|
|
19
|
+
p_user_id: userId
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (accessError || !hasAccess) {
|
|
23
|
+
throw new Error('Access denied or project not found');
|
|
24
|
+
}
|
|
24
25
|
|
|
25
26
|
// Simple keyword search
|
|
26
27
|
const terms = query.toLowerCase().split(/\s+/).filter(t => t.length > 2);
|
|
@@ -110,15 +110,14 @@ export async function runArchitectureAudit(
|
|
|
110
110
|
filePath: string,
|
|
111
111
|
content: string
|
|
112
112
|
): Promise<ArchitectureAuditResponse> {
|
|
113
|
-
// First, verify project
|
|
114
|
-
const { data:
|
|
115
|
-
.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (projectError || !project) {
|
|
113
|
+
// First, verify project access
|
|
114
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
115
|
+
.rpc('check_project_access_secure', {
|
|
116
|
+
p_project_id: projectId,
|
|
117
|
+
p_user_id: userId
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
if (accessError || !hasAccess) {
|
|
122
121
|
throw new Error('Project not found or access denied');
|
|
123
122
|
}
|
|
124
123
|
|
|
@@ -44,18 +44,24 @@ export async function saveDecision(
|
|
|
44
44
|
category: string = 'decision',
|
|
45
45
|
tags: string[] = []
|
|
46
46
|
): Promise<SaveDecisionResponse> {
|
|
47
|
-
//
|
|
48
|
-
const { data:
|
|
49
|
-
.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
.single();
|
|
47
|
+
// 1. Verify project access
|
|
48
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
49
|
+
.rpc('check_project_access_secure', {
|
|
50
|
+
p_project_id: projectId,
|
|
51
|
+
p_user_id: userId
|
|
52
|
+
});
|
|
54
53
|
|
|
55
|
-
if (
|
|
54
|
+
if (accessError || !hasAccess) {
|
|
56
55
|
throw new Error('Project not found or access denied');
|
|
57
56
|
}
|
|
58
57
|
|
|
58
|
+
// 2. Fetch project name for the response message
|
|
59
|
+
const { data: project } = await supabase
|
|
60
|
+
.from('projects')
|
|
61
|
+
.select('name')
|
|
62
|
+
.eq('id', projectId)
|
|
63
|
+
.single();
|
|
64
|
+
|
|
59
65
|
// Build the full content with title, decision, and rationale
|
|
60
66
|
const contentParts = [`# ${title}`, '', decision];
|
|
61
67
|
if (rationale) {
|
|
@@ -98,6 +104,6 @@ export async function saveDecision(
|
|
|
98
104
|
return {
|
|
99
105
|
success: true,
|
|
100
106
|
memoryId: memory.id,
|
|
101
|
-
message: `✅ Decision "${title}" saved to project "${project
|
|
107
|
+
message: `✅ Decision "${title}" saved to project "${project?.name || projectId}" with importance 9/10`
|
|
102
108
|
};
|
|
103
109
|
}
|
|
@@ -14,7 +14,7 @@ registry.register({
|
|
|
14
14
|
description: `Sven's Tool: Security Shield. Audits the database to ensure Row Level Security (RLS) is enforced.`,
|
|
15
15
|
schema: AuditRlsStatusInputSchema,
|
|
16
16
|
handler: async (args, context) => {
|
|
17
|
-
const result = await auditRlsStatus(context.supabase, args);
|
|
17
|
+
const result = await auditRlsStatus(context.supabase, context.userId, args);
|
|
18
18
|
return { content: [{ type: 'text', text: result.summary || 'No summary available' }] };
|
|
19
19
|
}
|
|
20
20
|
});
|
|
@@ -24,7 +24,7 @@ registry.register({
|
|
|
24
24
|
description: `Frank's Tool: Security Oracle. Performs a diagnostic security audit against the Fortress Matrix.`,
|
|
25
25
|
schema: AuditSecurityIntegrityInputSchema,
|
|
26
26
|
handler: async (args, context) => {
|
|
27
|
-
const result = await auditSecurityIntegrity(context.supabase, args);
|
|
27
|
+
const result = await auditSecurityIntegrity(context.supabase, context.userId, args);
|
|
28
28
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
29
29
|
}
|
|
30
30
|
});
|
|
@@ -35,8 +35,20 @@ registry.register({
|
|
|
35
35
|
*/
|
|
36
36
|
export async function auditRlsStatus(
|
|
37
37
|
supabase: SupabaseClient,
|
|
38
|
+
userId: string,
|
|
38
39
|
input: AuditRlsStatusInput
|
|
39
40
|
) {
|
|
41
|
+
// 0. Verify project access
|
|
42
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
43
|
+
.rpc('check_project_access_secure', {
|
|
44
|
+
p_project_id: input.projectId,
|
|
45
|
+
p_user_id: userId
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (accessError || !hasAccess) {
|
|
49
|
+
throw new Error('Project not found or access denied');
|
|
50
|
+
}
|
|
51
|
+
|
|
40
52
|
try {
|
|
41
53
|
const { data, error } = await supabase.rpc('execute_sql', {
|
|
42
54
|
query: `
|
|
@@ -97,8 +109,20 @@ export async function auditRlsStatus(
|
|
|
97
109
|
*/
|
|
98
110
|
export async function auditSecurityIntegrity(
|
|
99
111
|
supabase: SupabaseClient,
|
|
112
|
+
userId: string,
|
|
100
113
|
input: { projectId: string, filePath: string, content: string }
|
|
101
114
|
) {
|
|
115
|
+
// 0. Verify project access
|
|
116
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
117
|
+
.rpc('check_project_access_secure', {
|
|
118
|
+
p_project_id: input.projectId,
|
|
119
|
+
p_user_id: userId
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (accessError || !hasAccess) {
|
|
123
|
+
throw new Error('Project not found or access denied');
|
|
124
|
+
}
|
|
125
|
+
|
|
102
126
|
const violations: any[] = [];
|
|
103
127
|
const { content, filePath } = input;
|
|
104
128
|
|
package/src/tools/submit-idea.ts
CHANGED
|
@@ -42,18 +42,24 @@ export async function submitIdea(
|
|
|
42
42
|
category: string = 'feature',
|
|
43
43
|
tags: string[] = []
|
|
44
44
|
): Promise<SubmitIdeaResponse> {
|
|
45
|
-
//
|
|
46
|
-
const { data:
|
|
47
|
-
.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
.single();
|
|
45
|
+
// 1. Verify project access
|
|
46
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
47
|
+
.rpc('check_project_access_secure', {
|
|
48
|
+
p_project_id: projectId,
|
|
49
|
+
p_user_id: userId
|
|
50
|
+
});
|
|
52
51
|
|
|
53
|
-
if (
|
|
52
|
+
if (accessError || !hasAccess) {
|
|
54
53
|
throw new Error('Project not found or access denied');
|
|
55
54
|
}
|
|
56
55
|
|
|
56
|
+
// 2. Fetch project name for the response message
|
|
57
|
+
const { data: project } = await supabase
|
|
58
|
+
.from('projects')
|
|
59
|
+
.select('name')
|
|
60
|
+
.eq('id', projectId)
|
|
61
|
+
.single();
|
|
62
|
+
|
|
57
63
|
// Insert the idea into saved_ideas
|
|
58
64
|
const { data: idea, error: insertError } = await supabase
|
|
59
65
|
.from('saved_ideas')
|
|
@@ -86,6 +92,6 @@ export async function submitIdea(
|
|
|
86
92
|
return {
|
|
87
93
|
success: true,
|
|
88
94
|
ideaId: idea.id,
|
|
89
|
-
message: `💡 Idea "${title}" submitted to Idea Lab for project "${project
|
|
95
|
+
message: `💡 Idea "${title}" submitted to Idea Lab for project "${project?.name || projectId}". Status: Draft (awaiting review)`
|
|
90
96
|
};
|
|
91
97
|
}
|
|
@@ -22,7 +22,7 @@ registry.register({
|
|
|
22
22
|
based on project context and user settings.`,
|
|
23
23
|
schema: GenerateCursorRulesInputSchema,
|
|
24
24
|
handler: async (args, context) => {
|
|
25
|
-
const result = await syncIdeRules(context.supabase, args.projectId);
|
|
25
|
+
const result = await syncIdeRules(context.supabase, context.userId, args.projectId);
|
|
26
26
|
|
|
27
27
|
// Format response: Main file content + information about modular files
|
|
28
28
|
let responseText = `FileName: ${result.fileName}\n\nContent:\n${result.content}`;
|
|
@@ -43,14 +43,27 @@ based on project context and user settings.`,
|
|
|
43
43
|
* Uses the centralized rules-engine for consistent generation across all consumers.
|
|
44
44
|
*
|
|
45
45
|
* @param supabase - Supabase client instance
|
|
46
|
+
* @param userId - The user ID for access verification
|
|
46
47
|
* @param projectId - The project ID to generate rules for
|
|
47
48
|
* @returns Object with fileName, content, and the new modular files[] array
|
|
48
49
|
*/
|
|
49
50
|
export async function syncIdeRules(
|
|
50
51
|
supabase: SupabaseClient,
|
|
52
|
+
userId: string,
|
|
51
53
|
projectId: string
|
|
52
54
|
): Promise<{ fileName: string; content: string; files: RuleFile[] }> {
|
|
53
|
-
// 1.
|
|
55
|
+
// 1. Verify project access
|
|
56
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
57
|
+
.rpc('check_project_access_secure', {
|
|
58
|
+
p_project_id: projectId,
|
|
59
|
+
p_user_id: userId
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (accessError || !hasAccess) {
|
|
63
|
+
throw new Error('Project not found or access denied');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 2. Fetch Project & Preferred IDE
|
|
54
67
|
const { data: project, error: projectError } = await supabase
|
|
55
68
|
.from('projects')
|
|
56
69
|
.select('*')
|
|
@@ -58,7 +71,7 @@ export async function syncIdeRules(
|
|
|
58
71
|
.single();
|
|
59
72
|
|
|
60
73
|
if (projectError || !project) {
|
|
61
|
-
throw new Error(`Project ${projectId} not found.`);
|
|
74
|
+
throw new Error(`Project ${projectId} details not found.`);
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
// 2. Determine IDE (Preference -> Fallback)
|
|
@@ -65,14 +65,13 @@ export async function refineLogic(
|
|
|
65
65
|
const traceId = uuidv4();
|
|
66
66
|
|
|
67
67
|
// Verify project access
|
|
68
|
-
const { data:
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
.single();
|
|
68
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
69
|
+
.rpc('check_project_access_secure', {
|
|
70
|
+
p_project_id: projectId,
|
|
71
|
+
p_user_id: userId
|
|
72
|
+
});
|
|
74
73
|
|
|
75
|
-
if (
|
|
74
|
+
if (accessError || !hasAccess) {
|
|
76
75
|
throw new Error(`Project access denied or not found: ${projectId}`);
|
|
77
76
|
}
|
|
78
77
|
|
|
@@ -40,18 +40,24 @@ export async function updateRoadmap(
|
|
|
40
40
|
chunkId?: string,
|
|
41
41
|
title?: string
|
|
42
42
|
): Promise<UpdateRoadmapResponse> {
|
|
43
|
-
//
|
|
44
|
-
const { data:
|
|
45
|
-
.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
.single();
|
|
43
|
+
// 1. Verify project access
|
|
44
|
+
const { data: hasAccess, error: accessError } = await supabase
|
|
45
|
+
.rpc('check_project_access_secure', {
|
|
46
|
+
p_project_id: projectId,
|
|
47
|
+
p_user_id: userId
|
|
48
|
+
});
|
|
50
49
|
|
|
51
|
-
if (
|
|
50
|
+
if (accessError || !hasAccess) {
|
|
52
51
|
throw new Error('Project not found or access denied');
|
|
53
52
|
}
|
|
54
53
|
|
|
54
|
+
// 2. Fetch project details (for response message if needed)
|
|
55
|
+
const { data: project } = await supabase
|
|
56
|
+
.from('projects')
|
|
57
|
+
.select('name')
|
|
58
|
+
.eq('id', projectId)
|
|
59
|
+
.single();
|
|
60
|
+
|
|
55
61
|
// Find the roadmap chunk
|
|
56
62
|
let targetChunk: { id: string; title: string; status: string } | null = null;
|
|
57
63
|
|