UNPKG

plani-groupware-mcp

Version:

MCP server for groupware

191 lines (190 loc) 6.69 kB
#!/usr/bin/env node // MCP 서버 구현에 필요한 라이브러리 임포트 import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; // 입력값 검증을 위한 라이브러리 // 그룹웨어 API 기본 설정 // api url 작성 const API_BASE = "http://www.naver.com"; const USER_AGENT = "groupware-app/1.0"; // 환경 변수에서 설정 가져오기 const USERNAME = process.env.GROUPWARE_USERNAME; const PASSWORD = process.env.GROUPWARE_PASSWORD; if (!USERNAME || !PASSWORD) { console.error("Error: GROUPWARE_USERNAME and GROUPWARE_PASSWORD environment variables must be set"); process.exit(1); } // 토큰 저장소 let defaultToken = null; // 초기 로그인 수행 async function initializeAuth() { try { console.error("Attempting to connect to API server..."); const loginData = await makeAPIRequest("/auth/login", "POST", { username: USERNAME, password: PASSWORD, }); if (loginData && loginData.success) { defaultToken = loginData.token; console.error(`Successfully logged in as ${loginData.data.name}`); return true; } else { console.error("Failed to initialize authentication: Invalid credentials or server response"); return false; } } catch (error) { console.error("Error during authentication:", error); return false; } } // MCP 서버 인스턴스 생성 const server = new McpServer({ name: "groupware-mcp", version: "1.0.16", capabilities: { resources: {}, tools: {}, } }); // API 요청을 처리하는 헬퍼 함수 async function makeAPIRequest(url, method = "GET", body) { const headers = { "User-Agent": USER_AGENT, "Content-Type": "application/json", }; // 기본 토큰 사용 if (defaultToken) { headers["Authorization"] = `Bearer ${defaultToken}`; } try { console.error(`Making API request to ${API_BASE}${url}`); const response = await fetch(`${API_BASE}${url}`, { method, headers, body: body ? JSON.stringify(body) : undefined, }); if (!response.ok) { console.error(`API request failed with status ${response.status}`); const errorText = await response.text(); console.error(`Error response: ${errorText}`); throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.error(`API request successful: ${JSON.stringify(data)}`); return data; } catch (error) { console.error("Error making API request:", error); return null; } } // 회의실 목록 조회 도구 server.tool("get-rooms", "Get list of all meeting rooms", {}, async () => { const roomsData = await makeAPIRequest("/rooms", "GET"); if (!roomsData || !roomsData.success) { return { content: [ { type: "text", text: "Failed to retrieve rooms data. Please make sure you are logged in.", }, ], }; } const formattedRooms = roomsData.data.map((room) => `Room ID: ${room.room_id}\nName: ${room.name}\nLocation: ${room.location}\n---`); const roomsText = `Available Meeting Rooms:\n\n${formattedRooms.join("\n")}`; return { content: [ { type: "text", text: roomsText, }, ], }; }); // 회의실 예약 생성 도구 server.tool("create-reservation", "Create a new meeting room reservation", { room_id: z.number().describe("ID of the meeting room to reserve"), start_time: z.string().describe("Start time in ISO 8601 format (e.g. 2024-05-15T14:00:00Z)"), end_time: z.string().describe("End time in ISO 8601 format (e.g. 2024-05-15T15:00:00Z)"), purpose: z.string().describe("Purpose of the meeting"), }, async ({ room_id, start_time, end_time, purpose }) => { const reservationData = await makeAPIRequest("/reservations", "POST", { room_id, start_time, end_time, purpose, }); if (!reservationData || !reservationData.success) { return { content: [ { type: "text", text: "Failed to create reservation. Please make sure you are logged in.", }, ], }; } const reservationText = `Reservation created successfully:\n\n` + `Reservation ID: ${reservationData.data.reservation_id}\n` + `Room ID: ${reservationData.data.room_id}\n` + `Start Time: ${reservationData.data.start_time}\n` + `End Time: ${reservationData.data.end_time}\n` + `Purpose: ${reservationData.data.purpose}\n` + `Status: ${reservationData.data.status}`; return { content: [ { type: "text", text: reservationText, }, ], }; }); // 메인 함수: 서버 시작 및 실행 async function main() { try { // 초기 인증 수행 const authSuccess = await initializeAuth(); if (!authSuccess) { console.error("Authentication failed, exiting..."); process.exit(1); } const transport = new StdioServerTransport(); // 서버 연결 await server.connect(transport); console.error("Groupware MCP Server running on stdio"); // 프로세스 종료 시 정리 process.on('SIGINT', async () => { console.error('Shutting down server...'); await transport.close(); process.exit(0); }); process.on('SIGTERM', async () => { console.error('Shutting down server...'); await transport.close(); process.exit(0); }); // 연결 유지를 위한 이벤트 루프 process.stdin.resume(); process.stdin.setEncoding('utf8'); process.stdin.on('data', (data) => { console.error('Received data:', data.toString()); }); process.stdin.on('end', () => { console.error('stdin ended'); process.exit(0); }); } catch (error) { console.error('Error in main():', error); process.exit(1); } } // 에러 처리와 함께 메인 함수 실행 main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });