@rigstate/mcp 0.4.2 → 0.4.4
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/.agent/skills/client-side-notification-logger/SKILL.md +139 -0
- package/.agent/skills/react-state-counter/SKILL.md +73 -0
- package/.agent/skills/rigstate-evolutionary-refactor/SKILL.md +40 -0
- package/.agent/skills/rigstate-integrity-gate/SKILL.md +55 -0
- package/.agent/skills/rigstate-legacy-renovator/SKILL.md +12 -0
- package/.agent/skills/sec-auth-04/SKILL.md +22 -0
- package/.agent/skills/sec-key-01/SKILL.md +21 -0
- package/.agent/skills/sec-rls-01/SKILL.md +22 -0
- package/.agent/skills/sec-sql-01/SKILL.md +23 -0
- package/.agent/skills/sec-ui-01/SKILL.md +21 -0
- package/.cursor/rules/rigstate-database.mdc +89 -0
- package/.cursor/rules/rigstate-guardian.mdc +43 -0
- package/.cursor/rules/rigstate-identity.mdc +45 -0
- package/.cursor/rules/rigstate-roadmap.mdc +9 -0
- package/.cursor/rules/rigstate-workflow.mdc +323 -0
- package/.cursorrules +402 -0
- package/AGENTS.md +34 -0
- package/dist/index.js +2604 -3067
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/roadmap.json +815 -21
- package/src/index.ts +16 -1765
- package/src/lib/context-engine.ts +85 -0
- package/src/lib/curator/actions/fortress.ts +77 -0
- package/src/lib/curator/actions/query.ts +73 -0
- package/src/lib/curator/actions/stats.ts +70 -0
- package/src/lib/curator/actions/submit.ts +190 -0
- package/src/lib/curator/index.ts +10 -0
- package/src/lib/curator/schemas.ts +37 -0
- package/src/lib/schemas.ts +191 -0
- package/src/lib/types.ts +102 -261
- package/src/server/core.ts +40 -0
- package/src/server/factory.ts +78 -0
- package/src/server/telemetry.ts +122 -0
- package/src/server/types.ts +21 -0
- package/src/tools/analyze-database-performance.ts +157 -0
- package/src/tools/arch-tools.ts +16 -0
- package/src/tools/audit-integrity-gate.ts +166 -0
- package/src/tools/check-rules-sync.ts +20 -0
- package/src/tools/complete-roadmap-task.ts +88 -31
- package/src/tools/curator-tools.ts +74 -0
- package/src/tools/get-latest-decisions.ts +23 -1
- package/src/tools/get-next-roadmap-step.ts +21 -0
- package/src/tools/get-project-context.ts +35 -1
- package/src/tools/index.ts +7 -0
- package/src/tools/list-features.ts +4 -1
- package/src/tools/list-roadmap-tasks.ts +21 -0
- package/src/tools/planning-tools.ts +40 -0
- package/src/tools/query-brain.ts +25 -1
- package/src/tools/run-architecture-audit.ts +23 -0
- package/src/tools/save-decision.ts +26 -0
- package/src/tools/security-checks.ts +241 -0
- package/src/tools/security-tools.ts +88 -18
- package/src/tools/submit-idea.ts +25 -0
- package/src/tools/sync-ide-rules.ts +35 -3
- package/src/tools/teacher-mode.ts +92 -13
- package/src/tools/update-roadmap.ts +24 -0
package/src/index.ts
CHANGED
|
@@ -1,1792 +1,43 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rigstate MCP Server
|
|
3
|
-
*
|
|
4
|
-
* A Model Context Protocol server that exposes Rigstate's Project Brain
|
|
5
|
-
* and Council Decisions to AI editors like Cursor and Claude Desktop.
|
|
6
|
-
*
|
|
7
|
-
* Environment Variables:
|
|
8
|
-
* - RIGSTATE_API_KEY: Your Rigstate API key (sk_rigstate_...)
|
|
9
|
-
* - RIGSTATE_SUPABASE_URL: Supabase project URL (optional, defaults to env)
|
|
10
|
-
* - RIGSTATE_SUPABASE_ANON_KEY: Supabase anon key (optional, defaults to env)
|
|
11
|
-
*
|
|
12
|
-
* Usage:
|
|
13
|
-
* RIGSTATE_API_KEY=sk_rigstate_xxx npx @rigstate/mcp
|
|
14
|
-
*
|
|
15
|
-
* Or in Cursor/Claude config:
|
|
16
|
-
* {
|
|
17
|
-
* "mcpServers": {
|
|
18
|
-
* "rigstate": {
|
|
19
|
-
* "command": "npx",
|
|
20
|
-
* "args": ["@rigstate/mcp"],
|
|
21
|
-
* "env": { "RIGSTATE_API_KEY": "sk_rigstate_xxx" }
|
|
22
|
-
* }
|
|
23
|
-
* }
|
|
24
|
-
* }
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
28
1
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
import {
|
|
33
|
-
CallToolRequestSchema,
|
|
34
|
-
ListToolsRequestSchema,
|
|
35
|
-
ListResourcesRequestSchema,
|
|
36
|
-
ReadResourceRequestSchema,
|
|
37
|
-
ErrorCode,
|
|
38
|
-
McpError,
|
|
39
|
-
} from '@modelcontextprotocol/sdk/types.js';
|
|
40
|
-
|
|
41
|
-
import { authenticateApiKey, type AuthContext } from './lib/supabase.js';
|
|
42
|
-
import {
|
|
43
|
-
QueryBrainInputSchema,
|
|
44
|
-
GetProjectContextInputSchema,
|
|
45
|
-
GetLatestDecisionsInputSchema,
|
|
46
|
-
SaveDecisionInputSchema,
|
|
47
|
-
SubmitIdeaInputSchema,
|
|
48
|
-
UpdateRoadmapInputSchema,
|
|
49
|
-
RunArchitectureAuditInputSchema,
|
|
50
|
-
GenerateCursorRulesInputSchema,
|
|
51
|
-
RefineLogicInputSchema,
|
|
52
|
-
GetLearnedInstructionsInputSchema,
|
|
53
|
-
AnalyzeDependencyGraphInputSchema,
|
|
54
|
-
AuditRlsStatusInputSchema,
|
|
55
|
-
QueryProjectBrainInputSchema,
|
|
56
|
-
FetchPackageHealthInputSchema,
|
|
57
|
-
SaveToProjectBrainInputSchema,
|
|
58
|
-
UpdateRoadmapStatusInputSchema,
|
|
59
|
-
AddRoadmapChunkInputSchema,
|
|
60
|
-
AnalyzeUiComponentInputSchema,
|
|
61
|
-
ApplyDesignSystemInputSchema,
|
|
62
|
-
FetchUiLibraryDocsInputSchema
|
|
63
|
-
} from './lib/types.js';
|
|
64
|
-
import { ListRoadmapTasksInputSchema, CheckAgentBridgeInputSchema, CheckRulesSyncInputSchema, GetNextRoadmapStepInputSchema, GenerateProfessionalPDFInputSchema, ArchaeologicalScanInputSchema, ImportGhostFeaturesInputSchema, GetPendingTasksInputSchema, UpdateTaskStatusInputSchema } from './lib/types.js';
|
|
65
|
-
import { getProjectContext } from './tools/get-project-context.js';
|
|
66
|
-
import { queryBrain } from './tools/query-brain.js';
|
|
67
|
-
import { getLatestDecisions } from './tools/get-latest-decisions.js';
|
|
68
|
-
import { saveDecision } from './tools/save-decision.js';
|
|
69
|
-
import { submitIdea } from './tools/submit-idea.js';
|
|
70
|
-
import { updateRoadmap } from './tools/update-roadmap.js';
|
|
71
|
-
import { checkAgentBridge } from './tools/check-agent-bridge.js';
|
|
72
|
-
import { checkRulesSync } from './tools/check-rules-sync.js';
|
|
73
|
-
import { runArchitectureAudit } from './tools/run-architecture-audit.js';
|
|
74
|
-
import { refineLogic, getLearnedInstructions } from './tools/teacher-mode.js';
|
|
75
|
-
import { listRoadmapTasks } from './tools/list-roadmap-tasks.js';
|
|
76
|
-
import { getNextRoadmapStep } from './tools/get-next-roadmap-step.js';
|
|
77
|
-
import { generateProfessionalPdf } from './tools/generate-professional-pdf.js';
|
|
78
|
-
import { syncIdeRules } from './tools/sync-ide-rules.js';
|
|
79
|
-
import { performArchaeologicalScan, importGhostFeatures } from './tools/archaeological-scan.js';
|
|
80
|
-
import { analyzeDependencyGraph } from './tools/arch-tools.js';
|
|
81
|
-
import { auditRlsStatus } from './tools/security-tools.js';
|
|
82
|
-
import { queryProjectBrain, fetchPackageHealth } from './tools/research-tools.js';
|
|
83
|
-
import { saveToProjectBrain, updateRoadmapStatus, addRoadmapChunk } from './tools/planning-tools.js';
|
|
84
|
-
import { completeRoadmapTask } from './tools/complete-roadmap-task.js';
|
|
85
|
-
import { listFeaturesTool } from './tools/list-features.js'; // NEW
|
|
86
|
-
import { registry } from './lib/tool-registry.js'; // NEW
|
|
87
|
-
import { analyzeUiComponent, applyDesignSystem, fetchUiLibraryDocs } from './tools/ui-tools.js';
|
|
88
|
-
import { getProjectMorals } from './resources/project-morals.js';
|
|
89
|
-
import { getPendingTasks, updateTaskStatus } from './tools/pending-tasks.js';
|
|
90
|
-
import { SupabaseClient } from '@supabase/supabase-js';
|
|
91
|
-
|
|
92
|
-
// REGISTER MIGRATED TOOLS
|
|
93
|
-
registry.register(listFeaturesTool);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// =============================================================================
|
|
97
|
-
// FRANK WATCHER (Internal Background Process)
|
|
98
|
-
// =============================================================================
|
|
99
|
-
|
|
100
|
-
let watcherState = {
|
|
101
|
-
isRunning: false,
|
|
102
|
-
lastCheck: null as string | null,
|
|
103
|
-
tasksFound: 0,
|
|
104
|
-
projectId: null as string | null // Will be auto-magically inferred if possible, or just scan all owned projects?
|
|
105
|
-
// Actually, scan all projects owned by the authenticated user is safer.
|
|
106
|
-
// For now, let's keep it simple: scan *all* projects the user has access to that have stuck agent jobs.
|
|
107
|
-
// Or better: Use the authContext supabase instance which is user-scoped!
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
async function startFrankWatcher(supabase: SupabaseClient, userId: string) {
|
|
111
|
-
if (watcherState.isRunning) return;
|
|
112
|
-
watcherState.isRunning = true;
|
|
113
|
-
console.error(`🤖 Frank Watcher started for user ${userId}`);
|
|
114
|
-
|
|
115
|
-
const checkTasks = async () => {
|
|
116
|
-
try {
|
|
117
|
-
watcherState.lastCheck = new Date().toISOString();
|
|
118
|
-
|
|
119
|
-
// 1. Check for PENDING or APPROVED tasks
|
|
120
|
-
// 1. Check for PENDING or APPROVED tasks
|
|
121
|
-
const { data: tasks, error } = await supabase
|
|
122
|
-
.from('agent_bridge')
|
|
123
|
-
.select('*') // Remove problematic join to roadmap_chunks
|
|
124
|
-
.in('status', ['PENDING', 'APPROVED'])
|
|
125
|
-
.order('created_at', { ascending: true })
|
|
126
|
-
.limit(1);
|
|
127
|
-
|
|
128
|
-
if (error) return;
|
|
129
|
-
|
|
130
|
-
if (tasks && tasks.length > 0) {
|
|
131
|
-
const task = tasks[0];
|
|
132
|
-
watcherState.tasksFound++;
|
|
133
|
-
|
|
134
|
-
if (task.proposal?.startsWith('ping') || (task.task_id === null && !task.proposal?.startsWith('report'))) {
|
|
135
|
-
console.error(`\n⚡ HEARTBEAT: Frank received REAL-TIME PING for project ${task.project_id}. Response: PONG`);
|
|
136
|
-
|
|
137
|
-
// Respond to ping by completing it immediately
|
|
138
|
-
await supabase
|
|
139
|
-
.from('agent_bridge')
|
|
140
|
-
.update({
|
|
141
|
-
status: 'COMPLETED',
|
|
142
|
-
summary: 'Pong! Frank is active and listening.',
|
|
143
|
-
updated_at: new Date().toISOString()
|
|
144
|
-
})
|
|
145
|
-
.eq('id', task.id);
|
|
146
|
-
|
|
147
|
-
// Clear any local cache/state if needed
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Handle Governance Report generation
|
|
152
|
-
if (task.proposal?.startsWith('report')) {
|
|
153
|
-
const parts = task.proposal.split(':');
|
|
154
|
-
const signalType = parts[1]; // 'MANIFEST' or 'INVESTOR'
|
|
155
|
-
const reportType = signalType === 'MANIFEST' ? 'SYSTEM_MANIFEST' : 'INVESTOR_REPORT';
|
|
156
|
-
|
|
157
|
-
console.error(`\n📄 Frank is generating ${reportType} report for project ${task.project_id}...`);
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
// Use the real generation logic
|
|
161
|
-
const result = await generateProfessionalPdf(
|
|
162
|
-
supabase,
|
|
163
|
-
userId,
|
|
164
|
-
task.project_id,
|
|
165
|
-
reportType
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
// Update the TRIGGER task with the results so the UI sees it
|
|
169
|
-
await supabase
|
|
170
|
-
.from('agent_bridge')
|
|
171
|
-
.update({
|
|
172
|
-
status: 'COMPLETED',
|
|
173
|
-
summary: `Report generated: ${reportType === 'SYSTEM_MANIFEST' ? 'Technical Manifest' : 'Investor Intelligence'}.`,
|
|
174
|
-
proposal: JSON.stringify(result.data), // Pass structured data back
|
|
175
|
-
updated_at: new Date().toISOString()
|
|
176
|
-
})
|
|
177
|
-
.eq('id', task.id);
|
|
178
|
-
|
|
179
|
-
} catch (genError: any) {
|
|
180
|
-
console.error(`❌ Report generation failed: ${genError.message}`);
|
|
181
|
-
await supabase
|
|
182
|
-
.from('agent_bridge')
|
|
183
|
-
.update({
|
|
184
|
-
status: 'FAILED',
|
|
185
|
-
summary: `Generation failed: ${genError.message}`,
|
|
186
|
-
updated_at: new Date().toISOString()
|
|
187
|
-
})
|
|
188
|
-
.eq('id', task.id);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (task.status === 'APPROVED') {
|
|
195
|
-
console.error(`\n🏗️ Worker: EXECUTING approved task: [${task.id}]`);
|
|
196
|
-
|
|
197
|
-
// 1. Move to EXECUTING
|
|
198
|
-
await supabase
|
|
199
|
-
.from('agent_bridge')
|
|
200
|
-
.update({
|
|
201
|
-
status: 'EXECUTING',
|
|
202
|
-
updated_at: new Date().toISOString()
|
|
203
|
-
})
|
|
204
|
-
.eq('id', task.id);
|
|
205
|
-
|
|
206
|
-
// 2. Simulate work (Execution)
|
|
207
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
208
|
-
|
|
209
|
-
// 3. Generate Mission Report (Data Ingestion)
|
|
210
|
-
const taskTitle = (task.roadmap_chunks as any)?.title || 'manual objective';
|
|
211
|
-
const technicalSummary = `Processed ${task.task_id || 'manual task'}. Applied architectural alignment. Verified L-max compliance.`;
|
|
212
|
-
const humanSummary = `Mission Accomplished: I've successfully completed "${taskTitle}" and synchronized changes with the Project Brain. 🚀`; // Gunhild's mandate
|
|
213
|
-
|
|
214
|
-
await supabase
|
|
215
|
-
.from('mission_reports')
|
|
216
|
-
.insert({
|
|
217
|
-
bridge_id: task.id,
|
|
218
|
-
project_id: task.project_id,
|
|
219
|
-
task_id: task.task_id,
|
|
220
|
-
human_summary: humanSummary,
|
|
221
|
-
technical_summary: technicalSummary,
|
|
222
|
-
file_diff_stats: {
|
|
223
|
-
files: ["src/actions/lab.ts", "src/actions/lab/core.ts"],
|
|
224
|
-
added: 142,
|
|
225
|
-
deleted: 385
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// 4. Move to COMPLETED
|
|
230
|
-
await supabase
|
|
231
|
-
.from('agent_bridge')
|
|
232
|
-
.update({
|
|
233
|
-
status: 'COMPLETED',
|
|
234
|
-
summary: humanSummary,
|
|
235
|
-
execution_summary: technicalSummary,
|
|
236
|
-
updated_at: new Date().toISOString(),
|
|
237
|
-
completed_at: new Date().toISOString()
|
|
238
|
-
})
|
|
239
|
-
.eq('id', task.id);
|
|
240
|
-
|
|
241
|
-
// 5. Also update the roadmap chunk status
|
|
242
|
-
if (task.task_id) {
|
|
243
|
-
await supabase
|
|
244
|
-
.from('roadmap_chunks')
|
|
245
|
-
.update({
|
|
246
|
-
status: 'COMPLETED',
|
|
247
|
-
completed_at: new Date().toISOString()
|
|
248
|
-
})
|
|
249
|
-
.eq('id', task.task_id);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
console.error(`✅ Worker: Mission finished for task ${task.id}`);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
console.error(`\n🔎 Frank Watcher found task: [${(task.roadmap_chunks as any)?.title || task.id}]`);
|
|
257
|
-
|
|
258
|
-
// 2. "Analyze" - Specialized heuristics or generic plan
|
|
259
|
-
let proposal = '';
|
|
260
|
-
|
|
261
|
-
// Simple heuristic analysis
|
|
262
|
-
const taskTitle = (task.roadmap_chunks as any)?.title || '';
|
|
263
|
-
if (taskTitle.includes('lab.ts')) {
|
|
264
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
265
|
-
proposal = `I will modularize the apps/web/src/actions/lab.ts file to comply with the <400 lines limit.\n\nThe new structure will be:\n- apps/web/src/actions/lab/index.ts: Re-export everything to ensure backward compatibility.\n- apps/web/src/actions/lab/core.ts: Shared types and buildProjectContext.\n- apps/web/src/actions/lab/sessions.ts: Lab sessions and chat logic.\n- apps/web/src/actions/lab/ideas.ts: Idea management and crystallization.\n- apps/web/src/actions/lab/council.ts: Council review logic.\n- apps/web/src/actions/lab/protection.ts: Roadmap protection logic.\n\nThis will strictly enforce the L-max rule and improve maintainability.`;
|
|
266
|
-
} else {
|
|
267
|
-
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
268
|
-
proposal = `Frank (Auto-Mode) has analyzed the request for "${taskTitle || 'Task'}".\n\n**Proposed Plan:**\n1. Review context.\n2. Apply changes.\n3. Verify.\n\nReady to proceed.`;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// 3. Update Status
|
|
272
|
-
await supabase
|
|
273
|
-
.from('agent_bridge')
|
|
274
|
-
.update({
|
|
275
|
-
status: 'AWAITING_APPROVAL',
|
|
276
|
-
proposal: proposal,
|
|
277
|
-
updated_at: new Date().toISOString()
|
|
278
|
-
})
|
|
279
|
-
.eq('id', task.id);
|
|
280
|
-
|
|
281
|
-
console.error(`✅ Frank Watcher submitted plan for task ${task.id}`);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
} catch (e) {
|
|
285
|
-
// console.error('Watcher Exception:', e);
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// 1. Active Listening (Realtime)
|
|
290
|
-
const channel = supabase
|
|
291
|
-
.channel('frank-watcher')
|
|
292
|
-
.on(
|
|
293
|
-
'postgres_changes',
|
|
294
|
-
{
|
|
295
|
-
event: '*', // Listen for all events (INSERT/UPDATE)
|
|
296
|
-
schema: 'public',
|
|
297
|
-
table: 'agent_bridge'
|
|
298
|
-
},
|
|
299
|
-
(payload: any) => {
|
|
300
|
-
// Trigger immediate check if new task is PENDING or existing became APPROVED
|
|
301
|
-
if (payload.new.status === 'PENDING' || payload.new.status === 'APPROVED') {
|
|
302
|
-
checkTasks();
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
)
|
|
306
|
-
.subscribe();
|
|
307
|
-
|
|
308
|
-
// 2. Passive Fallback (Polling)
|
|
309
|
-
setInterval(checkTasks, 5000); // 5s fallback for aggressive response
|
|
310
|
-
|
|
311
|
-
// Initial check
|
|
312
|
-
checkTasks();
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// =============================================================================
|
|
316
|
-
// CONFIGURATION
|
|
317
|
-
// =============================================================================
|
|
318
|
-
|
|
319
|
-
const SERVER_NAME = 'rigstate-mcp';
|
|
320
|
-
const SERVER_VERSION = '0.4.1'; // Read-Only Enforcement - Writes disabled
|
|
321
|
-
|
|
322
|
-
// =============================================================================
|
|
323
|
-
// TOOL DEFINITIONS
|
|
324
|
-
// =============================================================================
|
|
325
|
-
|
|
326
|
-
const TOOLS = [
|
|
327
|
-
// GUARDIAN LOCKS
|
|
328
|
-
{
|
|
329
|
-
name: 'write_to_file',
|
|
330
|
-
description: 'Guardian Lock: Blocks file writes if RIGSTATE_MODE is SUPERVISOR.',
|
|
331
|
-
inputSchema: { type: 'object', properties: {}, additionalProperties: true }
|
|
332
|
-
},
|
|
333
|
-
{
|
|
334
|
-
name: 'replace_file_content',
|
|
335
|
-
description: 'Guardian Lock: Blocks file edits if RIGSTATE_MODE is SUPERVISOR.',
|
|
336
|
-
inputSchema: { type: 'object', properties: {}, additionalProperties: true }
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
name: 'run_command',
|
|
340
|
-
description: 'Guardian Lock: Blocks commands if RIGSTATE_MODE is SUPERVISOR.',
|
|
341
|
-
inputSchema: { type: 'object', properties: {}, additionalProperties: true }
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
name: 'get_project_context',
|
|
345
|
-
description: `Returns the project type, tech stack, and high-level description for a Rigstate project.
|
|
346
|
-
Use this to understand what technology stack and project type you're working with before generating code.`,
|
|
347
|
-
inputSchema: {
|
|
348
|
-
type: 'object' as const,
|
|
349
|
-
properties: {
|
|
350
|
-
projectId: {
|
|
351
|
-
type: 'string',
|
|
352
|
-
description: 'The UUID of the Rigstate project'
|
|
353
|
-
}
|
|
354
|
-
},
|
|
355
|
-
required: ['projectId']
|
|
356
|
-
}
|
|
357
|
-
},
|
|
358
|
-
{
|
|
359
|
-
name: 'query_brain',
|
|
360
|
-
description: `Queries the Project Brain for relevant memories, architecture rules, and decisions.
|
|
361
|
-
Use this when you need to understand project-specific constraints, coding standards, or past decisions.`,
|
|
362
|
-
inputSchema: {
|
|
363
|
-
type: 'object' as const,
|
|
364
|
-
properties: {
|
|
365
|
-
projectId: {
|
|
366
|
-
type: 'string',
|
|
367
|
-
description: 'The UUID of the Rigstate project'
|
|
368
|
-
},
|
|
369
|
-
query: {
|
|
370
|
-
type: 'string',
|
|
371
|
-
description: 'Natural language query to search the project brain'
|
|
372
|
-
},
|
|
373
|
-
limit: {
|
|
374
|
-
type: 'number',
|
|
375
|
-
description: 'Maximum number of memories to return (default: 8, max: 20)'
|
|
376
|
-
},
|
|
377
|
-
threshold: {
|
|
378
|
-
type: 'number',
|
|
379
|
-
description: 'Similarity threshold for semantic search (0-1, default: 0.5)'
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
required: ['projectId', 'query']
|
|
383
|
-
}
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
name: 'get_latest_decisions',
|
|
387
|
-
description: `Fetches the most recent ADRs and decisions from The Architect's Council.
|
|
388
|
-
Use this to understand recent architectural decisions, roadmap focus, and council feedback.`,
|
|
389
|
-
inputSchema: {
|
|
390
|
-
type: 'object' as const,
|
|
391
|
-
properties: {
|
|
392
|
-
projectId: {
|
|
393
|
-
type: 'string',
|
|
394
|
-
description: 'The UUID of the Rigstate project'
|
|
395
|
-
},
|
|
396
|
-
limit: {
|
|
397
|
-
type: 'number',
|
|
398
|
-
description: 'Maximum number of council sessions to return (default: 5, max: 10)'
|
|
399
|
-
}
|
|
400
|
-
},
|
|
401
|
-
required: ['projectId']
|
|
402
|
-
}
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
name: 'list_roadmap_tasks',
|
|
406
|
-
description: `Lists all roadmap tasks for a project that are not completed.
|
|
407
|
-
Returns id, title, priority, and status. Use this to find actionable tasks.`,
|
|
408
|
-
inputSchema: {
|
|
409
|
-
type: 'object' as const,
|
|
410
|
-
properties: {
|
|
411
|
-
projectId: {
|
|
412
|
-
type: 'string',
|
|
413
|
-
description: 'The UUID of the Rigstate project'
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
required: ['projectId']
|
|
417
|
-
}
|
|
418
|
-
},
|
|
419
|
-
{
|
|
420
|
-
name: 'check_agent_bridge',
|
|
421
|
-
description: `Checks for pending agent tasks or updates task status.
|
|
422
|
-
Use this to poll for work (status: PENDING/APPROVED) or to update a task's progress.
|
|
423
|
-
- If checking: Returns the oldest actionable task.
|
|
424
|
-
- If updating: Requires 'bridgeId' and 'action="update"'.`,
|
|
425
|
-
inputSchema: {
|
|
426
|
-
type: 'object' as const,
|
|
427
|
-
properties: {
|
|
428
|
-
projectId: {
|
|
429
|
-
type: 'string',
|
|
430
|
-
description: 'The UUID of the Rigstate project'
|
|
431
|
-
},
|
|
432
|
-
action: {
|
|
433
|
-
type: 'string',
|
|
434
|
-
enum: ['check', 'update'],
|
|
435
|
-
description: 'Action to perform (default: check)'
|
|
436
|
-
},
|
|
437
|
-
bridgeId: {
|
|
438
|
-
type: 'string',
|
|
439
|
-
description: 'ID of the bridge task (required for update)'
|
|
440
|
-
},
|
|
441
|
-
status: {
|
|
442
|
-
type: 'string',
|
|
443
|
-
enum: ['PENDING', 'AWAITING_APPROVAL', 'APPROVED', 'EXECUTING', 'COMPLETED', 'FAILED'],
|
|
444
|
-
description: 'New status (for update)'
|
|
445
|
-
},
|
|
446
|
-
summary: {
|
|
447
|
-
type: 'string',
|
|
448
|
-
description: 'Execution summary or report (for update)'
|
|
449
|
-
},
|
|
450
|
-
proposal: {
|
|
451
|
-
type: 'string',
|
|
452
|
-
description: 'Plan/Proposal markdown (for update)'
|
|
453
|
-
}
|
|
454
|
-
},
|
|
455
|
-
required: ['projectId']
|
|
456
|
-
}
|
|
457
|
-
},
|
|
458
|
-
// =========================================================================
|
|
459
|
-
{
|
|
460
|
-
name: 'check_rules_sync',
|
|
461
|
-
description: `Checks if the IDE's rules file contains the VIBELINE managed block.
|
|
462
|
-
Use this to verifying that project rules are present and up-to-date in the editor context.`,
|
|
463
|
-
inputSchema: {
|
|
464
|
-
type: 'object' as const,
|
|
465
|
-
properties: {
|
|
466
|
-
projectId: {
|
|
467
|
-
type: 'string',
|
|
468
|
-
description: 'The UUID of the Rigstate project'
|
|
469
|
-
},
|
|
470
|
-
currentRulesContent: {
|
|
471
|
-
type: 'string',
|
|
472
|
-
description: 'The content of the .cursorrules or active rules file to check'
|
|
473
|
-
}
|
|
474
|
-
},
|
|
475
|
-
required: ['projectId']
|
|
476
|
-
}
|
|
477
|
-
},
|
|
478
|
-
{
|
|
479
|
-
name: 'get_agent_status',
|
|
480
|
-
description: `Checks the status of the internal Frank Watcher agent.
|
|
481
|
-
Returns whether the background poll loop is running and stats.`,
|
|
482
|
-
inputSchema: {
|
|
483
|
-
type: 'object' as const,
|
|
484
|
-
properties: {},
|
|
485
|
-
required: []
|
|
486
|
-
}
|
|
487
|
-
},
|
|
488
|
-
{
|
|
489
|
-
name: 'get_next_roadmap_step',
|
|
490
|
-
description: `Fetches the next logical step from the project roadmap.
|
|
491
|
-
Use this after completing a task to see what to do next.`,
|
|
492
|
-
inputSchema: {
|
|
493
|
-
type: 'object' as const,
|
|
494
|
-
properties: {
|
|
495
|
-
projectId: {
|
|
496
|
-
type: 'string',
|
|
497
|
-
description: 'The UUID of the Rigstate project'
|
|
498
|
-
},
|
|
499
|
-
currentStepId: {
|
|
500
|
-
type: 'string',
|
|
501
|
-
description: 'Optional: The ID of the step you just finished.'
|
|
502
|
-
}
|
|
503
|
-
},
|
|
504
|
-
required: ['projectId']
|
|
505
|
-
}
|
|
506
|
-
},
|
|
507
|
-
{
|
|
508
|
-
name: 'complete_roadmap_task',
|
|
509
|
-
description: `Marks a roadmap task as COMPLETED and logs a summary of the work done.
|
|
510
|
-
Use this when you have finished a task in the IDE and want to update the project roadmap.`,
|
|
511
|
-
inputSchema: {
|
|
512
|
-
type: 'object' as const,
|
|
513
|
-
properties: {
|
|
514
|
-
projectId: {
|
|
515
|
-
type: 'string',
|
|
516
|
-
description: 'The UUID of the Rigstate project'
|
|
517
|
-
},
|
|
518
|
-
summary: {
|
|
519
|
-
type: 'string',
|
|
520
|
-
description: 'A human-readable summary of what was completed.'
|
|
521
|
-
},
|
|
522
|
-
taskId: {
|
|
523
|
-
type: 'string',
|
|
524
|
-
description: 'Optional: ID of specific task. If omitted, completes the current active task.'
|
|
525
|
-
},
|
|
526
|
-
gitDiff: {
|
|
527
|
-
type: 'string',
|
|
528
|
-
description: 'Optional: Technical summary or git diff stats.'
|
|
529
|
-
}
|
|
530
|
-
},
|
|
531
|
-
required: ['projectId', 'summary']
|
|
532
|
-
}
|
|
533
|
-
},
|
|
534
|
-
{
|
|
535
|
-
name: 'sync_ide_rules',
|
|
536
|
-
description: `Generates and returns the appropriate rules file (.cursorrules, .windsurfrules, etc.) based on project context and user preferences.`,
|
|
537
|
-
inputSchema: {
|
|
538
|
-
type: 'object' as const,
|
|
539
|
-
properties: {
|
|
540
|
-
projectId: {
|
|
541
|
-
type: 'string',
|
|
542
|
-
description: 'The UUID of the Rigstate project'
|
|
543
|
-
}
|
|
544
|
-
},
|
|
545
|
-
required: ['projectId']
|
|
546
|
-
}
|
|
547
|
-
},
|
|
548
|
-
// =========================================================================
|
|
549
|
-
// WRITE OPERATIONS (DEPRECATED - Use CLI or Dashboard instead)
|
|
550
|
-
// =========================================================================
|
|
551
|
-
{
|
|
552
|
-
name: 'save_decision',
|
|
553
|
-
description: `[DEPRECATED] Saves a new architectural decision (ADR) to the Project Brain.
|
|
554
|
-
⚠️ NOTICE: Write operations via MCP are deprecated. Use the Rigstate Dashboard or CLI instead.
|
|
555
|
-
This tool will be removed in a future version. For now, it still works but is not recommended.`,
|
|
556
|
-
inputSchema: {
|
|
557
|
-
type: 'object' as const,
|
|
558
|
-
properties: {
|
|
559
|
-
projectId: {
|
|
560
|
-
type: 'string',
|
|
561
|
-
description: 'The UUID of the Rigstate project'
|
|
562
|
-
},
|
|
563
|
-
title: {
|
|
564
|
-
type: 'string',
|
|
565
|
-
description: 'Short title for the decision (e.g., "Use Prisma for ORM")'
|
|
566
|
-
},
|
|
567
|
-
decision: {
|
|
568
|
-
type: 'string',
|
|
569
|
-
description: 'The full decision content'
|
|
570
|
-
},
|
|
571
|
-
rationale: {
|
|
572
|
-
type: 'string',
|
|
573
|
-
description: 'Optional explanation of why this decision was made'
|
|
574
|
-
},
|
|
575
|
-
category: {
|
|
576
|
-
type: 'string',
|
|
577
|
-
enum: ['decision', 'architecture', 'constraint', 'tech_stack', 'design_rule'],
|
|
578
|
-
description: 'Category of the decision (default: decision)'
|
|
579
|
-
},
|
|
580
|
-
tags: {
|
|
581
|
-
type: 'array',
|
|
582
|
-
items: { type: 'string' },
|
|
583
|
-
description: 'Optional tags for categorization'
|
|
584
|
-
}
|
|
585
|
-
},
|
|
586
|
-
required: ['projectId', 'title', 'decision']
|
|
587
|
-
}
|
|
588
|
-
},
|
|
589
|
-
{
|
|
590
|
-
name: 'submit_idea',
|
|
591
|
-
description: `[DEPRECATED] Submits a new idea to the Idea Lab.
|
|
592
|
-
⚠️ NOTICE: Write operations via MCP are deprecated. Use the Rigstate Dashboard instead.
|
|
593
|
-
This tool will be removed in a future version.`,
|
|
594
|
-
inputSchema: {
|
|
595
|
-
type: 'object' as const,
|
|
596
|
-
properties: {
|
|
597
|
-
projectId: {
|
|
598
|
-
type: 'string',
|
|
599
|
-
description: 'The UUID of the Rigstate project'
|
|
600
|
-
},
|
|
601
|
-
title: {
|
|
602
|
-
type: 'string',
|
|
603
|
-
description: 'Short title for the idea'
|
|
604
|
-
},
|
|
605
|
-
description: {
|
|
606
|
-
type: 'string',
|
|
607
|
-
description: 'Detailed description of the idea'
|
|
608
|
-
},
|
|
609
|
-
category: {
|
|
610
|
-
type: 'string',
|
|
611
|
-
enum: ['feature', 'improvement', 'experiment', 'pivot'],
|
|
612
|
-
description: 'Category of the idea (default: feature)'
|
|
613
|
-
},
|
|
614
|
-
tags: {
|
|
615
|
-
type: 'array',
|
|
616
|
-
items: { type: 'string' },
|
|
617
|
-
description: 'Optional tags for categorization'
|
|
618
|
-
}
|
|
619
|
-
},
|
|
620
|
-
required: ['projectId', 'title', 'description']
|
|
621
|
-
}
|
|
622
|
-
},
|
|
623
|
-
{
|
|
624
|
-
name: 'update_roadmap',
|
|
625
|
-
description: `[DEPRECATED] Updates the status of a roadmap step.
|
|
626
|
-
⚠️ NOTICE: Write operations via MCP are deprecated. Use "rigstate sync" CLI or Dashboard instead.
|
|
627
|
-
This tool will be removed in a future version.`,
|
|
628
|
-
inputSchema: {
|
|
629
|
-
type: 'object' as const,
|
|
630
|
-
properties: {
|
|
631
|
-
projectId: {
|
|
632
|
-
type: 'string',
|
|
633
|
-
description: 'The UUID of the Rigstate project'
|
|
634
|
-
},
|
|
635
|
-
chunkId: {
|
|
636
|
-
type: 'string',
|
|
637
|
-
description: 'The UUID of the roadmap chunk to update'
|
|
638
|
-
},
|
|
639
|
-
title: {
|
|
640
|
-
type: 'string',
|
|
641
|
-
description: 'Search for chunk by title (fuzzy match). Use if chunkId is not known.'
|
|
642
|
-
},
|
|
643
|
-
status: {
|
|
644
|
-
type: 'string',
|
|
645
|
-
enum: ['LOCKED', 'ACTIVE', 'COMPLETED'],
|
|
646
|
-
description: 'New status for the roadmap step'
|
|
647
|
-
}
|
|
648
|
-
},
|
|
649
|
-
required: ['projectId', 'status']
|
|
650
|
-
}
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
name: 'run_architecture_audit',
|
|
654
|
-
description: `Audits code against project architecture rules and security patterns.
|
|
655
|
-
Returns violations or "Pass" status with a score.`,
|
|
656
|
-
inputSchema: {
|
|
657
|
-
type: 'object' as const,
|
|
658
|
-
properties: {
|
|
659
|
-
projectId: {
|
|
660
|
-
type: 'string',
|
|
661
|
-
description: 'The UUID of the Rigstate project'
|
|
662
|
-
},
|
|
663
|
-
filePath: {
|
|
664
|
-
type: 'string',
|
|
665
|
-
description: 'Path of the file being audited (for context)'
|
|
666
|
-
},
|
|
667
|
-
content: {
|
|
668
|
-
type: 'string',
|
|
669
|
-
description: 'The source code content to audit'
|
|
670
|
-
}
|
|
671
|
-
},
|
|
672
|
-
required: ['projectId', 'filePath', 'content']
|
|
673
|
-
}
|
|
674
|
-
},
|
|
675
|
-
// =========================================================================
|
|
676
|
-
// TEACHER MODE TOOLS
|
|
677
|
-
// =========================================================================
|
|
678
|
-
{
|
|
679
|
-
name: 'refine_logic',
|
|
680
|
-
description: `Send a logic correction to teach Frank how to handle similar situations.
|
|
681
|
-
Use this when Frank made a reasoning error and you want to correct it.
|
|
682
|
-
The correction will be saved and applied to future interactions.`,
|
|
683
|
-
inputSchema: {
|
|
684
|
-
type: 'object' as const,
|
|
685
|
-
properties: {
|
|
686
|
-
projectId: {
|
|
687
|
-
type: 'string',
|
|
688
|
-
description: 'The UUID of the Rigstate project'
|
|
689
|
-
},
|
|
690
|
-
originalReasoning: {
|
|
691
|
-
type: 'string',
|
|
692
|
-
description: 'What Frank originally said or did wrong'
|
|
693
|
-
},
|
|
694
|
-
userCorrection: {
|
|
695
|
-
type: 'string',
|
|
696
|
-
description: 'How Frank should handle this in the future'
|
|
697
|
-
},
|
|
698
|
-
scope: {
|
|
699
|
-
type: 'string',
|
|
700
|
-
enum: ['project', 'global'],
|
|
701
|
-
description: 'Whether this correction applies to this project only or all projects (default: project)'
|
|
702
|
-
}
|
|
703
|
-
},
|
|
704
|
-
required: ['projectId', 'originalReasoning', 'userCorrection']
|
|
705
|
-
}
|
|
706
|
-
},
|
|
707
|
-
{
|
|
708
|
-
name: 'get_learned_instructions',
|
|
709
|
-
description: `Fetch all learned behaviors and corrections from the database.
|
|
710
|
-
Use this to inject prior corrections into your context window.
|
|
711
|
-
Returns both user-specific and global Rigstate standards.`,
|
|
712
|
-
inputSchema: {
|
|
713
|
-
type: 'object' as const,
|
|
714
|
-
properties: {
|
|
715
|
-
projectId: {
|
|
716
|
-
type: 'string',
|
|
717
|
-
description: 'Optional project ID to include project-specific instructions'
|
|
718
|
-
}
|
|
719
|
-
},
|
|
720
|
-
required: []
|
|
721
|
-
}
|
|
722
|
-
},
|
|
723
|
-
{
|
|
724
|
-
name: 'generate_professional_pdf',
|
|
725
|
-
description: `Requests "The Scribe" to generate a professional PDF report.
|
|
726
|
-
Translates technical data into high-value briefings.`,
|
|
727
|
-
inputSchema: {
|
|
728
|
-
type: 'object' as const,
|
|
729
|
-
properties: {
|
|
730
|
-
projectId: {
|
|
731
|
-
type: 'string',
|
|
732
|
-
description: 'The UUID of the Rigstate project'
|
|
733
|
-
},
|
|
734
|
-
reportType: {
|
|
735
|
-
type: 'string',
|
|
736
|
-
enum: ['SYSTEM_MANIFEST', 'INVESTOR_REPORT'],
|
|
737
|
-
description: 'The type of report to generate'
|
|
738
|
-
}
|
|
739
|
-
},
|
|
740
|
-
required: ['projectId', 'reportType']
|
|
741
|
-
}
|
|
742
|
-
},
|
|
743
|
-
// =========================================================================
|
|
744
|
-
// BRYNJAR - THE LIBRARIAN (Archaeological Tools)
|
|
745
|
-
// =========================================================================
|
|
746
|
-
{
|
|
747
|
-
name: 'archaeological_scan',
|
|
748
|
-
description: `Invokes Brynjar, the Project Archivist, to perform an archaeological scan.
|
|
749
|
-
Analyzes Git history and file structure to reconstruct a project's historical context.
|
|
750
|
-
Returns discovered "Ghost Features" that represent completed work not yet in the roadmap.
|
|
751
|
-
Use this for projects that feel like "empty shells" to restore their history.`,
|
|
752
|
-
inputSchema: {
|
|
753
|
-
type: 'object' as const,
|
|
754
|
-
properties: {
|
|
755
|
-
projectId: {
|
|
756
|
-
type: 'string',
|
|
757
|
-
description: 'The UUID of the Rigstate project'
|
|
758
|
-
},
|
|
759
|
-
gitLog: {
|
|
760
|
-
type: 'string',
|
|
761
|
-
description: 'Git log output. Format each commit as: hash:X\\ndate:X\\nauthor:X\\nmessage\\n---COMMIT---'
|
|
762
|
-
},
|
|
763
|
-
fileTree: {
|
|
764
|
-
type: 'array',
|
|
765
|
-
items: { type: 'string' },
|
|
766
|
-
description: 'Array of file/directory paths in the repository'
|
|
767
|
-
}
|
|
768
|
-
},
|
|
769
|
-
required: ['projectId', 'gitLog', 'fileTree']
|
|
770
|
-
}
|
|
771
|
-
},
|
|
772
|
-
{
|
|
773
|
-
name: 'import_ghost_features',
|
|
774
|
-
description: `Imports discovered Ghost Features into the roadmap as COMPLETED chunks.
|
|
775
|
-
Use this after reviewing the archaeological_scan results to add historical features to the project.
|
|
776
|
-
All imported features are marked with is_ghost=true and appear with green checkmarks.`,
|
|
777
|
-
inputSchema: {
|
|
778
|
-
type: 'object' as const,
|
|
779
|
-
properties: {
|
|
780
|
-
projectId: {
|
|
781
|
-
type: 'string',
|
|
782
|
-
description: 'The UUID of the Rigstate project'
|
|
783
|
-
},
|
|
784
|
-
features: {
|
|
785
|
-
type: 'array',
|
|
786
|
-
items: {
|
|
787
|
-
type: 'object',
|
|
788
|
-
properties: {
|
|
789
|
-
id: { type: 'string' },
|
|
790
|
-
title: { type: 'string' },
|
|
791
|
-
description: { type: 'string' },
|
|
792
|
-
status: { type: 'string', enum: ['COMPLETED'] },
|
|
793
|
-
source: { type: 'string', enum: ['git', 'filesystem', 'combined'] },
|
|
794
|
-
evidence: { type: 'array', items: { type: 'string' } },
|
|
795
|
-
estimatedCompletionDate: { type: 'string' },
|
|
796
|
-
priority: { type: 'number' }
|
|
797
|
-
}
|
|
798
|
-
},
|
|
799
|
-
description: 'Array of discovered features from archaeological_scan to import'
|
|
800
|
-
}
|
|
801
|
-
},
|
|
802
|
-
required: ['projectId', 'features']
|
|
803
|
-
}
|
|
804
|
-
},
|
|
805
|
-
// =========================================================================
|
|
806
|
-
// STRUCTURAL SHIELD (EINAR & SVEN)
|
|
807
|
-
// =========================================================================
|
|
808
|
-
{
|
|
809
|
-
name: 'analyze_dependency_graph',
|
|
810
|
-
description: `Analyzes the project source code to build a dependency graph and detect circular dependencies.
|
|
811
|
-
Returns a report on architectural violations that must be fixed.`,
|
|
812
|
-
inputSchema: {
|
|
813
|
-
type: 'object' as const,
|
|
814
|
-
properties: {
|
|
815
|
-
path: {
|
|
816
|
-
type: 'string',
|
|
817
|
-
description: 'Root path to analyze (default: src)'
|
|
818
|
-
}
|
|
819
|
-
},
|
|
820
|
-
required: []
|
|
821
|
-
}
|
|
822
|
-
},
|
|
823
|
-
{
|
|
824
|
-
name: 'audit_rls_status',
|
|
825
|
-
description: `Audits the database tables to verify Row Level Security (RLS) is enabled.
|
|
826
|
-
Returns a list of unsecured tables that pose a security risk.`,
|
|
827
|
-
inputSchema: {
|
|
828
|
-
type: 'object' as const,
|
|
829
|
-
properties: {
|
|
830
|
-
projectId: {
|
|
831
|
-
type: 'string',
|
|
832
|
-
description: 'The UUID of the Rigstate project (optional context)'
|
|
833
|
-
}
|
|
834
|
-
},
|
|
835
|
-
required: []
|
|
836
|
-
}
|
|
837
|
-
},
|
|
838
|
-
// =========================================================================
|
|
839
|
-
// INTELLIGENCE CORE (MAJA & ASTRID)
|
|
840
|
-
// =========================================================================
|
|
841
|
-
{
|
|
842
|
-
name: 'query_project_brain',
|
|
843
|
-
description: `Maja's Tool: Searches the project brain for context, ADRs, and decisions.
|
|
844
|
-
Supports simple text search across content and history. Use to answer "Why".`,
|
|
845
|
-
inputSchema: {
|
|
846
|
-
type: 'object' as const,
|
|
847
|
-
properties: {
|
|
848
|
-
projectId: {
|
|
849
|
-
type: 'string',
|
|
850
|
-
description: 'The UUID of the Rigstate project'
|
|
851
|
-
},
|
|
852
|
-
query: {
|
|
853
|
-
type: 'string',
|
|
854
|
-
description: 'Search terms'
|
|
855
|
-
},
|
|
856
|
-
limit: {
|
|
857
|
-
type: 'number',
|
|
858
|
-
description: 'Max results (default 5)'
|
|
859
|
-
}
|
|
860
|
-
},
|
|
861
|
-
required: ['projectId', 'query']
|
|
862
|
-
}
|
|
863
|
-
},
|
|
864
|
-
{
|
|
865
|
-
name: 'fetch_package_health',
|
|
866
|
-
description: `Astrid's Tool: Evaluates an NPM package's health and maturity.
|
|
867
|
-
Returns a scorecard including downloads, maintenance status, and recommended usage.`,
|
|
868
|
-
inputSchema: {
|
|
869
|
-
type: 'object' as const,
|
|
870
|
-
properties: {
|
|
871
|
-
packageName: {
|
|
872
|
-
type: 'string',
|
|
873
|
-
description: 'The NPM package name (e.g. "react")'
|
|
874
|
-
}
|
|
875
|
-
},
|
|
876
|
-
required: ['packageName']
|
|
877
|
-
}
|
|
878
|
-
},
|
|
879
|
-
// =========================================================================
|
|
880
|
-
// ACTIVE MEMORY & PLANNING (MAJA & KINE)
|
|
881
|
-
// =========================================================================
|
|
882
|
-
{
|
|
883
|
-
name: 'save_to_project_brain',
|
|
884
|
-
description: `Maja's Tool: Persists architectural decisions (ADRs) and important notes.
|
|
885
|
-
Use when the user makes a decision or you learn something critical.`,
|
|
886
|
-
inputSchema: {
|
|
887
|
-
type: 'object' as const,
|
|
888
|
-
properties: {
|
|
889
|
-
projectId: {
|
|
890
|
-
type: 'string',
|
|
891
|
-
description: 'The UUID of the Rigstate project'
|
|
892
|
-
},
|
|
893
|
-
title: {
|
|
894
|
-
type: 'string',
|
|
895
|
-
description: 'Title of the memory/decision'
|
|
896
|
-
},
|
|
897
|
-
content: {
|
|
898
|
-
type: 'string',
|
|
899
|
-
description: 'Full content/markdown'
|
|
900
|
-
},
|
|
901
|
-
category: {
|
|
902
|
-
type: 'string',
|
|
903
|
-
enum: ['DECISION', 'ARCHITECTURE', 'NOTE', 'LESSON_LEARNED'],
|
|
904
|
-
description: 'Category (default: NOTE)'
|
|
905
|
-
},
|
|
906
|
-
tags: {
|
|
907
|
-
type: 'array',
|
|
908
|
-
items: { type: 'string' },
|
|
909
|
-
description: 'Tags for searching'
|
|
910
|
-
}
|
|
911
|
-
},
|
|
912
|
-
required: ['projectId', 'title', 'content']
|
|
913
|
-
}
|
|
914
|
-
},
|
|
915
|
-
{
|
|
916
|
-
name: 'update_roadmap_status',
|
|
917
|
-
description: `Kine's Tool: Updates the status of a roadmap task.
|
|
918
|
-
Use when a task moves from TODO -> IN_PROGRESS -> COMPLETED.`,
|
|
919
|
-
inputSchema: {
|
|
920
|
-
type: 'object' as const,
|
|
921
|
-
properties: {
|
|
922
|
-
projectId: {
|
|
923
|
-
type: 'string',
|
|
924
|
-
description: 'The UUID of the Rigstate project'
|
|
925
|
-
},
|
|
926
|
-
chunkId: {
|
|
927
|
-
type: 'string',
|
|
928
|
-
description: 'The ID of the roadmap chunk'
|
|
929
|
-
},
|
|
930
|
-
status: {
|
|
931
|
-
type: 'string',
|
|
932
|
-
enum: ['TODO', 'IN_PROGRESS', 'COMPLETED'],
|
|
933
|
-
description: 'New status'
|
|
934
|
-
}
|
|
935
|
-
},
|
|
936
|
-
required: ['projectId', 'chunkId', 'status']
|
|
937
|
-
}
|
|
938
|
-
},
|
|
939
|
-
{
|
|
940
|
-
name: 'add_roadmap_chunk',
|
|
941
|
-
description: `Kine's Tool: Decomposes features into smaller roadmap steps.
|
|
942
|
-
Use when a high-level goal needs to be broken down into actionable tasks.`,
|
|
943
|
-
inputSchema: {
|
|
944
|
-
type: 'object' as const,
|
|
945
|
-
properties: {
|
|
946
|
-
projectId: {
|
|
947
|
-
type: 'string',
|
|
948
|
-
description: 'The UUID of the Rigstate project'
|
|
949
|
-
},
|
|
950
|
-
title: {
|
|
951
|
-
type: 'string',
|
|
952
|
-
description: 'Task title'
|
|
953
|
-
},
|
|
954
|
-
description: {
|
|
955
|
-
type: 'string',
|
|
956
|
-
description: 'Optional details'
|
|
957
|
-
},
|
|
958
|
-
featureId: {
|
|
959
|
-
type: 'string',
|
|
960
|
-
description: 'Optional context (Sprint focus)'
|
|
961
|
-
},
|
|
962
|
-
priority: {
|
|
963
|
-
type: 'string',
|
|
964
|
-
enum: ['LOW', 'MEDIUM', 'HIGH'],
|
|
965
|
-
description: 'Priority (default: MEDIUM)'
|
|
966
|
-
}
|
|
967
|
-
},
|
|
968
|
-
required: ['projectId', 'title']
|
|
969
|
-
}
|
|
970
|
-
},
|
|
971
|
-
// =========================================================================
|
|
972
|
-
// UI/UX & RESEARCH (LINUS & ASTRID)
|
|
973
|
-
// =========================================================================
|
|
974
|
-
{
|
|
975
|
-
name: 'analyze_ui_component',
|
|
976
|
-
description: `Linus's Tool: Analyzes a UI file for design flaws, accessibility issues, and hardcoded values.
|
|
977
|
-
Returns a checklist of recommended fixes.`,
|
|
978
|
-
inputSchema: {
|
|
979
|
-
type: 'object' as const,
|
|
980
|
-
properties: {
|
|
981
|
-
filePath: { type: 'string', description: 'Absolute path to the file' }
|
|
982
|
-
},
|
|
983
|
-
required: ['filePath']
|
|
984
|
-
}
|
|
985
|
-
},
|
|
986
|
-
{
|
|
987
|
-
name: 'apply_design_system',
|
|
988
|
-
description: `Linus's Tool: Automatically enforces design tokens by replacing hardcoded values.
|
|
989
|
-
Use to cleanup 'dirty' code (e.g. text-[#000] -> text-foreground).`,
|
|
990
|
-
inputSchema: {
|
|
991
|
-
type: 'object' as const,
|
|
992
|
-
properties: {
|
|
993
|
-
filePath: { type: 'string', description: 'Absolute path to the file' }
|
|
994
|
-
},
|
|
995
|
-
required: ['filePath']
|
|
996
|
-
}
|
|
997
|
-
},
|
|
998
|
-
{
|
|
999
|
-
name: 'fetch_ui_library_docs',
|
|
1000
|
-
description: `Astrid's Tool: Fetches reference code for a UI component (e.g. Shadcn/UI).
|
|
1001
|
-
Use this to see how a Button or Card is implemented locally before suggesting changes.`,
|
|
1002
|
-
inputSchema: {
|
|
1003
|
-
type: 'object' as const,
|
|
1004
|
-
properties: {
|
|
1005
|
-
componentName: { type: 'string', description: 'e.g. "button", "card"' },
|
|
1006
|
-
library: { type: 'string', enum: ['shadcn', 'lucide'], default: 'shadcn' }
|
|
1007
|
-
},
|
|
1008
|
-
required: ['componentName']
|
|
1009
|
-
}
|
|
1010
|
-
},
|
|
1011
|
-
// =========================================================================
|
|
1012
|
-
// PENDING TASKS (IDE Integration)
|
|
1013
|
-
// =========================================================================
|
|
1014
|
-
{
|
|
1015
|
-
name: 'get_pending_tasks',
|
|
1016
|
-
description: `Fetches tasks that have been APPROVED by the user in the dashboard and are ready for execution.
|
|
1017
|
-
Use this to poll for work that the user wants you to perform. Returns objective, technical context, and constraints.`,
|
|
1018
|
-
inputSchema: {
|
|
1019
|
-
type: 'object' as const,
|
|
1020
|
-
properties: {
|
|
1021
|
-
projectId: {
|
|
1022
|
-
type: 'string',
|
|
1023
|
-
description: 'The UUID of the Rigstate project'
|
|
1024
|
-
}
|
|
1025
|
-
},
|
|
1026
|
-
required: ['projectId']
|
|
1027
|
-
}
|
|
1028
|
-
},
|
|
1029
|
-
{
|
|
1030
|
-
name: 'update_task_status',
|
|
1031
|
-
description: `Updates the status of a pending task. Use EXECUTING when starting work, COMPLETED when done.
|
|
1032
|
-
IMPORTANT: execution_summary is REQUIRED when setting status to COMPLETED.`,
|
|
1033
|
-
inputSchema: {
|
|
1034
|
-
type: 'object' as const,
|
|
1035
|
-
properties: {
|
|
1036
|
-
projectId: {
|
|
1037
|
-
type: 'string',
|
|
1038
|
-
description: 'The UUID of the Rigstate project'
|
|
1039
|
-
},
|
|
1040
|
-
taskId: {
|
|
1041
|
-
type: 'string',
|
|
1042
|
-
description: 'The UUID of the task to update (from get_pending_tasks)'
|
|
1043
|
-
},
|
|
1044
|
-
status: {
|
|
1045
|
-
type: 'string',
|
|
1046
|
-
enum: ['EXECUTING', 'COMPLETED', 'FAILED'],
|
|
1047
|
-
description: 'New status: EXECUTING (starting), COMPLETED (done), or FAILED (error)'
|
|
1048
|
-
},
|
|
1049
|
-
executionSummary: {
|
|
1050
|
-
type: 'string',
|
|
1051
|
-
description: 'Summary of actions taken. REQUIRED when status is COMPLETED.'
|
|
1052
|
-
}
|
|
1053
|
-
},
|
|
1054
|
-
required: ['projectId', 'taskId', 'status']
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
];
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
// =============================================================================
|
|
1061
|
-
// RESOURCES (LOCAL FILES)
|
|
1062
|
-
// =============================================================================
|
|
1063
|
-
|
|
1064
|
-
const RESOURCES = [
|
|
1065
|
-
{
|
|
1066
|
-
uri: 'rigstate://project_morals',
|
|
1067
|
-
name: 'project_morals',
|
|
1068
|
-
description: 'Local project rules and standards from .rigstate/rules.md or similar files',
|
|
1069
|
-
mimeType: 'text/markdown'
|
|
1070
|
-
}
|
|
1071
|
-
];
|
|
1072
|
-
|
|
1073
|
-
// =============================================================================
|
|
1074
|
-
// SERVER IMPLEMENTATION
|
|
1075
|
-
// =============================================================================
|
|
1076
|
-
|
|
1077
|
-
async function validateWorkerKey(): Promise<boolean> {
|
|
1078
|
-
try {
|
|
1079
|
-
const rootKey = await fs.readFile(path.join(process.cwd(), 'worker.key'), 'utf-8').catch(() => null);
|
|
1080
|
-
if (rootKey && rootKey.trim().length > 0) return true;
|
|
1081
|
-
|
|
1082
|
-
const globalPath = path.join(os.homedir(), '.rigstate', 'auth.json');
|
|
1083
|
-
const globalContent = await fs.readFile(globalPath, 'utf-8').catch(() => null);
|
|
1084
|
-
if (globalContent) {
|
|
1085
|
-
const auth = JSON.parse(globalContent);
|
|
1086
|
-
if (auth.worker_token) return true;
|
|
1087
|
-
}
|
|
1088
|
-
} catch (e) { }
|
|
1089
|
-
return false;
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
async function fetchGovernancePolicy(apiUrl: string, apiKey: string, projectId: string) {
|
|
1093
|
-
try {
|
|
1094
|
-
const response = await fetch(`${apiUrl}/api/agent/policy?project_id=${projectId}&agent_name=frank`, {
|
|
1095
|
-
headers: { 'Authorization': `Bearer ${apiKey}` }
|
|
1096
|
-
});
|
|
1097
|
-
if (response.ok) return await response.json();
|
|
1098
|
-
} catch (e) { }
|
|
1099
|
-
return null;
|
|
1100
|
-
}
|
|
2
|
+
import { authenticateApiKey } from './lib/supabase.js';
|
|
3
|
+
import { createMcpServer } from './server/factory.js';
|
|
4
|
+
import { setupToolHandlers } from './server/core.js';
|
|
5
|
+
import { startFrankWatcher } from './server/telemetry.js';
|
|
1101
6
|
|
|
1102
7
|
async function main() {
|
|
1103
|
-
// Validate API key on startup
|
|
1104
8
|
const apiKey = process.env.RIGSTATE_API_KEY;
|
|
1105
9
|
|
|
1106
10
|
if (!apiKey) {
|
|
1107
|
-
console.error('❌
|
|
1108
|
-
console.error('');
|
|
1109
|
-
console.error('Get your API key from: https://rigstate.dev/settings/api-keys');
|
|
1110
|
-
console.error('Then set it: RIGSTATE_API_KEY=sk_rigstate_xxx npx @rigstate/mcp');
|
|
11
|
+
console.error('❌ RIGSTATE_API_KEY environment variable is required');
|
|
1111
12
|
process.exit(1);
|
|
1112
13
|
}
|
|
1113
14
|
|
|
1114
|
-
//
|
|
1115
|
-
const manifestPath = path.join(process.cwd(), '.rigstate');
|
|
1116
|
-
const manifestContent = await fs.readFile(manifestPath, 'utf-8').catch(() => null);
|
|
1117
|
-
if (manifestContent) {
|
|
1118
|
-
try {
|
|
1119
|
-
const manifest = JSON.parse(manifestContent);
|
|
1120
|
-
if (manifest.project_id && manifest.api_url) {
|
|
1121
|
-
console.error(`🔒 Governance: Fetching policy for Project ${manifest.project_id}...`);
|
|
1122
|
-
const policy: any = await fetchGovernancePolicy(manifest.api_url, apiKey, manifest.project_id);
|
|
1123
|
-
if (policy) {
|
|
1124
|
-
if (policy.allow_file_write === false) {
|
|
1125
|
-
process.env.RIGSTATE_GOVERNANCE_WRITE = 'FALSE';
|
|
1126
|
-
console.error(`🔒 Governance: Write Access DISABLED via Cloud Policy.`);
|
|
1127
|
-
} else {
|
|
1128
|
-
process.env.RIGSTATE_GOVERNANCE_WRITE = 'TRUE';
|
|
1129
|
-
console.error(`🔓 Governance: Write Access Enabled (Subject to Zero-Trust Key).`);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
} catch (e) { }
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
// Authenticate
|
|
15
|
+
// 1. Authenticate
|
|
1137
16
|
const authResult = await authenticateApiKey(apiKey);
|
|
1138
|
-
|
|
1139
17
|
if (!authResult.success || !authResult.context) {
|
|
1140
18
|
console.error(`❌ Authentication failed: ${authResult.error}`);
|
|
1141
19
|
process.exit(1);
|
|
1142
20
|
}
|
|
1143
21
|
|
|
1144
|
-
const
|
|
22
|
+
const { supabase, userId } = authResult.context;
|
|
1145
23
|
|
|
1146
|
-
// Start Frank Watcher
|
|
1147
|
-
startFrankWatcher(
|
|
24
|
+
// 2. Start Telemetry (Frank Watcher)
|
|
25
|
+
startFrankWatcher(supabase, userId);
|
|
1148
26
|
|
|
1149
|
-
// Create
|
|
1150
|
-
const server =
|
|
1151
|
-
{
|
|
1152
|
-
name: SERVER_NAME,
|
|
1153
|
-
version: SERVER_VERSION,
|
|
1154
|
-
},
|
|
1155
|
-
{
|
|
1156
|
-
capabilities: {
|
|
1157
|
-
tools: {},
|
|
1158
|
-
resources: {},
|
|
1159
|
-
},
|
|
1160
|
-
}
|
|
1161
|
-
);
|
|
27
|
+
// 3. Create Server (Factory)
|
|
28
|
+
const server = createMcpServer();
|
|
1162
29
|
|
|
1163
|
-
//
|
|
1164
|
-
server
|
|
1165
|
-
return {
|
|
1166
|
-
tools: [
|
|
1167
|
-
...TOOLS,
|
|
1168
|
-
...registry.getTools()
|
|
1169
|
-
]
|
|
1170
|
-
};
|
|
1171
|
-
});
|
|
30
|
+
// 4. Setup Handlers (Core)
|
|
31
|
+
setupToolHandlers(server, { supabase, userId });
|
|
1172
32
|
|
|
1173
|
-
//
|
|
1174
|
-
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1175
|
-
return { resources: RESOURCES };
|
|
1176
|
-
});
|
|
1177
|
-
|
|
1178
|
-
// Handle read_resource request
|
|
1179
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
1180
|
-
const { uri } = request.params;
|
|
1181
|
-
|
|
1182
|
-
if (uri === 'rigstate://project_morals') {
|
|
1183
|
-
const morals = getProjectMorals();
|
|
1184
|
-
return {
|
|
1185
|
-
contents: [
|
|
1186
|
-
{
|
|
1187
|
-
uri,
|
|
1188
|
-
mimeType: 'text/markdown',
|
|
1189
|
-
text: morals.formatted
|
|
1190
|
-
}
|
|
1191
|
-
]
|
|
1192
|
-
};
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
throw new McpError(ErrorCode.InvalidParams, `Unknown resource: ${uri}`);
|
|
1196
|
-
});
|
|
1197
|
-
|
|
1198
|
-
// Handle call_tool request
|
|
1199
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
1200
|
-
try {
|
|
1201
|
-
const { name } = request.params;
|
|
1202
|
-
const args = request.params.arguments as any;
|
|
1203
|
-
|
|
1204
|
-
// 0. Check Migration Registry
|
|
1205
|
-
// If tool exists in registry, it runs. If arguments invalid, it throws (good).
|
|
1206
|
-
try {
|
|
1207
|
-
return await registry.callTool(name, args, {
|
|
1208
|
-
supabase: authContext.supabase,
|
|
1209
|
-
userId: authContext.userId
|
|
1210
|
-
});
|
|
1211
|
-
} catch (e: any) {
|
|
1212
|
-
if (e.message && e.message.includes(`Tool '${name}' not found`)) {
|
|
1213
|
-
// Tool not in registry, proceed to legacy switch
|
|
1214
|
-
} else {
|
|
1215
|
-
// Tool was in registry but failed (e.g. validation or runtime error)
|
|
1216
|
-
throw new McpError(ErrorCode.InvalidParams, e.message);
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
// GUARDIAN LOCK & WORKER AUTH
|
|
1221
|
-
const WRITE_TOOLS = [
|
|
1222
|
-
'write_to_file', 'replace_file_content', 'run_command',
|
|
1223
|
-
'save_decision', 'submit_idea', 'update_roadmap',
|
|
1224
|
-
'save_to_project_brain', 'add_roadmap_chunk',
|
|
1225
|
-
'update_roadmap_status', 'update_task_status'
|
|
1226
|
-
];
|
|
1227
|
-
|
|
1228
|
-
if (WRITE_TOOLS.includes(name)) {
|
|
1229
|
-
// Governance Policy Check (Rigstate v2.8)
|
|
1230
|
-
if (process.env.RIGSTATE_GOVERNANCE_WRITE === 'FALSE') {
|
|
1231
|
-
throw new McpError(ErrorCode.InvalidParams, '[GOVERNANCE_BLOCK]: Write access disabled via Rigstate Cloud.');
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
// Universal Zero-Trust Lock (Rigstate v2.7)
|
|
1235
|
-
const isWorker = await validateWorkerKey();
|
|
1236
|
-
|
|
1237
|
-
if (!isWorker) {
|
|
1238
|
-
throw new McpError(ErrorCode.InvalidParams, '[RIGSTATE_SECURITY_BLOCK]: Unauthorized attempt. No active Worker context detected.');
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
switch (name) {
|
|
1243
|
-
case 'get_project_context': {
|
|
1244
|
-
const parsed = GetProjectContextInputSchema.parse(args);
|
|
1245
|
-
const result = await getProjectContext(
|
|
1246
|
-
authContext.supabase,
|
|
1247
|
-
authContext.userId,
|
|
1248
|
-
parsed.projectId
|
|
1249
|
-
);
|
|
1250
|
-
return {
|
|
1251
|
-
content: [
|
|
1252
|
-
{
|
|
1253
|
-
type: 'text',
|
|
1254
|
-
text: result.summary
|
|
1255
|
-
}
|
|
1256
|
-
]
|
|
1257
|
-
};
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
case 'query_brain': {
|
|
1261
|
-
const parsed = QueryBrainInputSchema.parse(args);
|
|
1262
|
-
const result = await queryBrain(
|
|
1263
|
-
authContext.supabase,
|
|
1264
|
-
authContext.userId,
|
|
1265
|
-
parsed.projectId,
|
|
1266
|
-
parsed.query,
|
|
1267
|
-
parsed.limit,
|
|
1268
|
-
parsed.threshold
|
|
1269
|
-
);
|
|
1270
|
-
return {
|
|
1271
|
-
content: [
|
|
1272
|
-
{
|
|
1273
|
-
type: 'text',
|
|
1274
|
-
text: result.formatted
|
|
1275
|
-
}
|
|
1276
|
-
]
|
|
1277
|
-
};
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
|
-
case 'get_latest_decisions': {
|
|
1281
|
-
const parsed = GetLatestDecisionsInputSchema.parse(args);
|
|
1282
|
-
const result = await getLatestDecisions(
|
|
1283
|
-
authContext.supabase,
|
|
1284
|
-
authContext.userId,
|
|
1285
|
-
parsed.projectId,
|
|
1286
|
-
parsed.limit
|
|
1287
|
-
);
|
|
1288
|
-
return {
|
|
1289
|
-
content: [
|
|
1290
|
-
{
|
|
1291
|
-
type: 'text',
|
|
1292
|
-
text: result.summary
|
|
1293
|
-
}
|
|
1294
|
-
]
|
|
1295
|
-
};
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
|
-
case 'list_roadmap_tasks': {
|
|
1299
|
-
const parsed = ListRoadmapTasksInputSchema.parse(args);
|
|
1300
|
-
const result = await listRoadmapTasks(
|
|
1301
|
-
authContext.supabase,
|
|
1302
|
-
authContext.userId,
|
|
1303
|
-
parsed.projectId
|
|
1304
|
-
);
|
|
1305
|
-
return {
|
|
1306
|
-
content: [
|
|
1307
|
-
{
|
|
1308
|
-
type: 'text',
|
|
1309
|
-
text: result.formatted
|
|
1310
|
-
}
|
|
1311
|
-
]
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
case 'check_agent_bridge': {
|
|
1317
|
-
const parsed = CheckAgentBridgeInputSchema.parse(args);
|
|
1318
|
-
const result = await checkAgentBridge(
|
|
1319
|
-
authContext.supabase,
|
|
1320
|
-
parsed.projectId,
|
|
1321
|
-
parsed.action,
|
|
1322
|
-
parsed.bridgeId,
|
|
1323
|
-
parsed.status,
|
|
1324
|
-
parsed.summary,
|
|
1325
|
-
parsed.proposal,
|
|
1326
|
-
// @ts-ignore - execution_summary is a new optional prop
|
|
1327
|
-
parsed.execution_summary
|
|
1328
|
-
);
|
|
1329
|
-
return {
|
|
1330
|
-
content: [
|
|
1331
|
-
{
|
|
1332
|
-
type: 'text',
|
|
1333
|
-
text: JSON.stringify(result, null, 2)
|
|
1334
|
-
}
|
|
1335
|
-
]
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
case 'check_rules_sync': {
|
|
1341
|
-
const parsed = CheckRulesSyncInputSchema.parse(args);
|
|
1342
|
-
const result = await checkRulesSync(
|
|
1343
|
-
authContext.supabase,
|
|
1344
|
-
parsed.projectId,
|
|
1345
|
-
parsed.currentRulesContent
|
|
1346
|
-
);
|
|
1347
|
-
return {
|
|
1348
|
-
content: [
|
|
1349
|
-
{
|
|
1350
|
-
type: 'text',
|
|
1351
|
-
text: JSON.stringify(result, null, 2)
|
|
1352
|
-
}
|
|
1353
|
-
]
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
case 'get_next_roadmap_step': {
|
|
1358
|
-
const parsed = GetNextRoadmapStepInputSchema.parse(args);
|
|
1359
|
-
const result = await getNextRoadmapStep(
|
|
1360
|
-
authContext.supabase,
|
|
1361
|
-
parsed.projectId,
|
|
1362
|
-
parsed.currentStepId
|
|
1363
|
-
);
|
|
1364
|
-
return {
|
|
1365
|
-
content: [
|
|
1366
|
-
{
|
|
1367
|
-
type: 'text',
|
|
1368
|
-
text: JSON.stringify(result, null, 2)
|
|
1369
|
-
}
|
|
1370
|
-
]
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
case 'complete_roadmap_task': {
|
|
1375
|
-
const args = request.params.arguments as any;
|
|
1376
|
-
if (!args.projectId || !args.summary) {
|
|
1377
|
-
throw new Error('projectId and summary are required');
|
|
1378
|
-
}
|
|
1379
|
-
const result = await completeRoadmapTask(
|
|
1380
|
-
authContext.supabase,
|
|
1381
|
-
args.projectId,
|
|
1382
|
-
args.summary,
|
|
1383
|
-
args.taskId,
|
|
1384
|
-
args.gitDiff
|
|
1385
|
-
);
|
|
1386
|
-
return {
|
|
1387
|
-
content: [{
|
|
1388
|
-
type: 'text',
|
|
1389
|
-
text: result.message
|
|
1390
|
-
}]
|
|
1391
|
-
};
|
|
1392
|
-
}
|
|
1393
|
-
|
|
1394
|
-
case 'generate_professional_pdf': {
|
|
1395
|
-
const parsed = GenerateProfessionalPDFInputSchema.parse(args);
|
|
1396
|
-
const result = await generateProfessionalPdf(
|
|
1397
|
-
authContext.supabase,
|
|
1398
|
-
authContext.userId,
|
|
1399
|
-
parsed.projectId,
|
|
1400
|
-
parsed.reportType as any
|
|
1401
|
-
);
|
|
1402
|
-
return {
|
|
1403
|
-
content: [
|
|
1404
|
-
{
|
|
1405
|
-
type: 'text',
|
|
1406
|
-
text: JSON.stringify(result, null, 2)
|
|
1407
|
-
}
|
|
1408
|
-
]
|
|
1409
|
-
};
|
|
1410
|
-
}
|
|
1411
|
-
|
|
1412
|
-
case 'get_agent_status': {
|
|
1413
|
-
return {
|
|
1414
|
-
content: [
|
|
1415
|
-
{
|
|
1416
|
-
type: 'text',
|
|
1417
|
-
text: JSON.stringify(watcherState, null, 2)
|
|
1418
|
-
}
|
|
1419
|
-
]
|
|
1420
|
-
};
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
// =============================================================
|
|
1424
|
-
// BRYNJAR - THE LIBRARIAN (Archaeological Operations)
|
|
1425
|
-
// =============================================================
|
|
1426
|
-
|
|
1427
|
-
case 'archaeological_scan': {
|
|
1428
|
-
const parsed = ArchaeologicalScanInputSchema.parse(args);
|
|
1429
|
-
const result = await performArchaeologicalScan(
|
|
1430
|
-
authContext.supabase,
|
|
1431
|
-
parsed.projectId,
|
|
1432
|
-
parsed.gitLog,
|
|
1433
|
-
parsed.fileTree
|
|
1434
|
-
);
|
|
1435
|
-
return {
|
|
1436
|
-
content: [
|
|
1437
|
-
{
|
|
1438
|
-
type: 'text',
|
|
1439
|
-
text: JSON.stringify(result, null, 2)
|
|
1440
|
-
}
|
|
1441
|
-
]
|
|
1442
|
-
};
|
|
1443
|
-
}
|
|
1444
|
-
|
|
1445
|
-
case 'import_ghost_features': {
|
|
1446
|
-
const parsed = ImportGhostFeaturesInputSchema.parse(args);
|
|
1447
|
-
const result = await importGhostFeatures(
|
|
1448
|
-
authContext.supabase,
|
|
1449
|
-
parsed.projectId,
|
|
1450
|
-
parsed.features
|
|
1451
|
-
);
|
|
1452
|
-
return {
|
|
1453
|
-
content: [
|
|
1454
|
-
{
|
|
1455
|
-
type: 'text',
|
|
1456
|
-
text: JSON.stringify(result, null, 2)
|
|
1457
|
-
}
|
|
1458
|
-
]
|
|
1459
|
-
};
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
// =============================================================
|
|
1463
|
-
// WRITE OPERATIONS (DEPRECATED - READ ONLY MODE)
|
|
1464
|
-
// =============================================================
|
|
1465
|
-
|
|
1466
|
-
case 'save_decision': {
|
|
1467
|
-
return {
|
|
1468
|
-
content: [{
|
|
1469
|
-
type: 'text',
|
|
1470
|
-
text: '🚫 [READ-ONLY MODE] save_decision is deprecated in MCP. Please use the Rigstate Dashboard to record decisions.'
|
|
1471
|
-
}],
|
|
1472
|
-
isError: true
|
|
1473
|
-
};
|
|
1474
|
-
}
|
|
1475
|
-
|
|
1476
|
-
case 'submit_idea': {
|
|
1477
|
-
return {
|
|
1478
|
-
content: [{
|
|
1479
|
-
type: 'text',
|
|
1480
|
-
text: '🚫 [READ-ONLY MODE] submit_idea is deprecated in MCP. Please use the Rigstate Dashboard (Idea Lab) to submit new ideas.'
|
|
1481
|
-
}],
|
|
1482
|
-
isError: true
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
case 'update_roadmap': {
|
|
1487
|
-
return {
|
|
1488
|
-
content: [{
|
|
1489
|
-
type: 'text',
|
|
1490
|
-
text: '🚫 [READ-ONLY MODE] update_roadmap is deprecated in MCP. Use the Rigstate CLI ("rigstate sync") or the Dashboard to update tasks.'
|
|
1491
|
-
}],
|
|
1492
|
-
isError: true
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
case 'run_architecture_audit': {
|
|
1497
|
-
return {
|
|
1498
|
-
content: [{
|
|
1499
|
-
type: 'text',
|
|
1500
|
-
text: '🚫 [READ-ONLY MODE] run_architecture_audit in MCP is deprecated. Use the Rigstate CLI command "rigstate check" for deterministic architectural validation.'
|
|
1501
|
-
}],
|
|
1502
|
-
isError: true
|
|
1503
|
-
};
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
|
-
// =============================================================
|
|
1507
|
-
// TEACHER MODE TOOLS
|
|
1508
|
-
// =============================================================
|
|
1509
|
-
|
|
1510
|
-
case 'refine_logic': {
|
|
1511
|
-
const parsed = RefineLogicInputSchema.parse(args);
|
|
1512
|
-
const result = await refineLogic(
|
|
1513
|
-
authContext.supabase,
|
|
1514
|
-
authContext.userId,
|
|
1515
|
-
parsed.projectId,
|
|
1516
|
-
parsed.originalReasoning,
|
|
1517
|
-
parsed.userCorrection,
|
|
1518
|
-
parsed.scope || 'project'
|
|
1519
|
-
);
|
|
1520
|
-
return {
|
|
1521
|
-
content: [
|
|
1522
|
-
{
|
|
1523
|
-
type: 'text',
|
|
1524
|
-
text: `${result.message}\n\nTrace ID: ${result.traceId}`
|
|
1525
|
-
}
|
|
1526
|
-
]
|
|
1527
|
-
};
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
case 'get_learned_instructions': {
|
|
1531
|
-
const parsed = GetLearnedInstructionsInputSchema.parse(args);
|
|
1532
|
-
const result = await getLearnedInstructions(
|
|
1533
|
-
authContext.supabase,
|
|
1534
|
-
authContext.userId,
|
|
1535
|
-
parsed.projectId
|
|
1536
|
-
);
|
|
1537
|
-
return {
|
|
1538
|
-
content: [
|
|
1539
|
-
{
|
|
1540
|
-
type: 'text',
|
|
1541
|
-
text: result.formatted
|
|
1542
|
-
}
|
|
1543
|
-
]
|
|
1544
|
-
};
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
case 'sync_ide_rules': {
|
|
1548
|
-
const { projectId } = GenerateCursorRulesInputSchema.parse(request.params.arguments);
|
|
1549
|
-
const result = await syncIdeRules(authContext.supabase, projectId);
|
|
1550
|
-
return {
|
|
1551
|
-
content: [{
|
|
1552
|
-
type: 'text',
|
|
1553
|
-
text: `FileName: ${result.fileName}\n\nContent:\n${result.content}`
|
|
1554
|
-
}]
|
|
1555
|
-
};
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
default:
|
|
1559
|
-
throw new McpError(
|
|
1560
|
-
ErrorCode.MethodNotFound,
|
|
1561
|
-
`Unknown tool: ${name}`
|
|
1562
|
-
);
|
|
1563
|
-
|
|
1564
|
-
// =============================================================
|
|
1565
|
-
// STRUCTURAL SHIELD (EINAR & SVEN)
|
|
1566
|
-
// =============================================================
|
|
1567
|
-
|
|
1568
|
-
case 'analyze_dependency_graph': {
|
|
1569
|
-
const parsed = AnalyzeDependencyGraphInputSchema.parse(args);
|
|
1570
|
-
const result = await analyzeDependencyGraph(parsed);
|
|
1571
|
-
return {
|
|
1572
|
-
content: [
|
|
1573
|
-
{
|
|
1574
|
-
type: 'text',
|
|
1575
|
-
text: JSON.stringify(result, null, 2)
|
|
1576
|
-
}
|
|
1577
|
-
]
|
|
1578
|
-
};
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
case 'audit_rls_status': {
|
|
1582
|
-
const parsed = AuditRlsStatusInputSchema.parse(args);
|
|
1583
|
-
const result = await auditRlsStatus(authContext.supabase, parsed);
|
|
1584
|
-
return {
|
|
1585
|
-
content: [
|
|
1586
|
-
{
|
|
1587
|
-
type: 'text',
|
|
1588
|
-
text: JSON.stringify(result, null, 2)
|
|
1589
|
-
}
|
|
1590
|
-
]
|
|
1591
|
-
};
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
// =============================================================
|
|
1595
|
-
// INTELLIGENCE CORE (MAJA & ASTRID)
|
|
1596
|
-
// =============================================================
|
|
1597
|
-
|
|
1598
|
-
case 'query_project_brain': {
|
|
1599
|
-
const parsed = QueryProjectBrainInputSchema.parse(args);
|
|
1600
|
-
const result = await queryProjectBrain(
|
|
1601
|
-
authContext.supabase,
|
|
1602
|
-
authContext.userId,
|
|
1603
|
-
parsed
|
|
1604
|
-
);
|
|
1605
|
-
return {
|
|
1606
|
-
content: [
|
|
1607
|
-
{
|
|
1608
|
-
type: 'text',
|
|
1609
|
-
text: JSON.stringify(result, null, 2)
|
|
1610
|
-
}
|
|
1611
|
-
]
|
|
1612
|
-
};
|
|
1613
|
-
}
|
|
1614
|
-
|
|
1615
|
-
case 'fetch_package_health': {
|
|
1616
|
-
const parsed = FetchPackageHealthInputSchema.parse(args);
|
|
1617
|
-
const result = await fetchPackageHealth(parsed);
|
|
1618
|
-
return {
|
|
1619
|
-
content: [
|
|
1620
|
-
{
|
|
1621
|
-
type: 'text',
|
|
1622
|
-
text: JSON.stringify(result, null, 2)
|
|
1623
|
-
}
|
|
1624
|
-
]
|
|
1625
|
-
};
|
|
1626
|
-
}
|
|
1627
|
-
|
|
1628
|
-
// =============================================================
|
|
1629
|
-
// ACTIVE MEMORY & PLANNING (MAJA & KINE)
|
|
1630
|
-
// =============================================================
|
|
1631
|
-
|
|
1632
|
-
case 'save_to_project_brain':
|
|
1633
|
-
case 'update_roadmap_status':
|
|
1634
|
-
case 'add_roadmap_chunk': {
|
|
1635
|
-
return {
|
|
1636
|
-
content: [{
|
|
1637
|
-
type: 'text',
|
|
1638
|
-
text: '🚫 [READ-ONLY MODE] Planning and active memory writes are deprecated in MCP. Use the Rigstate CLI or Dashboard.'
|
|
1639
|
-
}],
|
|
1640
|
-
isError: true
|
|
1641
|
-
};
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
// =============================================================
|
|
1645
|
-
// UI/UX & RESEARCH (LINUS & ASTRID)
|
|
1646
|
-
// =============================================================
|
|
1647
|
-
|
|
1648
|
-
case 'analyze_ui_component': {
|
|
1649
|
-
const parsed = AnalyzeUiComponentInputSchema.parse(args);
|
|
1650
|
-
const result = await analyzeUiComponent(parsed);
|
|
1651
|
-
return {
|
|
1652
|
-
content: [
|
|
1653
|
-
{
|
|
1654
|
-
type: 'text',
|
|
1655
|
-
text: JSON.stringify(result, null, 2)
|
|
1656
|
-
}
|
|
1657
|
-
]
|
|
1658
|
-
};
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
case 'apply_design_system': {
|
|
1662
|
-
const parsed = ApplyDesignSystemInputSchema.parse(args);
|
|
1663
|
-
const result = await applyDesignSystem(parsed);
|
|
1664
|
-
return {
|
|
1665
|
-
content: [
|
|
1666
|
-
{
|
|
1667
|
-
type: 'text',
|
|
1668
|
-
text: JSON.stringify(result, null, 2)
|
|
1669
|
-
}
|
|
1670
|
-
]
|
|
1671
|
-
};
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
case 'fetch_ui_library_docs': {
|
|
1675
|
-
const parsed = FetchUiLibraryDocsInputSchema.parse(args);
|
|
1676
|
-
const result = await fetchUiLibraryDocs(parsed);
|
|
1677
|
-
return {
|
|
1678
|
-
content: [
|
|
1679
|
-
{
|
|
1680
|
-
type: 'text',
|
|
1681
|
-
text: JSON.stringify(result, null, 2)
|
|
1682
|
-
}
|
|
1683
|
-
]
|
|
1684
|
-
};
|
|
1685
|
-
}
|
|
1686
|
-
|
|
1687
|
-
// =========================================================
|
|
1688
|
-
// PENDING TASKS (IDE Integration)
|
|
1689
|
-
// =========================================================
|
|
1690
|
-
case 'get_pending_tasks': {
|
|
1691
|
-
const parsed = GetPendingTasksInputSchema.parse(args);
|
|
1692
|
-
const result = await getPendingTasks(
|
|
1693
|
-
authContext.supabase,
|
|
1694
|
-
parsed.projectId
|
|
1695
|
-
);
|
|
1696
|
-
return {
|
|
1697
|
-
content: [
|
|
1698
|
-
{
|
|
1699
|
-
type: 'text',
|
|
1700
|
-
text: JSON.stringify(result, null, 2)
|
|
1701
|
-
}
|
|
1702
|
-
]
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
case 'update_task_status': {
|
|
1707
|
-
const parsed = UpdateTaskStatusInputSchema.parse(args);
|
|
1708
|
-
const result = await updateTaskStatus(
|
|
1709
|
-
authContext.supabase,
|
|
1710
|
-
parsed.projectId,
|
|
1711
|
-
parsed.taskId,
|
|
1712
|
-
parsed.status,
|
|
1713
|
-
parsed.executionSummary
|
|
1714
|
-
);
|
|
1715
|
-
return {
|
|
1716
|
-
content: [
|
|
1717
|
-
{
|
|
1718
|
-
type: 'text',
|
|
1719
|
-
text: JSON.stringify(result, null, 2)
|
|
1720
|
-
}
|
|
1721
|
-
]
|
|
1722
|
-
};
|
|
1723
|
-
}
|
|
1724
|
-
}
|
|
1725
|
-
} catch (error: any) {
|
|
1726
|
-
// Handle Zod validation errors
|
|
1727
|
-
if (error.name === 'ZodError') {
|
|
1728
|
-
throw new McpError(
|
|
1729
|
-
ErrorCode.InvalidParams,
|
|
1730
|
-
`Invalid parameters: ${error.errors.map((e: any) => e.message).join(', ')}`
|
|
1731
|
-
);
|
|
1732
|
-
}
|
|
1733
|
-
|
|
1734
|
-
// Handle access denied errors
|
|
1735
|
-
if (error.message?.includes('access denied') || error.message?.includes('not found')) {
|
|
1736
|
-
throw new McpError(
|
|
1737
|
-
ErrorCode.InvalidParams,
|
|
1738
|
-
error.message
|
|
1739
|
-
);
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
// Handle database constraint errors (write operations)
|
|
1743
|
-
if (error.message?.includes('Permission denied') ||
|
|
1744
|
-
error.message?.includes('constraint') ||
|
|
1745
|
-
error.message?.includes('already exists')) {
|
|
1746
|
-
throw new McpError(
|
|
1747
|
-
ErrorCode.InvalidParams,
|
|
1748
|
-
`Write operation failed: ${error.message}`
|
|
1749
|
-
);
|
|
1750
|
-
}
|
|
1751
|
-
|
|
1752
|
-
// Handle write operation specific errors
|
|
1753
|
-
if (error.message?.includes('Failed to')) {
|
|
1754
|
-
throw new McpError(
|
|
1755
|
-
ErrorCode.InternalError,
|
|
1756
|
-
error.message
|
|
1757
|
-
);
|
|
1758
|
-
}
|
|
1759
|
-
|
|
1760
|
-
// Re-throw MCP errors as-is
|
|
1761
|
-
if (error instanceof McpError) {
|
|
1762
|
-
throw error;
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
// Re-throw other errors
|
|
1766
|
-
throw new McpError(
|
|
1767
|
-
ErrorCode.InternalError,
|
|
1768
|
-
error.message || 'An unexpected error occurred'
|
|
1769
|
-
);
|
|
1770
|
-
}
|
|
1771
|
-
});
|
|
1772
|
-
|
|
1773
|
-
// Start server with stdio transport
|
|
33
|
+
// 5. Connect Transport
|
|
1774
34
|
const transport = new StdioServerTransport();
|
|
1775
35
|
await server.connect(transport);
|
|
1776
36
|
|
|
1777
|
-
|
|
1778
|
-
console.error(`✅ Rigstate MCP Server v${SERVER_VERSION} started`);
|
|
1779
|
-
console.error(` User ID: ${authContext.userId}`);
|
|
1780
|
-
console.error(` Mode: Read-Only (write ops deprecated)`);
|
|
1781
|
-
|
|
1782
|
-
// DEPRECATED: Frank Watcher is now handled by CLI daemon
|
|
1783
|
-
// Use "rigstate daemon" for background task processing
|
|
1784
|
-
// startFrankWatcher(authContext.supabase, authContext.userId);
|
|
37
|
+
console.error('🛰️ Rigstate MCP Server (Evolutionary) running on stdio');
|
|
1785
38
|
}
|
|
1786
39
|
|
|
1787
|
-
// Run the server
|
|
1788
40
|
main().catch((error) => {
|
|
1789
|
-
console.error('
|
|
41
|
+
console.error('FATAL ERROR:', error);
|
|
1790
42
|
process.exit(1);
|
|
1791
43
|
});
|
|
1792
|
-
|