#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema
} from "@modelcontextprotocol/sdk/types.js";
import Database from "better-sqlite3";
import { join } from "path";
import { existsSync, mkdirSync } from "fs";
import {
  LinearTaskManager
} from "../features/tasks/linear-task-manager.js";
import { FrameManager } from "../core/context/frame-manager.js";
import { AgentTaskManager } from "../agents/core/agent-task-manager.js";
import { logger } from "../core/monitoring/logger.js";
const PROJECT_ROOT = process.env["STACKMEMORY_PROJECT"] || process.cwd();
const stackmemoryDir = join(PROJECT_ROOT, ".stackmemory");
if (!existsSync(stackmemoryDir)) {
  mkdirSync(stackmemoryDir, { recursive: true });
}
const db = new Database(join(stackmemoryDir, "cache.db"));
const taskStore = new LinearTaskManager(PROJECT_ROOT, db);
const frameManager = new FrameManager(db, PROJECT_ROOT, void 0);
const agentTaskManager = new AgentTaskManager(taskStore, frameManager);
let _claudeSessionId = null;
let claudeFrameId = null;
const TOOLS = [
  {
    name: "create_task",
    description: "Create a new task in StackMemory with automatic agent assistance",
    inputSchema: {
      type: "object",
      properties: {
        title: { type: "string", description: "Task title" },
        description: {
          type: "string",
          description: "Detailed task description"
        },
        priority: {
          type: "string",
          enum: ["low", "medium", "high", "urgent"],
          description: "Task priority"
        },
        tags: {
          type: "array",
          items: { type: "string" },
          description: "Tags for categorization"
        },
        autoExecute: {
          type: "boolean",
          description: "Automatically start agent execution"
        }
      },
      required: ["title"]
    }
  },
  {
    name: "execute_task",
    description: "Execute a task using AI agent with verification loops",
    inputSchema: {
      type: "object",
      properties: {
        taskId: { type: "string", description: "Task ID to execute" },
        maxTurns: {
          type: "number",
          description: "Maximum turns (default 10)",
          minimum: 1,
          maximum: 20
        }
      },
      required: ["taskId"]
    }
  },
  {
    name: "task_status",
    description: "Get status of a task or all active tasks",
    inputSchema: {
      type: "object",
      properties: {
        taskId: { type: "string", description: "Optional specific task ID" }
      }
    }
  },
  {
    name: "save_context",
    description: "Save important context from current Claude conversation",
    inputSchema: {
      type: "object",
      properties: {
        content: { type: "string", description: "Context to save" },
        type: {
          type: "string",
          enum: ["decision", "constraint", "learning", "code", "error"],
          description: "Type of context"
        },
        importance: {
          type: "number",
          minimum: 0,
          maximum: 1,
          description: "Importance score (0-1)"
        }
      },
      required: ["content", "type"]
    }
  },
  {
    name: "load_context",
    description: "Load relevant context from StackMemory",
    inputSchema: {
      type: "object",
      properties: {
        query: { type: "string", description: "Search query for context" },
        limit: {
          type: "number",
          description: "Maximum results",
          minimum: 1,
          maximum: 20
        },
        frameId: { type: "string", description: "Optional specific frame ID" }
      },
      required: ["query"]
    }
  },
  {
    name: "agent_turn",
    description: "Execute a single turn in an active agent session",
    inputSchema: {
      type: "object",
      properties: {
        sessionId: { type: "string", description: "Active session ID" },
        action: { type: "string", description: "Action to perform" },
        context: {
          type: "object",
          description: "Additional context for the action"
        }
      },
      required: ["sessionId", "action"]
    }
  },
  {
    name: "session_feedback",
    description: "Get feedback from the last agent turn",
    inputSchema: {
      type: "object",
      properties: {
        sessionId: { type: "string", description: "Session ID" }
      },
      required: ["sessionId"]
    }
  },
  {
    name: "breakdown_task",
    description: "Break down a complex task into subtasks",
    inputSchema: {
      type: "object",
      properties: {
        taskId: { type: "string", description: "Task ID to break down" }
      },
      required: ["taskId"]
    }
  },
  {
    name: "list_active_sessions",
    description: "List all active agent sessions",
    inputSchema: {
      type: "object",
      properties: {}
    }
  },
  {
    name: "retry_session",
    description: "Retry a failed session with learned context",
    inputSchema: {
      type: "object",
      properties: {
        sessionId: { type: "string", description: "Session ID to retry" }
      },
      required: ["sessionId"]
    }
  }
];
const server = new Server(
  {
    name: "stackmemory",
    version: "1.0.0"
  },
  {
    capabilities: {
      tools: {}
    }
  }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: TOOLS
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  if (!args) {
    return {
      content: [
        {
          type: "text",
          text: "Error: No arguments provided"
        }
      ]
    };
  }
  try {
    switch (name) {
      case "create_task": {
        const taskArgs = args;
        if (!claudeFrameId) {
          claudeFrameId = frameManager.createFrame({
            type: "task",
            name: "Claude AI Session",
            inputs: { source: "mcp", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
          });
        }
        const taskId = taskStore.createTask({
          title: taskArgs.title,
          description: taskArgs.description,
          priority: taskArgs.priority || "medium",
          frameId: claudeFrameId,
          tags: taskArgs.tags || ["claude-generated"]
        });
        if (taskArgs.autoExecute) {
          const session = await agentTaskManager.startTaskSession(
            taskId,
            claudeFrameId
          );
          _claudeSessionId = session.id;
          return {
            content: [
              {
                type: "text",
                text: `Task created: ${taskId}
Agent session started: ${session.id}
Ready for execution with ${session.maxTurns} turns available.`
              }
            ]
          };
        }
        return {
          content: [
            {
              type: "text",
              text: `Task created successfully: ${taskId}`
            }
          ]
        };
      }
      case "execute_task": {
        const execArgs = args;
        if (!claudeFrameId) {
          claudeFrameId = frameManager.createFrame({
            type: "task",
            name: "Claude Task Execution",
            inputs: { taskId: execArgs.taskId }
          });
        }
        const session = await agentTaskManager.startTaskSession(
          execArgs.taskId,
          claudeFrameId
        );
        if (execArgs.maxTurns) {
          session.maxTurns = execArgs.maxTurns;
        }
        _claudeSessionId = session.id;
        return {
          content: [
            {
              type: "text",
              text: `Started agent session: ${session.id}
Task: ${execArgs.taskId}
Max turns: ${session.maxTurns}
Use 'agent_turn' to execute actions.`
            }
          ]
        };
      }
      case "agent_turn": {
        const turnArgs = args;
        const result = await agentTaskManager.executeTurn(
          turnArgs.sessionId,
          turnArgs.action,
          turnArgs.context || {}
        );
        const verificationSummary = result.verificationResults.map((v) => `${v.passed ? "\u2713" : "\u2717"} ${v.verifierId}: ${v.message}`).join("\n");
        return {
          content: [
            {
              type: "text",
              text: `Turn executed:
Success: ${result.success}
Should Continue: ${result.shouldContinue}

Feedback:
${result.feedback}

Verifications:
${verificationSummary}`
            }
          ]
        };
      }
      case "task_status": {
        const statusArgs = args;
        if (statusArgs.taskId) {
          const task = taskStore.getTask(statusArgs.taskId);
          if (!task) {
            return {
              content: [
                { type: "text", text: `Task ${statusArgs.taskId} not found` }
              ]
            };
          }
          return {
            content: [
              {
                type: "text",
                text: `Task: ${task.title}
Status: ${task.status}
Priority: ${task.priority}
Created: ${new Date(task.created_at * 1e3).toLocaleString()}
Description: ${task.description || "N/A"}`
              }
            ]
          };
        }
        const activeTasks = taskStore.getActiveTasks();
        const taskList = activeTasks.map((t) => `- ${t.id}: ${t.title} (${t.status}, ${t.priority})`).join("\n");
        return {
          content: [
            {
              type: "text",
              text: `Active tasks (${activeTasks.length}):
${taskList || "No active tasks"}`
            }
          ]
        };
      }
      case "save_context": {
        const saveArgs = args;
        if (!claudeFrameId) {
          claudeFrameId = frameManager.createFrame({
            type: "task",
            name: "Claude Context",
            inputs: { source: "mcp" }
          });
        }
        const eventId = frameManager.addEvent(
          "observation",
          {
            type: saveArgs.type,
            content: saveArgs.content,
            importance: saveArgs.importance || 0.5,
            source: "claude-mcp",
            timestamp: (/* @__PURE__ */ new Date()).toISOString()
          },
          claudeFrameId
        );
        return {
          content: [
            {
              type: "text",
              text: `Context saved to frame ${claudeFrameId} as event ${eventId}`
            }
          ]
        };
      }
      case "load_context": {
        const loadArgs = args;
        const frames = frameManager.getActiveFramePath();
        const limit = loadArgs.limit || 10;
        const events = loadArgs.frameId ? frameManager.getFrameEvents(loadArgs.frameId, limit) : [];
        const contextText = frames.map(
          (frame) => `[Frame ${frame.type}] ${frame.name}: ${frame.digest_text || "No digest"}`
        ).concat(
          events.map(
            (event) => `[Event ${event.event_type}] ${new Date(event.ts).toLocaleString()}: ${JSON.stringify(
              event.payload
            ).substring(0, 100)}...`
          )
        ).join("\n\n");
        return {
          content: [
            {
              type: "text",
              text: `Query: ${loadArgs.query}
Found ${frames.length} frames and ${events.length} events:

${contextText || "No matching context found"}`
            }
          ]
        };
      }
      case "breakdown_task": {
        const breakdownArgs = args;
        const task = taskStore.getTask(breakdownArgs.taskId);
        if (!task) {
          return {
            content: [
              { type: "text", text: `Task ${breakdownArgs.taskId} not found` }
            ]
          };
        }
        const subtasks = [
          `1. Analyze: ${task.title} - Understand requirements (2 turns)`,
          `2. Design: ${task.title} - Create implementation plan (2 turns)`,
          `3. Implement: ${task.title} - Build core functionality (5 turns)`,
          `4. Test: ${task.title} - Validate and verify (3 turns)`,
          `5. Polish: ${task.title} - Documentation and cleanup (1 turn)`
        ].join("\n");
        return {
          content: [
            {
              type: "text",
              text: `Task breakdown for: ${task.title}

${subtasks}

Total estimated turns: 13`
            }
          ]
        };
      }
      case "list_active_sessions": {
        const sessions = agentTaskManager.getActiveSessions();
        const sessionList = sessions.map(
          (s) => `- ${s.sessionId}: Task ${s.taskId} (Turn ${s.turnCount}, ${s.status})`
        ).join("\n");
        return {
          content: [
            {
              type: "text",
              text: `Active sessions (${sessions.length}):
${sessionList || "No active sessions"}`
            }
          ]
        };
      }
      case "retry_session": {
        const retryArgs = args;
        const newSession = await agentTaskManager.retrySession(
          retryArgs.sessionId
        );
        if (!newSession) {
          return {
            content: [
              {
                type: "text",
                text: "Cannot retry session (max retries reached or session is still active)"
              }
            ]
          };
        }
        _claudeSessionId = newSession.id;
        return {
          content: [
            {
              type: "text",
              text: `Retry session started: ${newSession.id}
Task: ${newSession.taskId}
Incorporating learned context from previous attempts.`
            }
          ]
        };
      }
      case "session_feedback": {
        const feedbackArgs = args;
        const sessions = agentTaskManager.getActiveSessions();
        const session = sessions.find(
          (s) => s.sessionId === feedbackArgs.sessionId
        );
        if (!session) {
          return {
            content: [
              {
                type: "text",
                text: `Session ${feedbackArgs.sessionId} not found or not active`
              }
            ]
          };
        }
        return {
          content: [
            {
              type: "text",
              text: `Session ${feedbackArgs.sessionId}:
Turn: ${session.turnCount}
Status: ${session.status}

Ready for next action.`
            }
          ]
        };
      }
      default:
        throw new Error(`Unknown tool: ${name}`);
    }
  } catch (error) {
    logger.error(
      "MCP tool execution failed",
      error instanceof Error ? error : void 0
    );
    return {
      content: [
        {
          type: "text",
          text: `Error: ${error instanceof Error ? error.message : String(error)}`
        }
      ]
    };
  }
});
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  logger.info("StackMemory MCP Server started", {
    projectRoot: PROJECT_ROOT,
    tools: TOOLS.map((t) => t.name)
  });
}
process.on("SIGINT", async () => {
  logger.info("Shutting down StackMemory MCP Server");
  if (claudeFrameId) {
    try {
      frameManager.closeFrame(claudeFrameId, {
        summary: "Claude session ended",
        timestamp: (/* @__PURE__ */ new Date()).toISOString()
      });
    } catch (error) {
      logger.error(
        "Error closing frame",
        error instanceof Error ? error : void 0
      );
    }
  }
  db.close();
  process.exit(0);
});
main().catch((error) => {
  logger.error(
    "Failed to start MCP server",
    error instanceof Error ? error : void 0
  );
  process.exit(1);
});
//# sourceMappingURL=stackmemory-mcp-server.js.map
