@aipmanager/project-manager-mcp
Version:
MCP for the Project Manager Agent, providing full control over projects, phases, and tasks.
451 lines (450 loc) • 22.5 kB
JavaScript
#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const zod_1 = require("zod");
const axios_1 = __importDefault(require("axios"));
const API_BASE_URL = process.env.API_BASE_URL || "http://localhost:3001/api";
const apiClient = axios_1.default.create({
baseURL: API_BASE_URL,
headers: { "Content-Type": "application/json" },
});
// Helper to create a standardized error response
const createErrorResponse = (error, toolName) => {
let errorMessage = `An unexpected error occurred in ${toolName}.`;
let statusCode;
let details;
if (axios_1.default.isAxiosError(error)) {
const axiosError = error;
statusCode = axiosError.response?.status;
const apiError = axiosError.response?.data?.error || axiosError.message;
details = axiosError.response?.data;
errorMessage = `API Error in ${toolName} (Status ${statusCode}): ${apiError}`;
}
else if (error instanceof Error) {
errorMessage = `Error in ${toolName}: ${error.message}`;
}
return {
isError: true,
content: [{
type: "text",
text: JSON.stringify({
error: errorMessage,
statusCode,
details,
}, null, 2)
}]
};
};
const server = new mcp_js_1.McpServer({
name: "aipm-project-manager-agent",
version: "1.0.0",
description: "项目管理智能体,负责项目的全生命周期管理,包括项目、阶段、任务和智能体的协调。",
});
// --- Project Management Tools ---
server.registerTool("createProject", {
title: "创建新项目",
description: "创建一个新的项目,包含目标、约束等信息。",
inputSchema: {
name: zod_1.z.string().describe("项目名称,例如:'AI电商平台重构'"),
description: zod_1.z.string().describe("项目的详细描述,例如:'使用最新的微服务架构和AI推荐算法重构现有电商平台,提高性能和用户体验'"),
goals: zod_1.z.string().describe("项目的主要目标,例如:'提升用户转化率20%,优化推荐精准度,减少系统响应时间50%'"),
timeline: zod_1.z.string().optional().describe("项目的时间线或截止日期,例如:'2025-12-31'(可选)"),
budget: zod_1.z.number().optional().describe("项目的预算金额,例如:500000(可选)"),
},
}, async (input) => {
try {
const response = await apiClient.post("/projects", input);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "createProject");
}
});
server.registerTool("getAllProjects", {
title: "获取所有项目",
description: "列出系统中的所有项目。",
inputSchema: {},
}, async () => {
try {
const response = await apiClient.get("/projects");
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getAllProjects");
}
});
server.registerTool("getProjectDetails", {
title: "获取项目详情",
description: "通过ID获取单个项目的详细信息,包括其所有阶段和任务。",
inputSchema: {
projectId: zod_1.z.string().describe("项目ID,例如:'clxyztqf000008jsb4fsc6f8e'"),
},
}, async ({ projectId }) => {
try {
const response = await apiClient.get(`/projects/${projectId}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getProjectDetails");
}
});
server.registerTool("updateProject", {
title: "更新项目",
description: "更新现有项目的信息。",
inputSchema: {
id: zod_1.z.string().describe("要更新的项目ID,例如:'clxyztqf000008jsb4fsc6f8e'"),
name: zod_1.z.string().optional().describe("新的项目名称,例如:'AI电商平台重构2.0'(可选)"),
description: zod_1.z.string().optional().describe("新的项目描述,例如:'增加区块链支付功能和多语言支持'(可选)"),
goals: zod_1.z.string().optional().describe("新的项目目标,例如:'拓展国际市场,提升安全性'(可选)"),
},
}, async ({ id, ...data }) => {
try {
const response = await apiClient.put(`/projects/${id}`, data);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "updateProject");
}
});
server.registerTool("getProjectStats", {
title: "获取项目统计信息",
description: "获取特定项目的统计信息,如任务完成率、进度等。",
inputSchema: {
id: zod_1.z.string().describe("要获取统计信息的项目ID,例如:'clxyztqf000008jsb4fsc6f8e'"),
},
}, async ({ id }) => {
try {
const response = await apiClient.get(`/projects/${id}/stats`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getProjectStats");
}
});
// --- Phase Management Tools ---
server.registerTool("createPhase", {
title: "创建阶段",
description: "在指定项目中创建一个新的阶段。",
inputSchema: {
projectId: zod_1.z.string().describe("阶段所属的项目ID,例如:'clxyztqf000008jsb4fsc6f8e'"),
name: zod_1.z.string().describe("阶段名称,例如:'第一阶段:需求分析与设计'"),
description: zod_1.z.string().describe("阶段的详细描述,例如:'收集和分析用户需求,设计系统架构和数据模型,创建原型'"),
startDate: zod_1.z.string().datetime().describe("阶段开始日期,ISO 8601格式,例如:'2025-08-01T00:00:00.000Z'"),
endDate: zod_1.z.string().datetime().describe("阶段结束日期,ISO 8601格式,例如:'2025-09-01T00:00:00.000Z'"),
},
}, async ({ projectId, ...data }) => {
try {
const response = await apiClient.post(`/phases/project/${projectId}`, data);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "createPhase");
}
});
server.registerTool("getPhasesByProject", {
title: "获取项目阶段",
description: "获取指定项目的所有阶段列表。",
inputSchema: {
projectId: zod_1.z.string().describe("项目ID,例如:'clxyztqf000008jsb4fsc6f8e'"),
},
}, async ({ projectId }) => {
try {
const response = await apiClient.get(`/phases/project/${projectId}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getPhasesByProject");
}
});
server.registerTool("getPhaseDetails", {
title: "获取阶段详情",
description: "获取单个阶段的信息。",
inputSchema: {
id: zod_1.z.string().describe("阶段ID,例如:'clxyztqf000018jsb4fsc6f8e'"),
},
}, async ({ id }) => {
try {
const response = await apiClient.get(`/phases/${id}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getPhaseDetails");
}
});
server.registerTool("updatePhase", {
title: "更新阶段",
description: "更新一个阶段。",
inputSchema: {
id: zod_1.z.string().describe("要更新的阶段ID,例如:'clxyztqf000018jsb4fsc6f8e'"),
name: zod_1.z.string().optional().describe("新的阶段名称,例如:'第一阶段:需求分析与原型设计'(可选)"),
description: zod_1.z.string().optional().describe("新的阶段描述,例如:'增加用户访谈和竞品分析环节'(可选)"),
startDate: zod_1.z.string().datetime().optional().describe("新的开始日期,ISO 8601格式,例如:'2025-07-25T00:00:00.000Z'(可选)"),
endDate: zod_1.z.string().datetime().optional().describe("新的结束日期,ISO 8601格式,例如:'2025-09-10T00:00:00.000Z'(可选)"),
status: zod_1.z.enum(['PLANNED', 'IN_PROGRESS', 'COMPLETED', 'DELAYED']).optional().describe("阶段状态,例如:'IN_PROGRESS'(可选)"),
},
}, async ({ id, ...data }) => {
try {
const response = await apiClient.put(`/phases/${id}`, data);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "updatePhase");
}
});
// --- Task Management Tools ---
server.registerTool("createTask", {
title: "创建任务",
description: "在指定阶段中创建一个新任务。",
inputSchema: {
name: zod_1.z.string().min(1).max(255).describe("任务名称,例如:'实现用户登录功能'"),
description: zod_1.z.string().min(1).describe("任务详细描述,例如:'设计并实现基于JWT的用户登录和注册API接口,包括密码加密、token生成和验证'"),
type: zod_1.z.enum(['CODING', 'TESTING', 'DATA_ANALYSIS', 'RESEARCH', 'DOCUMENTATION', 'REVIEW', 'DEPLOYMENT']).describe("任务类型,例如:'CODING'"),
priority: zod_1.z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).default('MEDIUM').describe("优先级,例如:'HIGH'"),
estimatedHours: zod_1.z.number().min(1).max(1000).describe("预计工时,例如:8"),
phaseId: zod_1.z.string().cuid().describe("阶段ID,例如:'clxyztqf000018jsb4fsc6f8e'"),
assignedAgentId: zod_1.z.string().cuid().optional().describe("分配的智能体ID,例如:'clxyztqf000028jsb4fsc6f8e'(可选)"),
dependencies: zod_1.z.array(zod_1.z.string().cuid()).default([]).describe("依赖的任务ID列表,例如:['clxyztqf000038jsb4fsc6f8e', 'clxyztqf000048jsb4fsc6f8e'](可选)"),
},
}, async (data) => {
try {
const response = await apiClient.post(`/tasks`, data);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "createTask");
}
});
server.registerTool("getAllTasks", {
title: "获取所有任务",
description: "获取系统中的所有任务。",
inputSchema: {
projectId: zod_1.z.string().cuid().optional().describe("项目ID,例如:'clxyztqf000008jsb4fsc6f8e'(可选)"),
status: zod_1.z.enum(['PENDING', 'IN_PROGRESS', 'COMPLETED', 'BLOCKED', 'FAILED']).optional().describe("任务状态,例如:'IN_PROGRESS'(可选)"),
type: zod_1.z.enum(['CODING', 'TESTING', 'DATA_ANALYSIS', 'RESEARCH', 'DOCUMENTATION', 'REVIEW', 'DEPLOYMENT']).optional().describe("任务类型,例如:'CODING'(可选)"),
priority: zod_1.z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).optional().describe("优先级,例如:'HIGH'(可选)"),
assignedAgentId: zod_1.z.string().cuid().optional().describe("分配的智能体ID,例如:'clxyztqf000028jsb4fsc6f8e'(可选)"),
available: zod_1.z.string().optional().describe("是否只显示可领取的任务,例如:'true'(可选)"),
page: zod_1.z.number().default(1).describe("页码,例如:1"),
limit: zod_1.z.number().default(50).describe("每页数量,例如:20"),
},
}, async (query) => {
try {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (value !== undefined) {
params.append(key, String(value));
}
}
const response = await apiClient.get(`/tasks?${params.toString()}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getAllTasks");
}
});
server.registerTool("getTaskDetails", {
title: "获取任务详情",
description: "通过ID获取特定任务的完整详情。",
inputSchema: {
id: zod_1.z.string().describe("任务ID,例如:'clxyztqf000038jsb4fsc6f8e'"),
},
}, async ({ id }) => {
try {
const response = await apiClient.get(`/tasks/${id}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getTaskDetails");
}
});
server.registerTool("updateTask", {
title: "更新任务",
description: "更新一个现有任务的信息。",
inputSchema: {
id: zod_1.z.string().describe("要更新的任务ID,例如:'clxyztqf000038jsb4fsc6f8e'"),
name: zod_1.z.string().min(1).max(255).optional().describe("任务名称,例如:'优化用户登录功能'(可选)"),
description: zod_1.z.string().min(1).optional().describe("任务描述,例如:'添加双因素认证和登录限制功能'(可选)"),
type: zod_1.z.enum(['CODING', 'TESTING', 'DATA_ANALYSIS', 'RESEARCH', 'DOCUMENTATION', 'REVIEW', 'DEPLOYMENT']).optional().describe("任务类型,例如:'CODING'(可选)"),
status: zod_1.z.enum(['PENDING', 'IN_PROGRESS', 'COMPLETED', 'BLOCKED', 'FAILED']).optional().describe("任务状态,例如:'IN_PROGRESS'(可选)"),
priority: zod_1.z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).optional().describe("优先级,例如:'HIGH'(可选)"),
estimatedHours: zod_1.z.number().min(1).max(1000).optional().describe("预计工时,例如:12(可选)"),
actualHours: zod_1.z.number().min(0).max(1000).optional().describe("实际工时,例如:10(可选)"),
assignedAgentId: zod_1.z.string().cuid().optional().describe("分配的智能体ID,例如:'clxyztqf000028jsb4fsc6f8e'(可选)"),
startDate: zod_1.z.string().datetime().optional().describe("开始日期,ISO 8601格式,例如:'2025-08-15T09:00:00.000Z'(可选)"),
endDate: zod_1.z.string().datetime().optional().describe("结束日期,ISO 8601格式,例如:'2025-08-20T18:00:00.000Z'(可选)"),
completedAt: zod_1.z.string().datetime().optional().describe("完成日期,ISO 8601格式,例如:'2025-08-20T18:00:00.000Z'(可选)"),
},
}, async ({ id, ...data }) => {
try {
const response = await apiClient.put(`/tasks/${id}`, data);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "updateTask");
}
});
server.registerTool("completeTask", {
title: "完成任务",
description: "将任务标记为已完成。",
inputSchema: {
id: zod_1.z.string().describe("要标记为完成的任务ID,例如:'clxyztqf000038jsb4fsc6f8e'"),
result: zod_1.z.any().optional().describe("任务结果,例如:{ 'success': true, 'features': ['登录', '注册', '密码重置'] }(可选)"),
actualHours: zod_1.z.number().optional().describe("实际工时,例如:8.5(可选)"),
notes: zod_1.z.string().optional().describe("备注,例如:'完成了所有功能,并进行了单元测试'(可选)"),
},
}, async ({ id, ...data }) => {
try {
const response = await apiClient.post(`/tasks/${id}/complete`, data);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "completeTask");
}
});
server.registerTool("getAvailableTasks", {
title: "获取可用任务",
description: "获取状态为'PENDING',且未分配给任何智能体的任务列表。",
inputSchema: {
type: zod_1.z.enum(['CODING', 'TESTING', 'DATA_ANALYSIS', 'RESEARCH', 'DOCUMENTATION', 'REVIEW', 'DEPLOYMENT']).optional().describe("任务类型,例如:'CODING'(可选)"),
priority: zod_1.z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).optional().describe("优先级,例如:'HIGH'(可选)"),
projectId: zod_1.z.string().cuid().optional().describe("项目ID,例如:'clxyztqf000008jsb4fsc6f8e'(可选)"),
},
}, async (query) => {
try {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (value !== undefined) {
params.append(key, String(value));
}
}
const response = await apiClient.get(`/tasks/available?${params.toString()}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getAvailableTasks");
}
});
server.registerTool("claimTask", {
title: "领取任务",
description: "为智能体领取任务,并将其状态设置为进行中。",
inputSchema: {
id: zod_1.z.string().describe("要领取的任务ID,例如:'clxyztqf000038jsb4fsc6f8e'"),
agentId: zod_1.z.string().cuid().describe("领取任务的智能体ID,例如:'clxyztqf000028jsb4fsc6f8e'"),
},
}, async ({ id, agentId }) => {
try {
const response = await apiClient.post(`/tasks/${id}/claim`, { agentId });
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "claimTask");
}
});
// --- Agent and Monitoring Tools ---
server.registerTool("getAllAgents", {
title: "获取所有已注册的智能体",
description: "列出系统中所有已注册的智能体及其状态。",
inputSchema: {},
}, async () => {
try {
const response = await apiClient.get("/agents");
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getAllAgents");
}
});
server.registerTool("getAgentsByType", {
title: "按类型获取智能体",
description: "根据指定的类型筛选智能体。",
inputSchema: {
type: zod_1.z.string().describe("智能体类型,例如:'CODING'、'TESTING'、'DATA_ANALYSIS'等"),
},
}, async ({ type }) => {
try {
const response = await apiClient.get(`/agents/type/${type}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getAgentsByType");
}
});
server.registerTool("assignTaskToAgent", {
title: "分配任务给智能体",
description: "将一个指定的任务分配给一个指定的智能体。",
inputSchema: {
id: zod_1.z.string().describe("智能体ID,例如:'clxyztqf000028jsb4fsc6f8e'"),
taskId: zod_1.z.string().describe("任务ID,例如:'clxyztqf000038jsb4fsc6f8e'"),
},
}, async ({ id, taskId }) => {
try {
const response = await apiClient.post(`/agents/${id}/assign`, { taskId });
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "assignTaskToAgent");
}
});
server.registerTool("getAgentMetrics", {
title: "获取Agent性能指标",
description: "获取所有Agent的性能指标,如任务完成数、平均耗时等。",
inputSchema: {
timeRange: zod_1.z.enum(['DAY', 'WEEK', 'MONTH', 'ALL']).optional().describe("时间范围,例如:'WEEK'(可选,默认为'ALL')"),
agentId: zod_1.z.string().optional().describe("特定智能体ID,例如:'clxyztqf000028jsb4fsc6f8e'(可选,默认返回所有智能体)"),
},
}, async (query) => {
try {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (value !== undefined) {
params.append(key, String(value));
}
}
const response = await apiClient.get(`/monitoring/agents/metrics?${params.toString()}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getAgentMetrics");
}
});
server.registerTool("getProjectMetrics", {
title: "获取项目进度指标",
description: "获取所有项目的整体进度和性能指标。",
inputSchema: {
projectId: zod_1.z.string().optional().describe("特定项目ID,例如:'clxyztqf000008jsb4fsc6f8e'(可选,默认返回所有项目)"),
includePhases: zod_1.z.boolean().optional().describe("是否包含阶段级别的指标,例如:true(可选,默认为false)"),
includeTasks: zod_1.z.boolean().optional().describe("是否包含任务级别的指标,例如:false(可选,默认为false)"),
},
}, async (query) => {
try {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (value !== undefined) {
params.append(key, String(value));
}
}
const response = await apiClient.get(`/monitoring/projects/metrics?${params.toString()}`);
return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }] };
}
catch (error) {
return createErrorResponse(error, "getProjectMetrics");
}
});
async function main() {
try {
console.log("[ProjectManagerAgent] Starting MCP server...");
const transport = new stdio_js_1.StdioServerTransport();
await server.connect(transport);
console.log("[ProjectManagerAgent] MCP server connected and listening on stdio.");
}
catch (error) {
console.error("[ProjectManagerAgent] Failed to start MCP server:", error);
process.exit(1);
}
}
main();