2026-02-06 00:03:56 +09:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
/**
|
2026-02-06 13:40:30 +09:00
|
|
|
b * Multi-Agent Orchestrator MCP Server v2.0
|
2026-02-06 00:03:56 +09:00
|
|
|
*
|
|
|
|
|
* Cursor Agent CLI를 활용한 멀티에이전트 시스템
|
|
|
|
|
* - PM (Cursor IDE): 전체 조율
|
|
|
|
|
* - Sub-agents (agent CLI): 전문가별 작업 수행
|
|
|
|
|
*
|
|
|
|
|
* 모든 AI 호출이 Cursor Team Plan으로 처리됨!
|
|
|
|
|
* API 키 불필요!
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
|
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
|
|
|
import {
|
|
|
|
|
CallToolRequestSchema,
|
|
|
|
|
ListToolsRequestSchema,
|
|
|
|
|
} from "@modelcontextprotocol/sdk/types.js";
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
import { spawn } from "child_process";
|
2026-02-06 00:03:56 +09:00
|
|
|
import { platform } from "os";
|
|
|
|
|
import { AGENT_CONFIGS } from "./agents/prompts.js";
|
|
|
|
|
import { AgentType, ParallelResult } from "./agents/types.js";
|
|
|
|
|
import { logger } from "./utils/logger.js";
|
|
|
|
|
|
|
|
|
|
// OS 감지
|
|
|
|
|
const isWindows = platform() === "win32";
|
|
|
|
|
logger.info(`Platform detected: ${platform()} (isWindows: ${isWindows})`);
|
|
|
|
|
|
|
|
|
|
// MCP 서버 생성
|
|
|
|
|
const server = new Server(
|
|
|
|
|
{
|
|
|
|
|
name: "agent-orchestrator",
|
|
|
|
|
version: "2.0.0",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
capabilities: {
|
|
|
|
|
tools: {},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
2026-02-09 13:22:48 +09:00
|
|
|
* 유틸: ms만큼 대기
|
2026-02-06 00:03:56 +09:00
|
|
|
*/
|
2026-02-09 13:22:48 +09:00
|
|
|
function sleep(ms: number): Promise<void> {
|
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Cursor Agent CLI 단일 호출 (내부용)
|
|
|
|
|
* spawn + stdin 직접 전달
|
|
|
|
|
*/
|
|
|
|
|
function spawnAgentOnce(
|
2026-02-06 00:03:56 +09:00
|
|
|
agentType: AgentType,
|
2026-02-09 13:22:48 +09:00
|
|
|
fullPrompt: string,
|
|
|
|
|
model: string
|
2026-02-06 00:03:56 +09:00
|
|
|
): Promise<string> {
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
const agentPath = isWindows ? 'agent' : `${process.env.HOME}/.local/bin/agent`;
|
|
|
|
|
|
|
|
|
|
return new Promise<string>((resolve, reject) => {
|
|
|
|
|
let stdout = '';
|
|
|
|
|
let stderr = '';
|
|
|
|
|
let settled = false;
|
|
|
|
|
|
|
|
|
|
const child = spawn(agentPath, ['--model', model, '--print'], {
|
2026-02-06 00:03:56 +09:00
|
|
|
cwd: process.cwd(),
|
2026-02-06 13:33:19 +09:00
|
|
|
env: {
|
|
|
|
|
...process.env,
|
|
|
|
|
PATH: `${process.env.HOME}/.local/bin:${process.env.PATH}`,
|
|
|
|
|
},
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
child.stdout.on('data', (data: Buffer) => {
|
|
|
|
|
stdout += data.toString();
|
2026-02-06 00:03:56 +09:00
|
|
|
});
|
|
|
|
|
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
child.stderr.on('data', (data: Buffer) => {
|
|
|
|
|
stderr += data.toString();
|
|
|
|
|
});
|
2026-02-06 00:03:56 +09:00
|
|
|
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
child.on('error', (err: Error) => {
|
|
|
|
|
if (!settled) {
|
|
|
|
|
settled = true;
|
|
|
|
|
reject(err);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
child.on('close', (code: number | null) => {
|
|
|
|
|
if (settled) return;
|
|
|
|
|
settled = true;
|
|
|
|
|
|
|
|
|
|
if (stderr) {
|
|
|
|
|
const significantStderr = stderr
|
|
|
|
|
.split('\n')
|
|
|
|
|
.filter((line: string) => line && !line.includes('warning') && !line.includes('info') && !line.includes('debug'))
|
|
|
|
|
.join('\n');
|
|
|
|
|
if (significantStderr) {
|
|
|
|
|
logger.warn(`${agentType} agent stderr`, { stderr: significantStderr.substring(0, 500) });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (code === 0 || stdout.trim().length > 0) {
|
|
|
|
|
resolve(stdout.trim());
|
|
|
|
|
} else {
|
2026-02-09 13:22:48 +09:00
|
|
|
reject(new Error(
|
|
|
|
|
`Agent exited with code ${code}. stderr: ${stderr.substring(0, 1000)}`
|
|
|
|
|
));
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 타임아웃 (5분)
|
|
|
|
|
const timeout = setTimeout(() => {
|
|
|
|
|
if (!settled) {
|
|
|
|
|
settled = true;
|
|
|
|
|
child.kill('SIGTERM');
|
|
|
|
|
reject(new Error(`${agentType} agent timed out after 5 minutes`));
|
|
|
|
|
}
|
|
|
|
|
}, 300000);
|
|
|
|
|
|
|
|
|
|
child.on('close', () => clearTimeout(timeout));
|
|
|
|
|
|
2026-02-09 13:22:48 +09:00
|
|
|
// stdin으로 프롬프트 직접 전달
|
docs: Add detailed backend, database, and frontend architecture analysis documents
- Created a comprehensive analysis document for the backend architecture, detailing the directory structure, API routes, authentication workflows, and more.
- Added a database architecture analysis report outlining the database structure, multi-tenancy architecture, and key system tables.
- Introduced a frontend architecture analysis document that covers the directory structure, component systems, and Next.js App Router structure.
These documents aim to enhance the understanding of the WACE ERP system's architecture and facilitate better workflow documentation.
2026-02-06 16:00:43 +09:00
|
|
|
child.stdin.write(fullPrompt);
|
|
|
|
|
child.stdin.end();
|
|
|
|
|
});
|
2026-02-06 00:03:56 +09:00
|
|
|
}
|
|
|
|
|
|
2026-02-09 13:22:48 +09:00
|
|
|
/**
|
|
|
|
|
* Cursor Agent CLI를 통해 에이전트 호출 (재시도 포함)
|
|
|
|
|
*
|
|
|
|
|
* - 최대 2회 재시도 (총 3회 시도)
|
|
|
|
|
* - 재시도 간 2초 대기 (Cursor CLI 동시 실행 제한 대응)
|
|
|
|
|
*/
|
|
|
|
|
async function callAgentCLI(
|
|
|
|
|
agentType: AgentType,
|
|
|
|
|
task: string,
|
|
|
|
|
context?: string
|
|
|
|
|
): Promise<string> {
|
|
|
|
|
const config = AGENT_CONFIGS[agentType];
|
|
|
|
|
const model = agentType === 'pm' ? 'opus-4.5' : 'sonnet-4.5';
|
|
|
|
|
const maxRetries = 2;
|
|
|
|
|
|
|
|
|
|
logger.info(`Calling ${agentType} agent via CLI (spawn+retry)`, {
|
|
|
|
|
model,
|
|
|
|
|
task: task.substring(0, 100),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const userMessage = context
|
|
|
|
|
? `${task}\n\n배경 정보:\n${context}`
|
|
|
|
|
: task;
|
|
|
|
|
const fullPrompt = `${config.systemPrompt}\n\n---\n\n${userMessage}`;
|
|
|
|
|
|
|
|
|
|
let lastError: Error | null = null;
|
|
|
|
|
|
|
|
|
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
|
|
|
try {
|
|
|
|
|
if (attempt > 0) {
|
|
|
|
|
const delay = attempt * 2000; // 2초, 4초
|
|
|
|
|
logger.info(`${agentType} agent retry ${attempt}/${maxRetries} (waiting ${delay}ms)`);
|
|
|
|
|
await sleep(delay);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result = await spawnAgentOnce(agentType, fullPrompt, model);
|
|
|
|
|
logger.info(`${agentType} agent completed (attempt ${attempt + 1})`);
|
|
|
|
|
return result;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
|
|
|
logger.warn(`${agentType} agent attempt ${attempt + 1} failed`, {
|
|
|
|
|
error: lastError.message.substring(0, 200),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 모든 재시도 실패
|
|
|
|
|
logger.error(`${agentType} agent failed after ${maxRetries + 1} attempts`);
|
|
|
|
|
throw lastError!;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-06 00:03:56 +09:00
|
|
|
/**
|
|
|
|
|
* 도구 목록 핸들러
|
|
|
|
|
*/
|
|
|
|
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
|
|
return {
|
|
|
|
|
tools: [
|
|
|
|
|
{
|
|
|
|
|
name: "ask_backend_agent",
|
|
|
|
|
description:
|
|
|
|
|
"백엔드 전문가에게 질문하거나 작업을 요청합니다. " +
|
|
|
|
|
"API 설계, 서비스 로직, 라우팅, 미들웨어 관련 작업에 사용하세요. " +
|
2026-02-06 13:40:30 +09:00
|
|
|
"담당 폴더: backend-node/src/ (Cursor Agent CLI, sonnet-4.5 모델)" +
|
|
|
|
|
"주의: 단순 파일 읽기/수정은 PM이 직접 처리하세요. 깊은 분석이 필요할 때만 호출!",
|
2026-02-06 00:03:56 +09:00
|
|
|
inputSchema: {
|
|
|
|
|
type: "object" as const,
|
|
|
|
|
properties: {
|
|
|
|
|
task: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "백엔드 에이전트에게 요청할 작업 내용",
|
|
|
|
|
},
|
|
|
|
|
context: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "작업에 필요한 배경 정보 (선택사항)",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
required: ["task"],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ask_db_agent",
|
|
|
|
|
description:
|
|
|
|
|
"DB 전문가에게 질문하거나 작업을 요청합니다. " +
|
|
|
|
|
"스키마 설계, SQL 쿼리, MyBatis 매퍼, 마이그레이션 관련 작업에 사용하세요. " +
|
2026-02-06 13:40:30 +09:00
|
|
|
"담당 폴더: src/com/pms/mapper/, db/ (Cursor Agent CLI, sonnet-4.5 모델)" +
|
|
|
|
|
"주의: 단순 스키마 확인은 PM이 직접 처리하세요. 복잡한 쿼리 설계/최적화 시에만 호출!",
|
2026-02-06 00:03:56 +09:00
|
|
|
inputSchema: {
|
|
|
|
|
type: "object" as const,
|
|
|
|
|
properties: {
|
|
|
|
|
task: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "DB 에이전트에게 요청할 작업 내용",
|
|
|
|
|
},
|
|
|
|
|
context: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "작업에 필요한 배경 정보 (선택사항)",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
required: ["task"],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ask_frontend_agent",
|
|
|
|
|
description:
|
|
|
|
|
"프론트엔드 전문가에게 질문하거나 작업을 요청합니다. " +
|
|
|
|
|
"React 컴포넌트, 페이지, 스타일링, 상태관리 관련 작업에 사용하세요. " +
|
2026-02-06 13:40:30 +09:00
|
|
|
"담당 폴더: frontend/ (Cursor Agent CLI, sonnet-4.5 모델)" +
|
|
|
|
|
"주의: 단순 컴포넌트 읽기/수정은 PM이 직접 처리하세요. 구조 분석이 필요할 때만 호출!",
|
2026-02-06 00:03:56 +09:00
|
|
|
inputSchema: {
|
|
|
|
|
type: "object" as const,
|
|
|
|
|
properties: {
|
|
|
|
|
task: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "프론트엔드 에이전트에게 요청할 작업 내용",
|
|
|
|
|
},
|
|
|
|
|
context: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "작업에 필요한 배경 정보 (선택사항)",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
required: ["task"],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "parallel_ask",
|
|
|
|
|
description:
|
|
|
|
|
"여러 전문가에게 동시에 질문합니다 (진짜 병렬 실행!). " +
|
2026-02-06 13:40:30 +09:00
|
|
|
"3개 영역(FE+BE+DB) 크로스도메인 분석이 필요할 때만 사용하세요. " +
|
|
|
|
|
"주의: 호출 시간이 오래 걸림! 단순 작업은 PM이 직접 처리하는 게 훨씬 빠릅니다. " +
|
|
|
|
|
"적합한 경우: 전체 아키텍처 파악, 대규모 리팩토링 계획, 크로스도메인 영향 분석",
|
2026-02-06 00:03:56 +09:00
|
|
|
inputSchema: {
|
|
|
|
|
type: "object" as const,
|
|
|
|
|
properties: {
|
|
|
|
|
requests: {
|
|
|
|
|
type: "array",
|
|
|
|
|
description: "각 에이전트에게 보낼 요청 목록",
|
|
|
|
|
items: {
|
|
|
|
|
type: "object",
|
|
|
|
|
properties: {
|
|
|
|
|
agent: {
|
|
|
|
|
type: "string",
|
|
|
|
|
enum: ["backend", "db", "frontend"],
|
|
|
|
|
description: "요청할 에이전트 타입",
|
|
|
|
|
},
|
|
|
|
|
task: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "해당 에이전트에게 요청할 작업",
|
|
|
|
|
},
|
|
|
|
|
context: {
|
|
|
|
|
type: "string",
|
|
|
|
|
description: "배경 정보 (선택사항)",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
required: ["agent", "task"],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
required: ["requests"],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "get_agent_info",
|
|
|
|
|
description:
|
|
|
|
|
"에이전트 시스템의 현재 상태와 사용 가능한 에이전트 정보를 확인합니다.",
|
|
|
|
|
inputSchema: {
|
|
|
|
|
type: "object" as const,
|
|
|
|
|
properties: {},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 도구 호출 핸들러
|
|
|
|
|
*/
|
|
|
|
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
|
|
const { name, arguments: args } = request.params;
|
|
|
|
|
|
|
|
|
|
logger.info(`Tool called: ${name}`);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
switch (name) {
|
|
|
|
|
case "ask_backend_agent": {
|
|
|
|
|
const { task, context } = args as { task: string; context?: string };
|
|
|
|
|
const result = await callAgentCLI("backend", task, context);
|
|
|
|
|
return {
|
|
|
|
|
content: [{ type: "text" as const, text: result }],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "ask_db_agent": {
|
|
|
|
|
const { task, context } = args as { task: string; context?: string };
|
|
|
|
|
const result = await callAgentCLI("db", task, context);
|
|
|
|
|
return {
|
|
|
|
|
content: [{ type: "text" as const, text: result }],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "ask_frontend_agent": {
|
|
|
|
|
const { task, context } = args as { task: string; context?: string };
|
|
|
|
|
const result = await callAgentCLI("frontend", task, context);
|
|
|
|
|
return {
|
|
|
|
|
content: [{ type: "text" as const, text: result }],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "parallel_ask": {
|
|
|
|
|
const { requests } = args as {
|
|
|
|
|
requests: Array<{
|
|
|
|
|
agent: "backend" | "db" | "frontend";
|
|
|
|
|
task: string;
|
|
|
|
|
context?: string;
|
|
|
|
|
}>;
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-09 13:22:48 +09:00
|
|
|
logger.info(`Parallel ask to ${requests.length} agents (STAGGERED PARALLEL)`);
|
|
|
|
|
|
|
|
|
|
// 시차 병렬 실행: 각 에이전트를 500ms 간격으로 시작
|
|
|
|
|
// Cursor Agent CLI 동시 실행 제한 대응
|
|
|
|
|
const STAGGER_DELAY = 500; // ms
|
2026-02-06 00:03:56 +09:00
|
|
|
|
|
|
|
|
const results: ParallelResult[] = await Promise.all(
|
2026-02-09 13:22:48 +09:00
|
|
|
requests.map(async (req, index) => {
|
2026-02-06 00:03:56 +09:00
|
|
|
try {
|
2026-02-09 13:22:48 +09:00
|
|
|
// 시차 적용 (첫 번째는 즉시, 이후 500ms 간격)
|
|
|
|
|
if (index > 0) {
|
|
|
|
|
await sleep(index * STAGGER_DELAY);
|
|
|
|
|
}
|
2026-02-06 00:03:56 +09:00
|
|
|
const result = await callAgentCLI(req.agent, req.task, req.context);
|
|
|
|
|
return { agent: req.agent, result };
|
|
|
|
|
} catch (error) {
|
|
|
|
|
return {
|
|
|
|
|
agent: req.agent,
|
|
|
|
|
result: "",
|
|
|
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 결과를 보기 좋게 포맷팅
|
|
|
|
|
const formattedResults = results.map((r) => {
|
|
|
|
|
const header = `\n${"=".repeat(60)}\n## ${r.agent.toUpperCase()} Agent 응답\n${"=".repeat(60)}\n`;
|
|
|
|
|
if (r.error) {
|
|
|
|
|
return `${header}❌ 에러: ${r.error}`;
|
|
|
|
|
}
|
|
|
|
|
return `${header}${r.result}`;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
type: "text" as const,
|
|
|
|
|
text: formattedResults.join("\n"),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case "get_agent_info": {
|
|
|
|
|
const info = {
|
|
|
|
|
system: "Multi-Agent Orchestrator v2.0",
|
|
|
|
|
version: "2.0.0",
|
|
|
|
|
backend: "Cursor Agent CLI (Team Plan)",
|
2026-02-06 13:33:19 +09:00
|
|
|
cliPath: `${process.env.HOME}/.local/bin/agent`,
|
|
|
|
|
apiKey: "NOT REQUIRED! Using Cursor Team Plan credits",
|
2026-02-06 00:03:56 +09:00
|
|
|
agents: {
|
|
|
|
|
pm: {
|
|
|
|
|
role: "Project Manager",
|
|
|
|
|
model: "opus-4.5 (Cursor IDE에서 직접)",
|
|
|
|
|
description: "전체 조율, 사용자 의도 파악, 작업 분배",
|
|
|
|
|
},
|
|
|
|
|
backend: {
|
|
|
|
|
role: "Backend Specialist",
|
2026-02-06 13:33:19 +09:00
|
|
|
model: "sonnet-4.5 (via Agent CLI)",
|
2026-02-06 00:03:56 +09:00
|
|
|
description: "API, 서비스 로직, 라우팅 담당",
|
|
|
|
|
folder: "backend-node/src/",
|
|
|
|
|
},
|
|
|
|
|
db: {
|
|
|
|
|
role: "Database Specialist",
|
2026-02-06 13:33:19 +09:00
|
|
|
model: "sonnet-4.5 (via Agent CLI)",
|
2026-02-06 00:03:56 +09:00
|
|
|
description: "스키마, 쿼리, 마이그레이션 담당",
|
|
|
|
|
folder: "src/com/pms/mapper/, db/",
|
|
|
|
|
},
|
|
|
|
|
frontend: {
|
|
|
|
|
role: "Frontend Specialist",
|
2026-02-06 13:33:19 +09:00
|
|
|
model: "sonnet-4.5 (via Agent CLI)",
|
2026-02-06 00:03:56 +09:00
|
|
|
description: "컴포넌트, 페이지, 스타일링 담당",
|
|
|
|
|
folder: "frontend/",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
features: {
|
|
|
|
|
parallel_execution: true,
|
|
|
|
|
cursor_team_plan: true,
|
2026-02-06 13:33:19 +09:00
|
|
|
cursor_agent_cli: true,
|
2026-02-06 00:03:56 +09:00
|
|
|
separate_api_key: false,
|
2026-02-06 13:33:19 +09:00
|
|
|
cross_platform: true,
|
2026-02-06 00:03:56 +09:00
|
|
|
},
|
|
|
|
|
usage: {
|
|
|
|
|
single_agent: "ask_backend_agent, ask_db_agent, ask_frontend_agent",
|
|
|
|
|
parallel: "parallel_ask로 여러 에이전트 동시 호출",
|
|
|
|
|
workflow: "1. parallel_ask로 정보 수집 → 2. 개별 에이전트로 작업 분배",
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
type: "text" as const,
|
|
|
|
|
text: JSON.stringify(info, null, 2),
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
throw new Error(`Unknown tool: ${name}`);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error(`Tool error: ${name}`, error);
|
|
|
|
|
return {
|
|
|
|
|
content: [
|
|
|
|
|
{
|
|
|
|
|
type: "text" as const,
|
|
|
|
|
text: `❌ 에러 발생: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
isError: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 서버 시작
|
|
|
|
|
*/
|
|
|
|
|
async function main() {
|
|
|
|
|
logger.info("Starting Multi-Agent Orchestrator MCP Server v2.0...");
|
2026-02-06 13:33:19 +09:00
|
|
|
logger.info(`Backend: Cursor Agent CLI (${process.env.HOME}/.local/bin/agent)`);
|
|
|
|
|
logger.info("Credits: Cursor Team Plan - No API Key Required!");
|
2026-02-06 00:03:56 +09:00
|
|
|
|
|
|
|
|
const transport = new StdioServerTransport();
|
|
|
|
|
await server.connect(transport);
|
|
|
|
|
|
|
|
|
|
logger.info("MCP Server connected and ready!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main().catch((error) => {
|
|
|
|
|
logger.error("Server failed to start", error);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|