@rigstate/mcp 0.7.2 → 0.7.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/dist/index.js CHANGED
@@ -1937,14 +1937,19 @@ async function getProjectContext(supabase, userId, projectId) {
1937
1937
  repository_tree: projectRow.repository_tree
1938
1938
  };
1939
1939
  const stackDef = projectRow.architectural_dna?.stack_definition;
1940
- const [activeTaskResult, nextTaskResult] = await Promise.all([
1941
- supabase.from("roadmap_chunks").select("id, title, step_number, role, instruction_set").eq("project_id", projectId).in("status", ["IN_PROGRESS", "ACTIVE"]).limit(1).maybeSingle(),
1942
- supabase.from("roadmap_chunks").select("id, title, step_number, role").eq("project_id", projectId).in("status", ["PENDING", "LOCKED"]).order("step_number", { ascending: true }).limit(1).maybeSingle()
1943
- ]);
1944
- const activeTask = activeTaskResult.data;
1945
- const nextTask = nextTaskResult.data;
1946
- const { data: agentTasks } = await supabase.from("agent_bridge").select("id, roadmap_chunks(title), execution_summary, completed_at").eq("project_id", projectId).eq("status", "COMPLETED").order("completed_at", { ascending: false }).limit(2);
1947
- const { data: roadmapItems } = await supabase.from("roadmap_chunks").select("title, status, updated_at").eq("project_id", projectId).order("updated_at", { ascending: false }).limit(2);
1940
+ const { data: allChunks, error: chunksError } = await supabase.rpc("get_roadmap_chunks_secure", {
1941
+ p_project_id: projectId,
1942
+ p_user_id: userId
1943
+ });
1944
+ const tasks = allChunks || [];
1945
+ const activeTask = tasks.find((t) => ["IN_PROGRESS", "ACTIVE"].includes(t.status));
1946
+ const nextTask = tasks.filter((t) => ["PENDING", "LOCKED"].includes(t.status)).sort((a, b) => a.step_number - b.step_number)[0];
1947
+ const { data: agentTasks } = await supabase.rpc("get_agent_bridge_secure", {
1948
+ p_project_id: projectId,
1949
+ p_user_id: userId,
1950
+ p_limit: 2
1951
+ });
1952
+ const roadmapItems = tasks.sort((a, b) => new Date(b.updated_at || b.created_at).getTime() - new Date(a.updated_at || a.created_at).getTime()).slice(0, 2);
1948
1953
  const techStack = {
1949
1954
  framework: null,
1950
1955
  orm: null,
@@ -2027,7 +2032,7 @@ Description: ${project.description}`);
2027
2032
  summaryParts.push("\nLatest AI Executions:");
2028
2033
  agentTasks.forEach((t) => {
2029
2034
  const time = t.completed_at ? new Date(t.completed_at).toLocaleString() : "Recently";
2030
- summaryParts.push(`- [${time}] ${t.roadmap_chunks?.title || "Task"}: ${t.execution_summary || "Completed"}`);
2035
+ summaryParts.push(`- [${time}] ${t.roadmap_title || "Task"}: ${t.execution_summary || "Completed"}`);
2031
2036
  });
2032
2037
  }
2033
2038
  if (roadmapItems && roadmapItems.length > 0) {
@@ -2211,8 +2216,11 @@ including active roadmap steps and council session feedback.`,
2211
2216
  }
2212
2217
  });
2213
2218
  async function getLatestDecisions(supabase, userId, projectId, limit = 5) {
2214
- const { data: project, error: projectError } = await supabase.from("projects").select("id").eq("id", projectId).eq("owner_id", userId).single();
2215
- if (projectError || !project) {
2219
+ const { data: hasAccess, error: accessError } = await supabase.rpc("check_project_access_secure", {
2220
+ p_project_id: projectId,
2221
+ p_user_id: userId
2222
+ });
2223
+ if (accessError || !hasAccess) {
2216
2224
  throw new Error("Project not found or access denied");
2217
2225
  }
2218
2226
  const { data: sessionData, error: sessionError } = await supabase.from("council_sessions").select("id, project_id, recruited_agents, feedback_summary, duration_ms, sprints_count, tasks_count, created_at").eq("project_id", projectId).order("created_at", { ascending: false }).limit(limit);
@@ -2767,22 +2775,30 @@ Shows active and locked steps with their step numbers.`,
2767
2775
  }
2768
2776
  });
2769
2777
  async function listRoadmapTasks(supabase, userId, projectId) {
2770
- const { data: project, error: projectError } = await supabase.from("projects").select("id").eq("id", projectId).eq("owner_id", userId).single();
2771
- if (projectError || !project) {
2772
- throw new Error("Project not found or access denied");
2773
- }
2774
- const { data: tasks, error } = await supabase.from("roadmap_chunks").select("id, title, priority, status, step_number, prompt_content").eq("project_id", projectId).neq("status", "COMPLETED").order("priority", { ascending: false }).order("step_number", { ascending: true });
2778
+ const { data: tasks, error } = await supabase.rpc("get_roadmap_chunks_secure", {
2779
+ p_project_id: projectId,
2780
+ p_user_id: userId
2781
+ });
2775
2782
  if (error) {
2783
+ if (error.message.includes("Access Denied")) {
2784
+ throw new Error("Project not found or access denied");
2785
+ }
2776
2786
  console.error("Failed to fetch roadmap tasks:", error);
2777
2787
  throw new Error("Failed to fetch roadmap tasks");
2778
2788
  }
2779
- const formatted = (tasks || []).length > 0 ? (tasks || []).map((t) => {
2789
+ const activeTasks = (tasks || []).filter((t) => t.status !== "COMPLETED").sort((a, b) => {
2790
+ if (a.priority !== b.priority) {
2791
+ const priorityOrder = { "CRITICAL": 3, "HIGH": 2, "MEDIUM": 1, "LOW": 0 };
2792
+ return (priorityOrder[b.priority] || 0) - (priorityOrder[a.priority] || 0);
2793
+ }
2794
+ return a.step_number - b.step_number;
2795
+ });
2796
+ const formatted = activeTasks.length > 0 ? activeTasks.map((t) => {
2780
2797
  const statusEmoji = t.status === "ACTIVE" ? "\u{1F535}" : "\u{1F512}";
2781
- const priorityStr = t.priority ? `[${t.priority}]` : "";
2782
2798
  return `${statusEmoji} Step ${t.step_number}: ${t.title} (ID: ${t.id})`;
2783
2799
  }).join("\n") : "No active or locked tasks found in the roadmap.";
2784
2800
  return {
2785
- tasks: (tasks || []).map((t) => ({
2801
+ tasks: activeTasks.map((t) => ({
2786
2802
  id: t.id,
2787
2803
  title: t.title,
2788
2804
  priority: t.priority,
@@ -2804,29 +2820,38 @@ Useful for transitioning between tasks.`,
2804
2820
  handler: async (args, context) => {
2805
2821
  const result = await getNextRoadmapStep(
2806
2822
  context.supabase,
2823
+ context.userId,
2807
2824
  args.projectId,
2808
2825
  args.currentStepId
2809
2826
  );
2810
2827
  return { content: [{ type: "text", text: result.message }] };
2811
2828
  }
2812
2829
  });
2813
- async function getNextRoadmapStep(supabase, projectId, currentStepId) {
2830
+ async function getNextRoadmapStep(supabase, userId, projectId, currentStepId) {
2831
+ const { data: allTasks, error: fetchError } = await supabase.rpc("get_roadmap_chunks_secure", {
2832
+ p_project_id: projectId,
2833
+ p_user_id: userId
2834
+ });
2835
+ if (fetchError) {
2836
+ throw new Error(`Failed to fetch roadmap data: ${fetchError.message}`);
2837
+ }
2838
+ const tasks = allTasks || [];
2814
2839
  let currentStepNumber = 0;
2815
2840
  if (currentStepId) {
2816
- const { data: current } = await supabase.from("roadmap_chunks").select("step_number").eq("id", currentStepId).single();
2841
+ const current = tasks.find((t) => t.id === currentStepId);
2817
2842
  if (current) {
2818
2843
  currentStepNumber = current.step_number;
2819
2844
  }
2820
2845
  } else {
2821
- const { data: active } = await supabase.from("roadmap_chunks").select("step_number").eq("project_id", projectId).in("status", ["ACTIVE", "IN_PROGRESS"]).order("step_number", { ascending: true }).limit(1).single();
2846
+ const active = tasks.filter((t) => ["ACTIVE", "IN_PROGRESS"].includes(t.status)).sort((a, b) => a.step_number - b.step_number)[0];
2822
2847
  if (active) {
2823
- currentStepNumber = active.step_number;
2848
+ return {
2849
+ nextStep: active,
2850
+ message: `Current active step: [Step ${active.step_number}] ${active.title}`
2851
+ };
2824
2852
  }
2825
2853
  }
2826
- const { data: nextStep, error } = await supabase.from("roadmap_chunks").select("*").eq("project_id", projectId).gt("step_number", currentStepNumber).neq("status", "COMPLETED").order("step_number", { ascending: true }).limit(1).single();
2827
- if (error && error.code !== "PGRST116") {
2828
- throw new Error(`Failed to fetch next roadmap step: ${error.message}`);
2829
- }
2854
+ const nextStep = tasks.filter((t) => t.step_number > currentStepNumber && t.status !== "COMPLETED").sort((a, b) => a.step_number - b.step_number)[0];
2830
2855
  if (!nextStep) {
2831
2856
  return {
2832
2857
  nextStep: null,
@@ -3617,8 +3642,8 @@ registry.register({
3617
3642
  });
3618
3643
  async function saveToProjectBrain(supabase, userId, input) {
3619
3644
  const { projectId, title, content, category, tags } = input;
3620
- const { data: p, error: pErr } = await supabase.from("projects").select("id").eq("id", projectId).eq("owner_id", userId).single();
3621
- if (pErr || !p) throw new Error("Access denied");
3645
+ const { data: hasAccess, error: accessError } = await supabase.rpc("check_project_access_secure", { p_project_id: projectId, p_user_id: userId });
3646
+ if (accessError || !hasAccess) throw new Error("Access denied");
3622
3647
  const fullContent = `# ${title}
3623
3648
 
3624
3649
  ${content}`;
@@ -3640,6 +3665,8 @@ ${content}`;
3640
3665
  }
3641
3666
  async function updateRoadmapStatus(supabase, userId, input) {
3642
3667
  const { projectId, chunkId, status } = input;
3668
+ const { data: hasAccess, error: accessError } = await supabase.rpc("check_project_access_secure", { p_project_id: projectId, p_user_id: userId });
3669
+ if (accessError || !hasAccess) throw new Error("Access denied");
3643
3670
  const dbStatus = status === "TODO" ? "LOCKED" : status === "IN_PROGRESS" ? "ACTIVE" : "COMPLETED";
3644
3671
  const { error } = await supabase.from("roadmap_chunks").update({ status: dbStatus }).eq("id", chunkId).eq("project_id", projectId);
3645
3672
  if (error) throw new Error(`Update failed: ${error.message}`);
@@ -3653,6 +3680,8 @@ async function updateRoadmapStatus(supabase, userId, input) {
3653
3680
  }
3654
3681
  async function addRoadmapChunk(supabase, userId, input) {
3655
3682
  const { projectId, title, description, priority } = input;
3683
+ const { data: hasAccess, error: accessError } = await supabase.rpc("check_project_access_secure", { p_project_id: projectId, p_user_id: userId });
3684
+ if (accessError || !hasAccess) throw new Error("Access denied");
3656
3685
  const { data: maxStep } = await supabase.from("roadmap_chunks").select("step_number").eq("project_id", projectId).order("step_number", { ascending: false }).limit(1).single();
3657
3686
  const nextStepNum = (maxStep?.step_number || 0) + 1;
3658
3687
  const { data, error } = await supabase.from("roadmap_chunks").insert({