Monday.com MCP Server
#!/usr/bin/env node
import {
CREATE_ITEM_TOOL,
DELETE_ITEM_TOOL,
GET_ITEMS_TOOL,
GET_ITEM_TOOL,
createItem,
deleteItem,
getItem,
getItems,
} from "./operations/items.js";
// Import operations
import {
CREATE_ITEM_WITH_DEMO_DATA_TOOL,
GET_BOARDS_BY_WORKSPACE_TOOL,
GET_BOARD_TOOL,
LIST_BOARDS_TOOL,
createItemWithDemoData,
getBoard,
getBoardsByWorkspace,
listBoards,
} from "./operations/boards.js";
import {
CREATE_MULTIPLE_ITEMS_TOOL,
CREATE_REMAINING_ITEMS_TOOL,
createFirstItem,
createRemainingItems,
formatItemAsMarkdownTable,
} from "./operations/bulk_items.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import {
GET_WORKSPACES_TOOL,
GET_WORKSPACE_TOOL,
getWorkspace,
getWorkspaces,
} from "./operations/workspaces.js";
import type { MondaySDKInstance } from "./types.js";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import mondaySdk from "monday-sdk-js";
class MondayServer {
public monday: MondaySDKInstance;
private apiKey: string | null = null;
constructor() {
this.monday = mondaySdk() as unknown as MondaySDKInstance;
}
public setApiKey(apiKey: string) {
this.apiKey = apiKey;
this.monday.setToken(apiKey);
}
public async validateAuth(): Promise<boolean> {
if (!this.apiKey) {
throw new Error("API key not set. Please provide a Monday.com API key.");
}
try {
await this.monday.api(`query { me { id name } }`);
return true;
} catch (error) {
throw new Error("Invalid API key or authentication failed");
}
}
}
const server = new Server({
name: "monday-server",
version: "0.1.0",
});
const mondayServer = new MondayServer();
// Get API key from command line arguments
const apiKey = process.argv[2];
if (apiKey) {
mondayServer.setApiKey(apiKey);
}
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
LIST_BOARDS_TOOL,
GET_BOARD_TOOL,
GET_ITEMS_TOOL,
GET_WORKSPACES_TOOL,
GET_WORKSPACE_TOOL,
GET_ITEM_TOOL,
GET_BOARDS_BY_WORKSPACE_TOOL,
CREATE_ITEM_TOOL,
DELETE_ITEM_TOOL,
CREATE_ITEM_WITH_DEMO_DATA_TOOL,
CREATE_MULTIPLE_ITEMS_TOOL,
CREATE_REMAINING_ITEMS_TOOL,
],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
await mondayServer.validateAuth();
if (
!request.params.arguments &&
(request.params.name === "get_board" ||
request.params.name === "get_items" ||
request.params.name === "create_item" ||
request.params.name === "get_item" ||
request.params.name === "get_workspace" ||
request.params.name === "get_boards")
) {
return {
content: [
{
type: "text",
text: "Missing required arguments",
},
],
isError: true,
};
}
switch (request.params.name) {
case "list_boards":
return listBoards(mondayServer.monday);
case "get_board":
return getBoard(
mondayServer.monday,
request.params.arguments!.boardId as number,
);
case "get_items":
return getItems(
mondayServer.monday,
request.params.arguments!.boardId as number,
);
case "get_workspaces":
return getWorkspaces(mondayServer.monday);
case "get_workspace":
return getWorkspace(
mondayServer.monday,
request.params.arguments!.workspaceId as number,
);
case "get_item":
return getItem(
mondayServer.monday,
request.params.arguments!.itemId as number,
);
case "get_boards":
return getBoardsByWorkspace(
mondayServer.monday,
request.params.arguments!.workspaceId as number,
);
case "create_item":
return createItem(
mondayServer.monday,
request.params.arguments!.boardId as number,
request.params.arguments!.itemName as string,
request.params.arguments!.groupId as string | undefined,
request.params.arguments!.columnValues as
| Record<string, any>
| undefined,
);
case "delete_item":
return deleteItem(
mondayServer.monday,
request.params.arguments!.itemId as number,
);
case "create_item_with_demo":
return createItemWithDemoData(
mondayServer.monday,
request.params.arguments!.boardId as number,
request.params.arguments!.columnIds as string[] | undefined,
);
case "create_multiple_items": {
const result = await createFirstItem(
mondayServer.monday,
request.params.arguments!.boardId as number,
request.params.arguments!.count as number,
Boolean(request.params.arguments!.isDemo),
);
return {
content: [
{
type: "text",
text: JSON.stringify(result),
},
],
metadata: {
remainingCount: result.remainingCount,
boardId: request.params.arguments!.boardId,
isDemo: Boolean(request.params.arguments!.isDemo),
},
};
}
case "create_remaining_items": {
const created = await createRemainingItems(
mondayServer.monday,
request.params.arguments!.boardId as number,
request.params.arguments!.count as number,
request.params.arguments!.startIndex as number,
Boolean(request.params.arguments!.isDemo),
);
return {
content: [
{
type: "text",
text: `Successfully created ${created} additional items.`,
},
],
};
}
default:
return {
content: [
{
type: "text",
text: `Unknown tool: ${request.params.name}`,
},
],
isError: true,
};
}
});
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Monday.com MCP Server running on stdio");
}
runServer().catch((error) => {
console.error("Fatal error running server:", error);
process.exit(1);
});