Monday.com MCP Server

import { z } from "zod"; // Monday SDK Instance Type export interface MondaySDKInstance { setToken(token: string): void; api( query: string, options?: { variables?: Record<string, any> }, ): Promise<any>; } // Base schemas for common column types export const PersonColumnSchema = z.object({ personsAndTeams: z.array( z.object({ id: z.number(), kind: z.enum(["person", "team"]), }), ), }); export const StatusColumnSchema = z.object({ label: z.string(), index: z.number().optional(), }); export const DateColumnSchema = z.object({ date: z.string(), time: z.string().optional(), timezone: z.string().optional(), }); // Enhanced column type schemas export const TextColumnSchema = z.object({ text: z.string(), }); export const NumberColumnSchema = z.object({ number: z.number(), }); export const TimelineColumnSchema = z.object({ from: z.string(), // ISO date string to: z.string(), // ISO date string }); export const CheckboxColumnSchema = z.object({ checked: z.boolean(), }); export const DropdownColumnSchema = z.object({ labels: z.array(z.string()), }); export const EmailColumnSchema = z.object({ email: z.string().email(), text: z.string().optional(), }); export const PhoneColumnSchema = z.object({ phone: z.string(), countryShortName: z.string().optional(), }); export const LinkColumnSchema = z.object({ url: z.string().url(), text: z.string().optional(), }); export const LongTextColumnSchema = z.object({ text: z.string(), }); export const ColorColumnSchema = z.object({ color: z.string(), }); export const RatingColumnSchema = z.object({ rating: z.number().min(0).max(5), }); // Column values schema export const ColumnValuesSchema = z.record( z.union([ TextColumnSchema, NumberColumnSchema, DateColumnSchema, StatusColumnSchema, PersonColumnSchema, TimelineColumnSchema, CheckboxColumnSchema, DropdownColumnSchema, EmailColumnSchema, PhoneColumnSchema, LinkColumnSchema, LongTextColumnSchema, ColorColumnSchema, RatingColumnSchema, ]), ); // Create item input schema export const CreateItemInputSchema = z.object({ boardId: z.union([z.string(), z.number()]), itemName: z.string(), columnValues: ColumnValuesSchema.optional(), groupId: z.string().optional(), }); // Types inferred from schemas export type PersonColumn = z.infer<typeof PersonColumnSchema>; export type StatusColumn = z.infer<typeof StatusColumnSchema>; export type DateColumn = z.infer<typeof DateColumnSchema>; export type ColumnValues = z.infer<typeof ColumnValuesSchema>; export type CreateItemInput = z.infer<typeof CreateItemInputSchema>; // Helper function to format column values based on type export function formatColumnValue( columnId: string, value: any, columnType: string, ): any { switch (columnType.toLowerCase()) { case "text": return { text: String(value) }; case "numeric": return { number: Number(value) }; case "date": if (typeof value === "string") { return { date: value }; } if (typeof value === "object") { return { date: value.date, time: value.time, timezone: value.timezone, }; } throw new Error("Invalid date value format"); case "status": return { label: String(value) }; case "people": if (!Array.isArray(value)) { value = [value]; } return { personsAndTeams: value.map((v: number | { id: number }) => ({ id: typeof v === "number" ? v : v.id, kind: "person", })), }; case "checkbox": return { checked: Boolean(value) }; case "timeline": return { from: value.from, to: value.to, }; case "dropdown": return { labels: Array.isArray(value) ? value : [String(value)], }; case "email": return typeof value === "string" ? { email: value } : { email: value.email, text: value.text }; case "phone": return typeof value === "string" ? { phone: value } : { phone: value.phone, countryShortName: value.countryShortName }; case "link": return typeof value === "string" ? { url: value } : { url: value.url, text: value.text }; case "long-text": return { text: String(value) }; case "color": return { color: String(value) }; case "rating": return { rating: Number(value) }; default: // For unknown column types, pass through the value as is return value; } } // Helper function to validate and format column values export function validateAndFormatColumnValues( values: Record<string, any>, columnTypes?: Record<string, string>, ): ColumnValues { const formattedValues: Record<string, any> = {}; for (const [columnId, value] of Object.entries(values)) { const columnType = columnTypes?.[columnId] ?? "text"; // default to text if type unknown formattedValues[columnId] = formatColumnValue(columnId, value, columnType); } const parsed = ColumnValuesSchema.safeParse(formattedValues); if (!parsed.success) { throw new Error(`Invalid column values: ${parsed.error.message}`); } return parsed.data; } // Helper function to validate create item input export function validateCreateItemInput( input: Record<string, any>, ): CreateItemInput { const parsed = CreateItemInputSchema.safeParse(input); if (!parsed.success) { throw new Error(`Invalid create item input: ${parsed.error.message}`); } return parsed.data; } // Response Type export interface MondayResponse { data?: any; error?: any; }