UNPKG

@notbnull/mcp-cursor-taskmaster

Version:

A project-scoped MCP server requiring explicit --project-dir configuration for task management, memory retrieval, and agentic workflows

154 lines 5.62 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ApprovalUIServer = void 0; exports.getApprovalUIServer = getApprovalUIServer; const express_1 = __importDefault(require("express")); const socket_io_1 = require("socket.io"); const http_1 = require("http"); const path_1 = __importDefault(require("path")); const timers_1 = require("timers"); class ApprovalUIServer { app; server; io; port; pendingApprovals = new Map(); isRunning = false; constructor(port = 3456) { this.port = port; this.app = (0, express_1.default)(); this.server = (0, http_1.createServer)(this.app); this.io = new socket_io_1.Server(this.server, { cors: { origin: "*", methods: ["GET", "POST"], }, }); this.setupRoutes(); this.setupSocketHandlers(); } setupRoutes() { this.app.use(express_1.default.static(path_1.default.join(__dirname, "../public"))); this.app.use(express_1.default.json()); // Serve the approval UI this.app.get("/", (req, res) => { res.sendFile(path_1.default.join(__dirname, "../public/approval.html")); }); // API endpoint to get pending approvals this.app.get("/api/pending", (req, res) => { const pending = Array.from(this.pendingApprovals.entries()).map(([id, data]) => ({ id, request: data.request, })); res.json(pending); }); } setupSocketHandlers() { this.io.on("connection", (socket) => { console.error("Approval UI: Client connected"); // Send all pending approvals to newly connected client const pending = Array.from(this.pendingApprovals.entries()).map(([id, data]) => ({ id, request: data.request, })); socket.emit("pending-approvals", pending); // Handle approval response socket.on("approval-response", (response) => { const pending = this.pendingApprovals.get(response.taskId); if (pending) { pending.resolve(response); this.pendingApprovals.delete(response.taskId); // Notify all clients that this approval is resolved this.io.emit("approval-resolved", response.taskId); } }); socket.on("disconnect", () => { console.error("Approval UI: Client disconnected"); }); }); } async start() { if (this.isRunning) return; return new Promise((resolve, reject) => { this.server .listen(this.port, () => { this.isRunning = true; console.error(`Approval UI server running at http://localhost:${this.port}`); resolve(); }) .on("error", (err) => { if (err.code === "EADDRINUSE") { console.error(`Port ${this.port} is already in use, assuming UI is already running`); this.isRunning = true; resolve(); } else { reject(err); } }); }); } async stop() { if (!this.isRunning) return; return new Promise((resolve) => { this.server.close(() => { this.isRunning = false; resolve(); }); }); } async requestApproval(request) { // Ensure server is running await this.start(); return new Promise((resolve, reject) => { // Store the pending approval this.pendingApprovals.set(request.taskId, { request, resolve, reject, }); // Notify all connected clients this.io.emit("new-approval", { id: request.taskId, request, }); // Open the UI in browser if not already open if (this.pendingApprovals.size === 1) { import("open") .then(({ default: open }) => { open(`http://localhost:${this.port}`).catch(() => { console.error("Failed to open browser automatically. Please open http://localhost:" + this.port); }); }) .catch(() => { console.error("Failed to load open module. Please open http://localhost:" + this.port + " manually"); }); } // Set a timeout for the approval (5 minutes) (0, timers_1.setTimeout)(() => { if (this.pendingApprovals.has(request.taskId)) { this.pendingApprovals.delete(request.taskId); reject(new Error("Approval timeout")); } }, 5 * 60 * 1000); }); } } exports.ApprovalUIServer = ApprovalUIServer; // Singleton instance let approvalUIServer = null; function getApprovalUIServer() { if (!approvalUIServer) { approvalUIServer = new ApprovalUIServer(); } return approvalUIServer; } //# sourceMappingURL=approval-ui.js.map