Skip to main content
Glama
calendar-tools.ts9.15 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import axios, { AxiosRequestConfig } from "axios"; import { z } from "zod"; import { SessionManager } from "./auth-tools.js"; // Helper function for calendar API requests async function makeCalendarRequest<T>( method: string, path: string, body: any = null, params: any = null, apiKey?: string, sessionId?: string ): Promise<T> { let hostUrl = process.env.CALENDAR_API_HOST_URL || "http://localhost:8000"; if (!hostUrl.endsWith("/")) hostUrl += "/"; // Add platform-calendar prefix if not present if (!hostUrl.includes("/platform-calendar")) { hostUrl = hostUrl.replace(/\/$/, "") + "/platform-calendar/"; } const url = `${hostUrl}${path}`; // Получаем API ключ из параметров, сессии или переменной окружения const sessionManager = SessionManager.getInstance(); const finalApiKey = apiKey || sessionManager.getApiKey(sessionId) || sessionManager.getCurrentApiKey() || process.env.CALENDAR_API_KEY || ""; const headers: Record<string, string> = { authorization: finalApiKey, Accept: "application/json", }; if (method.toUpperCase() !== "GET") { headers["Content-Type"] = "application/json"; } console.log("[DEBUG] Calendar API Request", { method, url, headers: { ...headers, authorization: "***" }, body, params, hasStoredApiKey: !!sessionManager.getCurrentApiKey(), sessionId: sessionId || "current", }); try { const config: AxiosRequestConfig = { url, method, headers, params, }; if (method.toUpperCase() !== "GET" && body !== null) { config.data = body; } const response = await axios(config); return response.data; } catch (error) { if (axios.isAxiosError(error)) { if (error.response) { console.error("[DEBUG] Calendar API Error Response", { status: error.response.status, data: error.response.data, }); } throw new Error(`Calendar API request failed: ${error.message}`); } throw error; } } // Schema definitions const CalendarGetMySchema = z.object({ start: z.string().optional().describe("Start date in YYYY-MM-DD format"), end: z.string().optional().describe("End date in YYYY-MM-DD format"), _: z.string().optional().describe("Additional parameter (min 3 chars)"), api_key: z.string().optional().describe("API key for authentication (overrides stored session)"), session_id: z.string().optional().describe("Session ID to use specific session (optional)"), }); const CalendarGetByUserSchema = z.object({ user_id: z.number().describe("User ID to get calendar for"), start: z.string().optional().describe("Start date/datetime"), end: z.string().optional().describe("End date/datetime"), api_key: z.string().optional().describe("API key for authentication (overrides stored session)"), session_id: z.string().optional().describe("Session ID to use specific session (optional)"), }); const MeetingCreateSchema = z.object({ title: z.string().describe("Meeting title"), description: z.string().optional().describe("Meeting description"), place: z.string().optional().describe("Meeting place"), start: z.string().describe("Start date-time in ISO format"), end: z.string().describe("End date-time in ISO format"), invited: z.array(z.number()).optional().describe("List of invited user IDs"), notify: z.number().optional().describe("Notification time in minutes"), api_key: z.string().optional().describe("API key for authentication (overrides stored session)"), session_id: z.string().optional().describe("Session ID to use specific session (optional)"), }); const MeetingGetSchema = z.object({ meeting_id: z.string().describe("Meeting ID to retrieve"), api_key: z.string().optional().describe("API key for authentication (overrides stored session)"), session_id: z.string().optional().describe("Session ID to use specific session (optional)"), }); const MeetingAvailabilitySchema = z.object({ start: z.string().describe("Start date-time in ISO format"), end: z.string().describe("End date-time in ISO format"), user_ids: z.array(z.number()).describe("List of user IDs to check availability"), meeting_id: z.string().optional().describe("Exclude specific meeting ID"), api_key: z.string().optional().describe("API key for authentication (overrides stored session)"), session_id: z.string().optional().describe("Session ID to use specific session (optional)"), }); const MeetingRequiringAttentionSchema = z.object({ api_key: z.string().optional().describe("API key for authentication (overrides stored session)"), session_id: z.string().optional().describe("Session ID to use specific session (optional)"), }); export const registerCalendarTools = (server: McpServer) => { // Get current user's calendar server.tool( "calendar_get_my", CalendarGetMySchema.shape, { title: "Get current user's calendar with events for specified date range", }, async (args) => { const validatedArgs = CalendarGetMySchema.parse(args); const { api_key, session_id, ...requestParams } = validatedArgs; const params = Object.fromEntries(Object.entries(requestParams).filter(([, value]) => value !== undefined)); const result = await makeCalendarRequest("GET", "api/v1/calendar/my", null, params, api_key, session_id); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } ); // Get calendar by user ID server.tool( "calendar_get_by_user", CalendarGetByUserSchema.shape, { title: "Get calendar for a specific user by user ID", }, async (args) => { const validatedArgs = CalendarGetByUserSchema.parse(args); const { user_id, api_key, session_id, ...params } = validatedArgs; const filteredParams = Object.fromEntries(Object.entries(params).filter(([, value]) => value !== undefined)); const result = await makeCalendarRequest( "GET", `api/v1/calendar/${user_id}`, null, filteredParams, api_key, session_id ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } ); // Create meeting server.tool( "meeting_create", MeetingCreateSchema.shape, { title: "Create a new meeting", }, async (args) => { const validatedArgs = MeetingCreateSchema.parse(args); const { api_key, session_id, ...requestBody } = validatedArgs; const result = await makeCalendarRequest("POST", "api/v1/meeting", requestBody, null, api_key, session_id); return { content: [ { type: "text", text: `Meeting created successfully: ${JSON.stringify(result, null, 2)}`, }, ], }; } ); // Get meeting by ID server.tool( "meeting_get", MeetingGetSchema.shape, { title: "Get meeting details by ID", }, async (args) => { const validatedArgs = MeetingGetSchema.parse(args); const { api_key, session_id, meeting_id } = validatedArgs; const result = await makeCalendarRequest("GET", `api/v1/meeting/${meeting_id}`, null, null, api_key, session_id); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } ); // Check user availability server.tool( "meeting_get_user_availability", MeetingAvailabilitySchema.shape, { title: "Check user availability (busy times) for a time period", }, async (args) => { const validatedArgs = MeetingAvailabilitySchema.parse(args); const { user_ids, meeting_id, api_key, session_id, ...dateParams } = validatedArgs; const params = { ...dateParams, user: user_ids, ...(meeting_id && { meetId: meeting_id }), }; const result = await makeCalendarRequest("GET", "api/v1/meeting", null, params, api_key, session_id); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } ); // Get meetings requiring attention server.tool( "meeting_get_requiring_attention", MeetingRequiringAttentionSchema.shape, { title: "Get meetings that require attention from the current user", }, async (args) => { const validatedArgs = MeetingRequiringAttentionSchema.parse(args); const { api_key, session_id } = validatedArgs; const result = await makeCalendarRequest( "GET", "api/v1/meeting/requiring_attention", null, null, api_key, session_id ); return { content: [ { type: "text", text: JSON.stringify(result, null, 2), }, ], }; } ); };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/inite-ai/radius-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server