Monday.com MCP Server

  • operations
import { CREATE_ITEM_WITH_DEMO_DATA_TOOL, GET_BOARD_WITH_SETTINGS_QUERY, generateDemoValue, } from "../prompts.js"; import type { MondaySDKInstance } from "../types.js"; import type { Tool } from "@modelcontextprotocol/sdk/types.js"; import { createItem } from "./items.js"; import { z } from "zod"; // Query Definitions export const LIST_BOARDS_QUERY = ` query { boards (limit: 100) { id name description state permissions board_kind workspace { id name } } } `; export const GET_BOARD_QUERY = ` query ($boardId: ID!) { boards (ids: [$boardId]) { name state permissions columns { id title } items_page { items { id name created_at creator { id name } column_values { id text value column { id title type } } group { id title } } } } } `; export const GET_BOARDS_BY_WORKSPACE_QUERY = ` query ($workspaceId: ID!) { boards(workspace_ids: [$workspaceId], limit: 100) { id name description state permissions board_kind workspace { id name } } } `; // Schema Definitions export const ListBoardsSchema = z.object({}); export const GetBoardSchema = z.object({ boardId: z.string().or(z.number()), }); export const GetBoardsByWorkspaceSchema = z.object({ workspaceId: z.string().or(z.number()), limit: z.number().optional(), }); // Tool Definitions export const LIST_BOARDS_TOOL: Tool = { name: "list_boards", description: "List all boards in your Monday.com workspace", inputSchema: { type: "object", properties: {}, required: [], }, }; export const GET_BOARD_TOOL: Tool = { name: "get_board", description: "Get detailed information about a specific board", inputSchema: { type: "object", properties: { boardId: { type: "number", description: "The ID of the board to fetch", }, }, required: ["boardId"], }, }; export const GET_BOARDS_BY_WORKSPACE_TOOL: Tool = { name: "get_boards", description: "Get all boards in a specific workspace", inputSchema: { type: "object", properties: { workspaceId: { type: "number", description: "The ID of the workspace to fetch boards from", }, }, required: ["workspaceId"], }, }; export { CREATE_ITEM_WITH_DEMO_DATA_TOOL }; // Add type definitions interface BoardColumn { id: string; title: string; type: string; settings_str?: string; } interface ColumnValue { column: { id: string; title: string; }; text: string; value: string | null; } interface VerificationResult { columnId: string; columnTitle: string; isSet: boolean; actualValue: { text: string; value: string | null } | null; } // Operation Functions export async function listBoards(monday: MondaySDKInstance) { try { const response = await monday.api(LIST_BOARDS_QUERY); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error: ${JSON.stringify(error)}`, }, ], isError: true, }; } } export async function getBoard(monday: MondaySDKInstance, boardId: number) { try { const response = await monday.api(GET_BOARD_QUERY, { variables: { boardId: boardId.toString() }, }); if (response.errors) { return { content: [ { type: "text", text: `Monday.com API Error: ${JSON.stringify(response.errors)}`, }, ], isError: true, }; } if (response.data?.boards?.length > 0) { return { content: [ { type: "text", text: JSON.stringify(response.data.boards[0], null, 2), }, ], }; } return { content: [ { type: "text", text: `Board with ID ${boardId} not found`, }, ], isError: true, }; } catch (error) { return { content: [ { type: "text", text: `Failed to fetch board: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } export async function getBoardsByWorkspace( monday: MondaySDKInstance, workspaceId: number, ) { try { const response = await monday.api(GET_BOARDS_BY_WORKSPACE_QUERY, { variables: { workspaceId: workspaceId.toString() }, }); if (response.errors) { return { content: [ { type: "text", text: `Monday.com API Error: ${JSON.stringify(response.errors)}`, }, ], isError: true, }; } return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Failed to fetch boards: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } export async function getBoardWithSettings( monday: MondaySDKInstance, boardId: number, ) { try { const response = await monday.api(GET_BOARD_WITH_SETTINGS_QUERY, { variables: { boardId: boardId.toString() }, }); if (response.errors) { return { content: [ { type: "text", text: `Monday.com API Error: ${JSON.stringify(response.errors)}`, }, ], isError: true, }; } if (!response.data?.boards?.[0]) { return { content: [ { type: "text", text: `Board with ID ${boardId} not found`, }, ], isError: true, }; } return { content: [ { type: "text", text: JSON.stringify(response.data.boards[0], null, 2), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Failed to fetch board: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } } export async function createItemWithDemoData( monday: MondaySDKInstance, boardId: number, columnIds?: string[], ) { try { // First, fetch the board structure const boardResponse = await monday.api(GET_BOARD_WITH_SETTINGS_QUERY, { variables: { boardId: boardId.toString() }, }); if (boardResponse.errors || !boardResponse.data?.boards?.[0]) { throw new Error( boardResponse.errors ? JSON.stringify(boardResponse.errors) : `Board ${boardId} not found`, ); } const board = boardResponse.data.boards[0]; const columnValues: Record<string, any> = {}; // Generate demo data for specified columns or all columns const columnsToProcess = columnIds?.length ? board.columns.filter((col: BoardColumn) => columnIds.includes(col.id)) : board.columns; // Validate that all requested columns exist if (columnIds?.length) { const foundColumnIds = columnsToProcess.map((col: BoardColumn) => col.id); const missingColumns = columnIds.filter( (id) => !foundColumnIds.includes(id), ); if (missingColumns.length > 0) { throw new Error( `Some requested columns were not found: ${missingColumns.join(", ")}`, ); } } for (const column of columnsToProcess) { let settings; if (column.settings_str) { try { settings = JSON.parse(column.settings_str); } catch (e) { settings = undefined; } } columnValues[column.id] = generateDemoValue(column.type, settings); } // Create the item with demo data const createResponse = await createItem( monday, boardId, "Demo Item", undefined, columnValues, ); // Check if item creation was successful if (createResponse.isError ?? !createResponse.content?.[0]?.text) { throw new Error("Failed to create item"); } // Parse the created item data const createdItem = JSON.parse(createResponse.content[0].text); // Verify the values were set correctly const verificationResults = columnsToProcess.map((column: BoardColumn) => { const columnValue = createdItem.column_values.find( (cv: ColumnValue) => cv.column.id === column.id, ); const isSet = columnValue && (columnValue.value !== null || columnValue.text !== ""); return { columnId: column.id, columnTitle: column.title, isSet, actualValue: columnValue ? { text: columnValue.text, value: columnValue.value } : null, }; }); // Check if any columns failed to set const failedColumns = verificationResults.filter( (result: VerificationResult) => !result.isSet, ); if (failedColumns.length > 0) { return { content: [ { type: "text", text: JSON.stringify( { message: "Item created but some columns failed to set properly", item: createdItem, failedColumns: failedColumns, }, null, 2, ), }, ], isError: true, }; } // All good - return success with verification details return { content: [ { type: "text", text: JSON.stringify( { message: "Item created successfully with all values set properly", item: createdItem, verificationResults, }, null, 2, ), }, ], }; } catch (error) { return { content: [ { type: "text", text: `Failed to create item with demo data: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }