├── .nvmrc ├── .eslintignore ├── .prettierignore ├── packages ├── agent-toolkit │ ├── CHANGELOG.md │ ├── src │ │ ├── openai │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── version.utils.ts │ │ │ ├── types.ts │ │ │ ├── index.ts │ │ │ ├── tracking.utils.ts │ │ │ ├── tools │ │ │ │ ├── initializing.utils.ts │ │ │ │ └── tools-filtering.utils.ts │ │ │ ├── tests │ │ │ │ ├── token.utils.test.ts │ │ │ │ └── string.utils.test.ts │ │ │ ├── time.utils.ts │ │ │ ├── string.utils.ts │ │ │ ├── error.utils.ts │ │ │ ├── token.utils.ts │ │ │ └── microsoft-copilot.utils.ts │ │ ├── mcp │ │ │ └── index.ts │ │ ├── monday-graphql │ │ │ ├── generated │ │ │ │ └── graphql │ │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── core │ │ │ ├── tools │ │ │ ├── platform-api-tools │ │ │ │ ├── full-board-data-tool │ │ │ │ │ ├── full-board-data.consts.ts │ │ │ │ │ ├── full-board-data.types.ts │ │ │ │ │ └── full-board-data.graphql.ts │ │ │ │ ├── search-tool │ │ │ │ │ ├── search-tool.consts.ts │ │ │ │ │ ├── search-tool.graphql.ts │ │ │ │ │ └── search-tool.types.ts │ │ │ │ ├── list-workspace-tool │ │ │ │ │ ├── list-workspace.consts.ts │ │ │ │ │ └── list-workspace.graphql.ts │ │ │ │ ├── dashboard-tools │ │ │ │ │ ├── index.ts │ │ │ │ │ └── dashboard-queries.graphql.ts │ │ │ │ ├── get-column-type-info │ │ │ │ │ ├── get-column-type-schema.graphql.ts │ │ │ │ │ └── get-column-type-info-tool.ts │ │ │ │ ├── workforms-tools │ │ │ │ │ ├── get-form-tool │ │ │ │ │ │ ├── schema.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── create-form-tool │ │ │ │ │ │ ├── schema.ts │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── form-questions-editor-tool │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── utils │ │ │ │ │ │ └── form-questions-editor-tool-helpers.ts │ │ │ │ ├── update-workspace-tool │ │ │ │ │ ├── update-workspace-tool.graphql.ts │ │ │ │ │ └── update-workspace-tool.ts │ │ │ │ ├── create-update-tool │ │ │ │ │ ├── create-update.graphql.ts │ │ │ │ │ └── create-update-tool.ts │ │ │ │ ├── create-item-tool │ │ │ │ │ ├── duplicate-item.graphql.ts │ │ │ │ │ └── create-subitem.graphql.ts │ │ │ │ ├── list-users-and-teams-tool │ │ │ │ │ ├── constants.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── create-workspace-tool │ │ │ │ │ ├── create-workspace-tool.graphql.ts │ │ │ │ │ └── create-workspace-tool.ts │ │ │ │ ├── get-board-activity │ │ │ │ │ ├── get-board-activity.graphql.ts │ │ │ │ │ └── get-board-activity-tool.ts │ │ │ │ ├── create-group │ │ │ │ │ ├── create-group.graphql.ts │ │ │ │ │ ├── create-group.consts.ts │ │ │ │ │ └── create-group-tool.ts │ │ │ │ ├── create-folder-tool │ │ │ │ │ ├── create-folder-tool.graphql.ts │ │ │ │ │ └── create-folder-tool.ts │ │ │ │ ├── board-insights │ │ │ │ │ ├── board-insights.graphql.ts │ │ │ │ │ └── board-insights.consts.ts │ │ │ │ ├── move-object-tool │ │ │ │ │ └── move-object-tool.graphql.ts │ │ │ │ ├── update-folder-tool │ │ │ │ │ ├── update-folder-tool.graphql.ts │ │ │ │ │ └── update-folder-tool.ts │ │ │ │ ├── workspace-info-tool │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── helpers.ts │ │ │ │ │ └── workspace-info-tool.ts │ │ │ │ ├── create-doc-tool │ │ │ │ │ └── create-doc-tool.graphql.ts │ │ │ │ ├── delete-item-tool.ts │ │ │ │ ├── get-board-items-page-tool │ │ │ │ │ └── get-board-items-page-tool.graphql.ts │ │ │ │ ├── move-item-to-group-tool.ts │ │ │ │ ├── get-board-info │ │ │ │ │ ├── get-board-info.graphql.ts │ │ │ │ │ └── get-board-info-tool.ts │ │ │ │ ├── fetch-custom-activity-tool.ts │ │ │ │ ├── create-board-tool.ts │ │ │ │ ├── delete-column-tool.ts │ │ │ │ ├── create-custom-activity-tool.ts │ │ │ │ ├── get-board-schema-tool.ts │ │ │ │ ├── create-column-tool.ts │ │ │ │ ├── change-item-column-values-tool.ts │ │ │ │ ├── test-utils │ │ │ │ │ └── mock-api-client.ts │ │ │ │ ├── create-timeline-item-tool.ts │ │ │ │ ├── base-monday-api-tool.ts │ │ │ │ └── get-graphql-schema-tool.ts │ │ │ ├── monday-apps-tools │ │ │ │ ├── app-development-assistant │ │ │ │ │ ├── index.ts │ │ │ │ │ └── schemas │ │ │ │ │ │ └── assistant-schemas.ts │ │ │ │ ├── app-version │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── schemas │ │ │ │ │ │ └── app-version-schemas.ts │ │ │ │ │ ├── get-app-version.ts │ │ │ │ │ └── get-app-versions.ts │ │ │ │ ├── storage │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── schemas │ │ │ │ │ │ └── storage-schemas.ts │ │ │ │ │ ├── export-storage-data.ts │ │ │ │ │ └── search-storage-records.ts │ │ │ │ ├── app │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── schemas │ │ │ │ │ │ └── app-schemas.ts │ │ │ │ │ ├── create-app.ts │ │ │ │ │ ├── get-all-apps.ts │ │ │ │ │ └── promote-app.ts │ │ │ │ ├── app-feature │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── schemas │ │ │ │ │ │ └── app-feature-schemas.ts │ │ │ │ │ └── get-app-features.ts │ │ │ │ ├── monday-code │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── schemas │ │ │ │ │ │ └── code-schemas.ts │ │ │ │ │ ├── set-environment-variable.ts │ │ │ │ │ ├── list-environment-variable-keys.ts │ │ │ │ │ └── get-deployment-status.ts │ │ │ │ ├── consts │ │ │ │ │ ├── apps.consts.ts │ │ │ │ │ └── routes.consts.ts │ │ │ │ └── index.ts │ │ │ ├── monday-dev-tools │ │ │ │ ├── shared │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── get-sprints-boards-tool │ │ │ │ │ └── get-sprints-boards-tool.graphql.ts │ │ │ │ ├── index.ts │ │ │ │ ├── get-sprint-summary-tool │ │ │ │ │ └── get-sprint-summary-tool.graphql.ts │ │ │ │ └── get-sprints-metadata-tool │ │ │ │ │ └── get-sprints-metadata-tool.graphql.ts │ │ │ └── index.ts │ │ │ ├── executable.ts │ │ │ ├── index.ts │ │ │ ├── monday-agent-toolkit.ts │ │ │ └── tool.ts │ ├── graphql.config.yml │ ├── fetch-schema.sh │ ├── jest.config.ts │ ├── codegen.yml │ ├── tsconfig.json │ ├── LICENSE.md │ ├── rollup.config.js │ ├── README.md │ └── package.json └── monday-api-mcp │ ├── CHANGELOG.md │ ├── src │ ├── lib.ts │ ├── domains │ │ └── atp │ │ │ ├── atp.types.ts │ │ │ └── index.ts │ ├── utils │ │ └── args │ │ │ ├── args.types.ts │ │ │ ├── args.config.ts │ │ │ └── args.service.ts │ └── index.ts │ ├── tests │ └── mcp.test.ts │ ├── tsconfig.test.json │ ├── jest.config.js │ ├── tsconfig.json │ └── package.json ├── .prettierrc.json ├── .graphqlrc.yml ├── .eslintrc.json ├── commands └── monday │ ├── sprint-summary.toml │ ├── save-my-user-id.toml │ ├── create-item.toml │ ├── update-item.toml │ └── analyze-board.toml ├── gemini-extension.json ├── .vscode └── settings.json ├── turbo.json ├── .github └── workflows │ ├── pull_request.yml │ ├── npm_publish.yml │ └── version_check.yml ├── package.json ├── LICENSE ├── server.json ├── MONDAY.md ├── .gitignore └── docs └── version-bumping.md /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.18.1 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/generated/** 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/generated/** 2 | -------------------------------------------------------------------------------- /packages/agent-toolkit/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/lib.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/openai/index.ts: -------------------------------------------------------------------------------- 1 | export * from './toolkit'; 2 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/version.utils.ts: -------------------------------------------------------------------------------- 1 | export const API_VERSION = '2026-01'; 2 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/mcp/index.ts: -------------------------------------------------------------------------------- 1 | export * from './toolkit'; 2 | export * from './dynamic-tool-manager'; 3 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/monday-graphql/generated/graphql/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export * from './gql'; -------------------------------------------------------------------------------- /packages/agent-toolkit/src/monday-graphql/index.ts: -------------------------------------------------------------------------------- 1 | export * from './generated/graphql'; 2 | export * from './queries.graphql'; 3 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/domains/atp/atp.types.ts: -------------------------------------------------------------------------------- 1 | export interface AtpServerConfig { 2 | token: string; 3 | version?: string; 4 | } 5 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/full-board-data-tool/full-board-data.consts.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_ITEMS_LIMIT = 7; 2 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/executable.ts: -------------------------------------------------------------------------------- 1 | export interface Executable { 2 | execute: (input?: Input) => Promise; 3 | } 4 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/tests/mcp.test.ts: -------------------------------------------------------------------------------- 1 | describe('Existence', () => { 2 | it('should pass', () => { 3 | expect(1).toBe(1); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './executable'; 2 | export * from './tool'; 3 | export * from './tools'; 4 | export * from './monday-agent-toolkit'; 5 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/search-tool/search-tool.consts.ts: -------------------------------------------------------------------------------- 1 | export const SEARCH_LIMIT = 100; 2 | export const LOAD_INTO_MEMORY_LIMIT = 10_000; 3 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/domains/atp/index.ts: -------------------------------------------------------------------------------- 1 | export { runAtpMcpServer } from './atp.service.js'; 2 | export * from './atp.consts.js'; 3 | export * from './atp.types.js'; 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "printWidth": 120, 5 | "semi": true, 6 | "singleQuote": true, 7 | "bracketSpacing": true 8 | } 9 | -------------------------------------------------------------------------------- /packages/agent-toolkit/graphql.config.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | api: 3 | schema: ./src/monday-graphql/schema.graphql 4 | documents: 5 | - ./src/**/*.graphql 6 | - ./src/**/*.graphql.ts 7 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/list-workspace-tool/list-workspace.consts.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_WORKSPACE_LIMIT = 100; 2 | export const MAX_WORKSPACE_LIMIT_FOR_SEARCH = 10_000; 3 | -------------------------------------------------------------------------------- /.graphqlrc.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | agent-toolkit: 3 | schema: ./packages/agent-toolkit/src/monday-graphql/schema.graphql 4 | documents: 5 | - ./packages/agent-toolkit/src/**/*.graphql 6 | - ./packages/agent-toolkit/src/**/*.graphql.ts 7 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/dashboard-tools/index.ts: -------------------------------------------------------------------------------- 1 | // Dashboard Tools - Export all dashboard-related tools 2 | export * from './create-dashboard-tool'; 3 | export * from './all-widgets-schema-tool'; 4 | export * from './create-widget-tool'; 5 | 6 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDirs": ["./src", "./tests"], 5 | "isolatedModules": true, 6 | "esModuleInterop": true 7 | }, 8 | "include": ["./src/**/*", "./tests/**/*"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-column-type-info/get-column-type-schema.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getColumnTypeSchema = gql` 4 | query GetColumnTypeSchema($type: ColumnType!) { 5 | get_column_type_schema(type: $type) 6 | } 7 | `; -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workforms-tools/get-form-tool/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { GraphQLDescriptions } from '../workforms.consts'; 3 | 4 | export const getFormToolSchema = { 5 | formToken: z.string().describe(GraphQLDescriptions.commonArgs.formToken), 6 | }; 7 | -------------------------------------------------------------------------------- /packages/agent-toolkit/fetch-schema.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Extract API version from shared constants file 4 | API_VERSION=$(grep -o "API_VERSION = '[^']*'" src/utils/version.utils.ts | cut -d "'" -f 2) 5 | 6 | curl "https://api.monday.com/v2/get_schema?format=sdl&version=$API_VERSION" -o src/monday-graphql/schema.graphql -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/types.ts: -------------------------------------------------------------------------------- 1 | import { ColumnType } from "src/monday-graphql/generated/graphql/graphql"; 2 | 3 | export const NonDeprecatedColumnType = Object.fromEntries( 4 | Object.entries(ColumnType).filter(([key]) => key !== "Person") 5 | ) as Record, ColumnType>; -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:@typescript-eslint/recommended" 5 | ], 6 | "plugins": [ 7 | "@typescript-eslint" 8 | ], 9 | "rules": { 10 | "@typescript-eslint/no-explicit-any": "off", 11 | "@typescript-eslint/no-unused-vars": "off" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /commands/monday/sprint-summary.toml: -------------------------------------------------------------------------------- 1 | description = "Get a comprehensive summary of a monday.com sprint." 2 | prompt = """ 3 | Please provide a comprehensive summary for the monday.com sprint. 4 | 5 | Sprint ID or details: {{args}} 6 | 7 | Use the `get_sprint_summary` tool. If the Sprint ID is missing, please ask for it. 8 | """ 9 | -------------------------------------------------------------------------------- /gemini-extension.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monday", 3 | "description": "Manage your monday.com projects, tasks, and everday work.", 4 | "version": "0.0.41", 5 | "contextFileName": "MONDAY.md", 6 | "mcpServers": { 7 | "monday": { 8 | "httpUrl": "https://mcp.monday.com/mcp" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-development-assistant/index.ts: -------------------------------------------------------------------------------- 1 | import { GetAppDevelopmentContextTool } from './get-app-development-context'; 2 | 3 | export const appDevelopmentAssistantTools = [GetAppDevelopmentContextTool]; 4 | 5 | export * from './get-app-development-context'; 6 | export * from './schemas/assistant-schemas'; 7 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/index.ts: -------------------------------------------------------------------------------- 1 | import { GetAppVersionsTool } from './get-app-versions'; 2 | import { GetAppVersionTool } from './get-app-version'; 3 | 4 | export const appVersionTools = [GetAppVersionsTool, GetAppVersionTool]; 5 | 6 | export * from './get-app-versions'; 7 | export * from './get-app-version'; 8 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/full-board-data-tool/full-board-data.types.ts: -------------------------------------------------------------------------------- 1 | import { GetUsersByIdsQuery, PeopleEntity, PeopleValue } from '../../../../monday-graphql/generated/graphql/graphql'; 2 | 3 | export type User = NonNullable[number]>; 4 | 5 | export type { PeopleEntity, PeopleValue }; 6 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/list-workspace-tool/list-workspace.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const listWorkspaces = gql` 4 | query listWorkspaces($limit: Int!, $page: Int!) { 5 | workspaces(limit: $limit, page: $page) { 6 | id 7 | name 8 | description 9 | } 10 | } 11 | `; 12 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/index.ts: -------------------------------------------------------------------------------- 1 | import { SearchStorageRecordsTool } from './search-storage-records'; 2 | import { ExportStorageDataTool } from './export-storage-data'; 3 | 4 | export const storageTools = [SearchStorageRecordsTool, ExportStorageDataTool]; 5 | 6 | export * from './search-storage-records'; 7 | export * from './export-storage-data'; 8 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/update-workspace-tool/update-workspace-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const updateWorkspace = gql` 4 | mutation updateWorkspace($id: ID!, $attributes: UpdateWorkspaceAttributesInput!) { 5 | update_workspace(id: $id, attributes: $attributes) { 6 | id 7 | } 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-dev-tools/shared/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shared Monday Dev tools module 3 | * 4 | * This module provides common types, constants, and helpers 5 | */ 6 | 7 | // Export all types 8 | export * from './types'; 9 | 10 | // Export all constants 11 | export * from './constants'; 12 | 13 | // Export all helper functions 14 | export * from './helpers'; 15 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/index.ts: -------------------------------------------------------------------------------- 1 | import { allMondayAppsTools } from './monday-apps-tools'; 2 | import { allGraphqlApiTools } from './platform-api-tools'; 3 | import { allMondayDevTools } from './monday-dev-tools'; 4 | 5 | export const allTools = [...allGraphqlApiTools, ...allMondayDevTools, ...allMondayAppsTools]; 6 | 7 | export { allGraphqlApiTools, allMondayDevTools, allMondayAppsTools }; 8 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-update-tool/create-update.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const createUpdate = gql` 4 | mutation createUpdate($itemId: ID!, $body: String!, $mentionsList: [UpdateMention]) { 5 | create_update(body: $body, item_id: $itemId, mentions_list: $mentionsList) { 6 | id 7 | } 8 | } 9 | `; 10 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-item-tool/duplicate-item.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const duplicateItem = gql` 4 | mutation duplicateItem($boardId: ID!, $itemId: ID!, $withUpdates: Boolean) { 5 | duplicate_item(board_id: $boardId, item_id: $itemId, with_updates: $withUpdates) { 6 | id 7 | name 8 | } 9 | } 10 | `; 11 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app/index.ts: -------------------------------------------------------------------------------- 1 | import { GetAllAppsTool } from './get-all-apps'; 2 | import { PromoteAppTool } from './promote-app'; 3 | import { CreateAppTool } from './create-app'; 4 | 5 | export const appTools = [GetAllAppsTool, PromoteAppTool, CreateAppTool]; 6 | 7 | export * from './get-all-apps'; 8 | export * from './promote-app'; 9 | export * from './create-app'; 10 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/jest.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | /** @type {import('jest').Config} */ 3 | module.exports = { 4 | preset: 'ts-jest', 5 | testEnvironment: 'node', 6 | transform: { 7 | '^.+\\.tsx?$': [ 8 | 'ts-jest', 9 | { 10 | useESM: true, 11 | }, 12 | ], 13 | }, 14 | extensionsToTreatAsEsm: ['.ts'], 15 | testMatch: ['**/tests/**/*.test.ts'], 16 | }; 17 | -------------------------------------------------------------------------------- /packages/agent-toolkit/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from '@jest/types'; 2 | 3 | const config: Config.InitialOptions = { 4 | verbose: true, 5 | testEnvironment: 'node', 6 | preset: 'ts-jest', 7 | moduleNameMapper: { 8 | '^src/(.*)$': '/src/$1' 9 | }, 10 | roots: ['/src'], 11 | testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'] 12 | }; 13 | 14 | export default config; 15 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/list-users-and-teams-tool/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Constants for list_users_and_teams tool limits and configuration 3 | */ 4 | 5 | // Max limits for ID arrays 6 | export const MAX_USER_IDS = 500; // Maximum user IDs allowed in a single query 7 | export const MAX_TEAM_IDS = 500; // Maximum team IDs allowed in a single query 8 | 9 | export const DEFAULT_USER_LIMIT = 1000; // Default limit when no IDs provided 10 | 11 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "Node16", 5 | "moduleResolution": "Node16", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "skipLibCheck": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "resolveJsonModule": true, 11 | "outDir": "./dist", 12 | "rootDirs": ["./src"] 13 | }, 14 | "include": ["./src/**/*"], 15 | "exclude": ["node_modules"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-item-tool/create-subitem.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const createSubitem = gql` 4 | mutation createSubitem($parentItemId: ID!, $itemName: String!, $columnValues: JSON) { 5 | create_subitem(parent_item_id: $parentItemId, item_name: $itemName, column_values: $columnValues) { 6 | id 7 | name 8 | parent_item { 9 | id 10 | } 11 | } 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /commands/monday/save-my-user-id.toml: -------------------------------------------------------------------------------- 1 | description = "Fetches the current monday.com user ID and saves it to long-term memory." 2 | prompt = """ 3 | I need you to find and remember my monday.com User ID. 4 | 5 | Please execute the following steps: 6 | 1. Use the `list_users_and_teams` tool with `{"getMe": true}` to find my user details. 7 | 2. Once you have the response, extract the `id` field. 8 | 3. Use the `save_memory` tool to save this exact fact: "My monday.com user ID is [THE_ID_YOU_FOUND]". 9 | """ 10 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/index.ts: -------------------------------------------------------------------------------- 1 | import { GetAppFeaturesTool } from './get-app-features'; 2 | import { CreateAppFeatureTool } from './create-app-feature'; 3 | import { GetAppFeatureSchemaToool } from './get-app-feature-schema'; 4 | 5 | export const appFeatureTools = [GetAppFeaturesTool, CreateAppFeatureTool, GetAppFeatureSchemaToool]; 6 | 7 | export * from './get-app-features'; 8 | export * from './create-app-feature'; 9 | export * from './get-app-feature-schema'; 10 | -------------------------------------------------------------------------------- /packages/agent-toolkit/codegen.yml: -------------------------------------------------------------------------------- 1 | overwrite: true 2 | schema: 'src/monday-graphql/schema.graphql' 3 | documents: 'src/**/*.graphql.ts' 4 | ignoreNoDocuments: true 5 | generates: 6 | src/monday-graphql/generated/graphql/: 7 | presetConfig: 8 | fragmentMasking: false 9 | preset: client 10 | hooks: 11 | afterOneFileWrite: 12 | - node -e "const fs = require('fs'); fs.writeFileSync('src/monday-graphql/generated/graphql/index.ts', '/* eslint-disable */\nexport * from \'./gql\';');" 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "jest.virtualFolders": [ 3 | { 4 | "name": "agent-toolkit", 5 | "files": ["packages/agent-toolkit"], 6 | "jestCommandLine": "yarn run jest --config ./packages/agent-toolkit/jest.config.ts" 7 | }, 8 | { 9 | "name": "monday-api-mcp", 10 | "files": ["packages/monday-api-mcp"], 11 | "jestCommandLine": "yarn run jest --config ./packages/monday-api-mcp/jest.config.js" 12 | }, 13 | ] 14 | } -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-dev-tools/get-sprints-boards-tool/get-sprints-boards-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getRecentBoards = gql` 4 | query GetRecentBoards($limit: Int) { 5 | boards(limit: $limit, order_by: used_at, state: active) { 6 | id 7 | name 8 | workspace { 9 | id 10 | name 11 | } 12 | columns { 13 | id 14 | type 15 | settings 16 | } 17 | } 18 | } 19 | `; 20 | 21 | -------------------------------------------------------------------------------- /commands/monday/create-item.toml: -------------------------------------------------------------------------------- 1 | description = "Create a new item in a monday.com board." 2 | prompt = """ 3 | I want to create a new item in monday.com. 4 | 5 | Here is the input: {{args}} 6 | 7 | Please use the `create_item` tool. 8 | If any strictly required information (like Board ID or Item Name) is missing 9 | from the input, please ask for it before proceeding. If column values are 10 | provided in natural language, please try to map them to the board's actual 11 | columns (you might need to use `get_board_info` first if you don't know the column IDs). 12 | """ 13 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/utils/args/args.types.ts: -------------------------------------------------------------------------------- 1 | import { ToolMode } from '@mondaydotcomorg/agent-toolkit/core'; 2 | 3 | export interface ArgConfig { 4 | name: string; 5 | flags: string[]; 6 | description: string; 7 | required?: boolean; 8 | defaultValue?: unknown; 9 | } 10 | 11 | export interface ParsedArgs { 12 | [key: string]: string | undefined; 13 | } 14 | 15 | export interface ValidatedArgs { 16 | token: string; 17 | version?: string; 18 | readOnlyMode: boolean; 19 | mode: ToolMode; 20 | enableDynamicApiTools: boolean | 'only'; 21 | } 22 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-workspace-tool/create-workspace-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const createWorkspace = gql` 4 | mutation createWorkspace( 5 | $name: String! 6 | $workspaceKind: WorkspaceKind! 7 | $description: String 8 | $accountProductId: ID 9 | ) { 10 | create_workspace( 11 | name: $name 12 | kind: $workspaceKind 13 | description: $description 14 | account_product_id: $accountProductId 15 | ) { 16 | id 17 | } 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": ["**/.env.*local"], 4 | "tasks": { 5 | "build": { 6 | "dependsOn": ["^build"], 7 | "outputs": ["dist/**"] 8 | }, 9 | "test": { 10 | "dependsOn": ["build"], 11 | "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"] 12 | }, 13 | "dev": { 14 | "cache": false, 15 | "persistent": true 16 | }, 17 | "prettier": { 18 | "cache": false 19 | }, 20 | "lint": { 21 | "cache": false 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/index.ts: -------------------------------------------------------------------------------- 1 | import { GetDeploymentStatusTool } from './get-deployment-status'; 2 | import { SetEnvironmentVariableTool } from './set-environment-variable'; 3 | import { ListEnvironmentVariableKeysTool } from './list-environment-variable-keys'; 4 | 5 | export const codeTools = [ 6 | GetDeploymentStatusTool, 7 | SetEnvironmentVariableTool, 8 | ListEnvironmentVariableKeysTool, 9 | ]; 10 | 11 | export * from './get-deployment-status'; 12 | export * from './set-environment-variable'; 13 | export * from './list-environment-variable-keys'; 14 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getFilteredToolInstances } from './tools/tools-filtering.utils'; 2 | export { toolFactory } from './tools/initializing.utils'; 3 | export { trackEvent } from './tracking.utils'; 4 | export { extractTokenInfo, decodeJwtToken, MondayTokenPayload } from './token.utils'; 5 | export { TIME_IN_SECONDS, TIME_IN_MILLISECONDS, NANOSECONDS_PER_MILLISECOND } from './time.utils'; 6 | export { API_VERSION } from './version.utils'; 7 | export { rethrowWithContext } from './error.utils'; 8 | export { filterByTopic, filterByTopicWithDetails, FilterByTopicResult } from './content-filter.utils'; 9 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-board-activity/get-board-activity.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getBoardAllActivity = gql` 4 | query GetBoardAllActivity( 5 | $boardId: ID! 6 | $fromDate: ISO8601DateTime! 7 | $toDate: ISO8601DateTime! 8 | $limit: Int = 1000 9 | $page: Int = 1 10 | ) { 11 | boards(ids: [$boardId]) { 12 | activity_logs(from: $fromDate, to: $toDate, limit: $limit, page: $page) { 13 | user_id 14 | entity 15 | event 16 | data 17 | created_at 18 | } 19 | } 20 | } 21 | `; 22 | -------------------------------------------------------------------------------- /commands/monday/update-item.toml: -------------------------------------------------------------------------------- 1 | description = "Update a monday.com item with a comment or change column values." 2 | prompt = """ 3 | Please update a monday.com item. (bug, task, epic, etc.) 4 | 5 | Input details: {{args}} 6 | 7 | To add a comment on an item use the `create_update` tool. You will need the Item ID and the text of the update. 8 | If these are not clear from the input, please ask for clarification. 9 | 10 | To update a column value on an item use the `change_item_column_values` tool. You will need the Board ID, Item ID and the column ID and value. 11 | If these are not clear from the input, please ask for clarification. 12 | """ 13 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-group/create-group.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const createGroup = gql` 4 | mutation createGroup( 5 | $boardId: ID! 6 | $groupName: String! 7 | $groupColor: String 8 | $relativeTo: String 9 | $positionRelativeMethod: PositionRelative 10 | ) { 11 | create_group( 12 | board_id: $boardId 13 | group_name: $groupName 14 | group_color: $groupColor 15 | relative_to: $relativeTo 16 | position_relative_method: $positionRelativeMethod 17 | ) { 18 | id 19 | title 20 | } 21 | } 22 | `; 23 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/tracking.utils.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | /** 4 | * Tracks event 5 | * @param name - Event name 6 | * @param data - Event data 7 | */ 8 | export const trackEvent = ({ name, data }: { name: string; data: Record }): void => { 9 | axios 10 | .post( 11 | 'https://track.bigbrain.me/prod/event', 12 | { 13 | name, 14 | data, 15 | }, 16 | { 17 | headers: { 18 | 'Content-Type': 'application/json', 19 | 'User-Agent': 'dapulse', 20 | }, 21 | }, 22 | ) 23 | .catch(() => { 24 | // ignore errors in tracking 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-folder-tool/create-folder-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const createFolderTool = gql` 4 | mutation createFolder( 5 | $workspaceId: ID! 6 | $name: String! 7 | $color: FolderColor 8 | $fontWeight: FolderFontWeight 9 | $customIcon: FolderCustomIcon 10 | $parentFolderId: ID 11 | ) { 12 | create_folder( 13 | workspace_id: $workspaceId 14 | name: $name 15 | color: $color 16 | font_weight: $fontWeight 17 | custom_icon: $customIcon 18 | parent_folder_id: $parentFolderId 19 | ) { 20 | id 21 | } 22 | } 23 | `; 24 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yml: -------------------------------------------------------------------------------- 1 | on: pull_request 2 | name: Pull Request 3 | jobs: 4 | validate: 5 | name: Run validations 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@master 9 | with: 10 | fetch-depth: 0 11 | - name: Use Node.js 12 | uses: actions/setup-node@v3 13 | with: 14 | node-version: '20.18.1' 15 | - name: Install Yarn 16 | run: npm install -g yarn@1.22.21 17 | - run: yarn install 18 | - run: yarn prettier 19 | - run: yarn lint 20 | 21 | - name: Build packages 22 | run: yarn build 23 | 24 | - name: Test packages 25 | run: yarn test 26 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-group/create-group.consts.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Predefined group colors from Monday.com platform 3 | * These are the official group colors supported by Monday.com 4 | * Source: @mondaydotcomorg/board-columns/src/constants/columns/group/group-colors.js 5 | */ 6 | export const GROUP_COLORS = [ 7 | '#037f4c', 8 | '#00c875', 9 | '#9cd326', 10 | '#cab641', 11 | '#ffcb00', 12 | '#784bd1', 13 | '#9d50dd', 14 | '#007eb5', 15 | '#579bfc', 16 | '#66ccff', 17 | '#bb3354', 18 | '#df2f4a', 19 | '#ff007f', 20 | '#ff5ac4', 21 | '#ff642e', 22 | '#fdab3d', 23 | '#7f5347', 24 | '#c4c4c4', 25 | '#757575', 26 | ] as const; 27 | -------------------------------------------------------------------------------- /packages/agent-toolkit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "lib": ["ES2021", "dom"], 5 | "module": "ESNext", 6 | "target": "ES2021", 7 | "moduleResolution": "node", 8 | "rootDirs": ["./lib", "tests"], 9 | "outDir": "./dist", 10 | "moduleDetection": "force", 11 | "strict": true, 12 | "declaration": true, 13 | "skipLibCheck": true, 14 | "sourceMap": true, 15 | "esModuleInterop": true, 16 | "resolveJsonModule": true, 17 | "allowSyntheticDefaultImports": true, 18 | "forceConsistentCasingInFileNames": true 19 | }, 20 | "exclude": ["dist", "node_modules"], 21 | "include": ["./src/**/*", "tests", "scripts"] 22 | } 23 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/board-insights/board-insights.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const boardInsights = gql` 4 | query aggregateBoardInsights($query: AggregateQueryInput!) { 5 | aggregate(query: $query) { 6 | results { 7 | entries { 8 | alias 9 | value { 10 | ... on AggregateBasicAggregationResult { 11 | result 12 | } 13 | ... on AggregateGroupByResult { 14 | value_string 15 | value_int 16 | value_float 17 | value_boolean 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | `; 25 | -------------------------------------------------------------------------------- /commands/monday/analyze-board.toml: -------------------------------------------------------------------------------- 1 | description = "Analyze a monday.com board to provide insights." 2 | prompt = """ 3 | Please analyze the monday.com board corresponding to this input: {{args}} 4 | 5 | Goal: Provide a summary of the board's data, such as total items, items per status, or other relevant aggregations. 6 | 7 | Steps: 8 | 1. Identify the Board ID from the input. If not provided, ask for it. You can extract it from the board's url. 9 | 2. If you are not familiar with the board's structure, use `get_board_info` first to understand available columns. 10 | 3. Use the `board_insights` tool to calculate relevant insights based on the user's request or general best practices if no specific insight was requested. 11 | """ 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "monday-ai", 3 | "version": "1.1.0", 4 | "description": "monday.com AI repository", 5 | "private": true, 6 | "packageManager": "yarn@1.22.21", 7 | "scripts": { 8 | "build": "turbo build", 9 | "test": "turbo test", 10 | "dev": "turbo dev", 11 | "build:watch": "turbo watch build", 12 | "prettier": "turbo prettier", 13 | "lint": "turbo lint" 14 | }, 15 | "devDependencies": { 16 | "@typescript-eslint/eslint-plugin": "^8.29.0", 17 | "@typescript-eslint/parser": "^8.29.0", 18 | "eslint": "^8.56.0", 19 | "prettier": "^3.2.4", 20 | "ts-node": "^10.9.2", 21 | "turbo": "^2.1.0", 22 | "typescript": "^5.3.3" 23 | }, 24 | "workspaces": [ 25 | "packages/*" 26 | ], 27 | "author": "monday.com AI Team", 28 | "license": "MIT" 29 | } 30 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-dev-tools/index.ts: -------------------------------------------------------------------------------- 1 | import { BaseMondayApiToolConstructor } from '../platform-api-tools/base-monday-api-tool'; 2 | import { GetSprintSummaryTool } from './get-sprint-summary-tool/get-sprint-summary-tool'; 3 | import { GetSprintsMetadataTool } from './get-sprints-metadata-tool/get-sprints-metadata-tool'; 4 | import { GetSprintsBoardsTool } from './get-sprints-boards-tool/get-sprints-boards-tool'; 5 | 6 | export const allMondayDevTools: BaseMondayApiToolConstructor[] = [ 7 | GetSprintsBoardsTool, 8 | GetSprintsMetadataTool, 9 | GetSprintSummaryTool, 10 | ]; 11 | 12 | export * from './get-sprint-summary-tool/get-sprint-summary-tool'; 13 | export * from './get-sprints-metadata-tool/get-sprints-metadata-tool'; 14 | export * from './get-sprints-boards-tool/get-sprints-boards-tool'; 15 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/move-object-tool/move-object-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const updateBoardHierarchy = gql` 4 | mutation updateBoardHierarchy($boardId: ID!, $attributes: UpdateBoardHierarchyAttributesInput!) { 5 | update_board_hierarchy(board_id: $boardId, attributes: $attributes) { 6 | success 7 | message 8 | board { 9 | id 10 | } 11 | } 12 | } 13 | `; 14 | 15 | export const updateOverviewHierarchy = gql` 16 | mutation updateOverviewHierarchy($overviewId: ID!, $attributes: UpdateOverviewHierarchyAttributesInput!) { 17 | update_overview_hierarchy(overview_id: $overviewId, attributes: $attributes) { 18 | success 19 | message 20 | overview { 21 | id 22 | } 23 | } 24 | } 25 | `; 26 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/monday-agent-toolkit.ts: -------------------------------------------------------------------------------- 1 | import { ApiClientConfig } from '@mondaydotcomorg/api'; 2 | import { MondayApiToolContext } from './tools/platform-api-tools/base-monday-api-tool'; 3 | 4 | export enum ToolMode { 5 | API = 'api', 6 | APPS = 'apps', 7 | ATP = 'atp', 8 | } 9 | 10 | export type ToolsConfiguration = { 11 | include?: string[]; 12 | exclude?: string[]; 13 | readOnlyMode?: boolean; 14 | mode?: ToolMode; 15 | enableDynamicApiTools?: boolean | 'only'; 16 | enableToolManager?: boolean; 17 | }; 18 | 19 | export type MondayAgentToolkitConfig = { 20 | mondayApiToken: ApiClientConfig['token']; 21 | mondayApiVersion?: ApiClientConfig['apiVersion']; 22 | mondayApiRequestConfig?: ApiClientConfig['requestConfig']; 23 | toolsConfiguration?: ToolsConfiguration; 24 | context?: MondayApiToolContext; 25 | }; 26 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/update-folder-tool/update-folder-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const updateFolder = gql` 4 | mutation updateFolder( 5 | $folderId: ID! 6 | $name: String 7 | $color: FolderColor 8 | $fontWeight: FolderFontWeight 9 | $customIcon: FolderCustomIcon 10 | $parentFolderId: ID 11 | $workspaceId: ID 12 | $accountProductId: ID 13 | $position: DynamicPosition 14 | ) { 15 | update_folder( 16 | folder_id: $folderId 17 | name: $name 18 | color: $color 19 | font_weight: $fontWeight 20 | custom_icon: $customIcon 21 | parent_folder_id: $parentFolderId 22 | workspace_id: $workspaceId 23 | account_product_id: $accountProductId 24 | position: $position 25 | ) { 26 | id 27 | } 28 | } 29 | `; 30 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/search-tool/search-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getBoards = gql` 4 | query GetBoards($page: Int!, $limit: Int!, $workspace_ids: [ID]) { 5 | boards(page: $page, limit: $limit, workspace_ids: $workspace_ids) { 6 | id 7 | name 8 | url 9 | } 10 | } 11 | `; 12 | 13 | 14 | export const getDocs = gql` 15 | query GetDocs($page: Int!, $limit: Int!, $workspace_ids: [ID]) { 16 | docs(page: $page, limit: $limit, workspace_ids: $workspace_ids) { 17 | id 18 | name 19 | url 20 | } 21 | } 22 | `; 23 | 24 | export const getFolders = gql` 25 | query GetFolders($page: Int!, $limit: Int!, $workspace_ids: [ID]) { 26 | folders(page: $page, limit: $limit, workspace_ids: $workspace_ids) { 27 | id 28 | name 29 | } 30 | } 31 | `; -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/tools/initializing.utils.ts: -------------------------------------------------------------------------------- 1 | import { ApiClient } from '@mondaydotcomorg/api'; 2 | import { Tool } from '../../core/tool'; 3 | import { BaseMondayApiTool, MondayApiToolContext } from '../../core/tools/platform-api-tools/base-monday-api-tool'; 4 | import { BaseMondayAppsTool } from 'src/core/tools/monday-apps-tools/base-tool/base-monday-apps-tool'; 5 | 6 | export const toolFactory = ( 7 | tool: new (...args: any[]) => Tool, 8 | instanceOptions: { apiClient: ApiClient; apiToken: string; context?: MondayApiToolContext }, 9 | ) => { 10 | if (tool.prototype instanceof BaseMondayApiTool) { 11 | return new tool(instanceOptions.apiClient, instanceOptions.apiToken, instanceOptions.context); 12 | } else if (tool.prototype instanceof BaseMondayAppsTool) { 13 | return new tool(instanceOptions.apiToken); 14 | } 15 | return new tool(); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-dev-tools/get-sprint-summary-tool/get-sprint-summary-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getSprintsByIds = gql` 4 | query getSprintsByIds($ids: [ID!]) { 5 | items(ids: $ids) { 6 | id 7 | name 8 | board { 9 | id 10 | } 11 | column_values { 12 | id 13 | type 14 | __typename 15 | ... on TextValue { 16 | value 17 | } 18 | ... on DateValue { 19 | date 20 | } 21 | ... on TimelineValue { 22 | from 23 | to 24 | } 25 | ... on CheckboxValue { 26 | checked 27 | } 28 | ... on DocValue { 29 | file { 30 | doc { 31 | object_id 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | `; 39 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workspace-info-tool/types.ts: -------------------------------------------------------------------------------- 1 | export interface OrganizedWorkspaceInfo { 2 | workspace: { 3 | id: string; 4 | name: string; 5 | description: string; 6 | kind: string; 7 | created_at: string; 8 | state: string; 9 | is_default_workspace: boolean; 10 | owners_subscribers: Array<{ 11 | id: string; 12 | name: string; 13 | email: string; 14 | }>; 15 | }; 16 | folders: Array<{ 17 | id: string; 18 | name: string; 19 | boards: Array<{ 20 | id: string; 21 | name: string; 22 | }>; 23 | docs: Array<{ 24 | id: string; 25 | name: string; 26 | }>; 27 | }>; 28 | root_items: { 29 | boards: Array<{ 30 | id: string; 31 | name: string; 32 | }>; 33 | docs: Array<{ 34 | id: string; 35 | name: string; 36 | }>; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/tests/token.utils.test.ts: -------------------------------------------------------------------------------- 1 | import { normalizeToken } from '../token.utils'; 2 | 3 | describe('normalizeToken', () => { 4 | it('removes Bearer prefix (case-insensitive)', () => { 5 | expect(normalizeToken('Bearer eyJtoken123')).toBe('eyJtoken123'); 6 | expect(normalizeToken('bearer eyJtoken123')).toBe('eyJtoken123'); 7 | expect(normalizeToken('BEARER eyJtoken123')).toBe('eyJtoken123'); 8 | }); 9 | 10 | it('handles token without Bearer prefix and trims whitespace', () => { 11 | expect(normalizeToken(' eyJtoken123 ')).toBe('eyJtoken123'); 12 | expect(normalizeToken('eyJtoken123')).toBe('eyJtoken123'); 13 | }); 14 | 15 | it('handles multiple spaces and edge cases', () => { 16 | expect(normalizeToken('Bearer eyJtoken123')).toBe('eyJtoken123'); 17 | expect(normalizeToken('Bearereytoken123')).toBe('Bearereytoken123'); // no space, not matched 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/time.utils.ts: -------------------------------------------------------------------------------- 1 | const SECOND_IN_MILLISECOND = 1000; 2 | export const NANOSECONDS_PER_MILLISECOND = 1_000_000; 3 | 4 | export enum TIME_IN_SECONDS { 5 | YEAR = 365 * 24 * 60 * 60, 6 | MONTH31Days = 31 * 24 * 60 * 60, 7 | MONTH30Days = 30 * 24 * 60 * 60, 8 | MONTH29Days = 29 * 24 * 60 * 60, 9 | MONTH28Days = 28 * 24 * 60 * 60, 10 | WEEK = 7 * 24 * 60 * 60, 11 | DAY = 24 * 60 * 60, 12 | HOUR = 60 * 60, 13 | MINUTE = 60, 14 | } 15 | 16 | export enum TIME_IN_MILLISECONDS { 17 | YEAR = 365 * 24 * 60 * 60 * SECOND_IN_MILLISECOND, 18 | MONTH31Days = 31 * 24 * 60 * 60 * SECOND_IN_MILLISECOND, 19 | MONTH30Days = 30 * 24 * 60 * 60 * SECOND_IN_MILLISECOND, 20 | MONTH29Days = 29 * 24 * 60 * 60 * SECOND_IN_MILLISECOND, 21 | MONTH28Days = 28 * 24 * 60 * 60 * SECOND_IN_MILLISECOND, 22 | DAY = 24 * 60 * 60 * SECOND_IN_MILLISECOND, 23 | HOUR = 60 * 60 * SECOND_IN_MILLISECOND, 24 | MINUTE = 60 * SECOND_IN_MILLISECOND, 25 | SECOND = SECOND_IN_MILLISECOND, 26 | } 27 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/search-tool/search-tool.types.ts: -------------------------------------------------------------------------------- 1 | export interface SearchResult { 2 | id: string; 3 | title: string; 4 | url?: string; 5 | } 6 | 7 | export interface DataWithFilterInfo { 8 | items: T[]; 9 | wasFiltered: boolean; 10 | } 11 | 12 | export enum ObjectPrefixes { 13 | BOARD = 'board-', 14 | DOCUMENT = 'doc-', 15 | FOLDER = 'folder-', 16 | } 17 | 18 | export enum GlobalSearchType { 19 | BOARD = 'BOARD', 20 | DOCUMENTS = 'DOCUMENTS', 21 | FOLDERS = 'FOLDERS', 22 | 23 | // Why other types are not included: 24 | // FORMS = 'FORMS', // forms are not supported 25 | // USERS = 'USERS', // already supported by list_users_and_teams tool 26 | // TEAMS = 'TEAMS', // already supported by list_users_and_teams tool 27 | // WORKSPACES = 'WORKSPACES', // already supported by list_workspaces tool 28 | // ITEMS = 'ITEMS', // already supported by get_board_items_page tool 29 | // GROUPS = 'GROUPS', // already supported by get_board_info tool 30 | } -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tool.ts: -------------------------------------------------------------------------------- 1 | import { z, ZodRawShape, ZodTypeAny } from 'zod'; 2 | import { ToolAnnotations } from '@modelcontextprotocol/sdk/types'; 3 | import { Executable } from './executable'; 4 | 5 | export type ToolInputType = Input extends ZodRawShape 6 | ? z.objectOutputType 7 | : undefined; 8 | 9 | export type ToolOutputType> = { 10 | content: string; 11 | metadata?: T; 12 | }; 13 | 14 | export enum ToolType { 15 | READ = 'read', 16 | WRITE = 'write', 17 | ALL_API = 'all_api', 18 | } 19 | 20 | export interface Tool = never> 21 | extends Executable, ToolOutputType> { 22 | name: string; 23 | type: ToolType; 24 | annotations: ToolAnnotations; 25 | /** Whether the tool is enabled by default. Defaults to true if not specified. */ 26 | enabledByDefault?: boolean; 27 | 28 | getDescription(): string; 29 | getInputSchema(): Input; 30 | } 31 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-dev-tools/get-sprints-metadata-tool/get-sprints-metadata-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getSprintsBoardItemsWithColumns = gql` 4 | query GetSprintsBoardItemsWithColumns($boardId: ID!, $limit: Int) { 5 | boards(ids: [$boardId]) { 6 | items_page(limit: $limit) { 7 | items { 8 | id 9 | name 10 | column_values { 11 | __typename 12 | id 13 | type 14 | ... on TextValue { 15 | value 16 | } 17 | ... on DocValue { 18 | file { 19 | doc { 20 | object_id 21 | } 22 | } 23 | } 24 | ... on TimelineValue { 25 | from 26 | to 27 | } 28 | ... on CheckboxValue { 29 | checked 30 | } 31 | ... on DateValue { 32 | date 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } 39 | `; 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 monday.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-dev-tools/shared/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GetSprintsBoardItemsWithColumnsQuery, 3 | CheckboxValue, 4 | DateValue, 5 | TimelineValue, 6 | DocValue, 7 | GetRecentBoardsQuery, 8 | } from '../../../../monday-graphql/generated/graphql/graphql'; 9 | import type { MONDAY_DEV_TASK_COLUMN_IDS } from './constants'; 10 | 11 | 12 | export type MondayDevTaskColumnId = (typeof MONDAY_DEV_TASK_COLUMN_IDS)[keyof typeof MONDAY_DEV_TASK_COLUMN_IDS]; 13 | 14 | export type Sprint = NonNullable< 15 | NonNullable[number]>['items_page'] 16 | >['items'][number]; 17 | 18 | export type Board = NonNullable[number]>; 19 | 20 | export interface SprintsBoardPair { 21 | sprintsBoard: { 22 | id: string; 23 | name: string; 24 | workspaceId: string; 25 | workspaceName: string; 26 | }; 27 | tasksBoard: { 28 | id: string; 29 | name: string; 30 | workspaceId: string; 31 | workspaceName: string; 32 | }; 33 | } 34 | 35 | export type { CheckboxValue, DateValue, TimelineValue, DocValue }; 36 | -------------------------------------------------------------------------------- /server.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json", 3 | "name": "com.monday/monday.com", 4 | "description": "MCP server for monday.com integration.", 5 | "repository": { 6 | "url": "https://github.com/mondaycom/mcp", 7 | "source": "github" 8 | }, 9 | "version": "0.0.1", 10 | "remotes": [ 11 | { 12 | "type": "streamable-http", 13 | "url": "https://mcp.monday.com/mcp", 14 | "headers": [ 15 | { 16 | "name": "Authorization", 17 | "description": "monday.com API token (format: 'Bearer your_token_here' or just 'your_token_here')", 18 | "isRequired": false, 19 | "isSecret": true 20 | } 21 | ] 22 | }, 23 | { 24 | "type": "sse", 25 | "url": "https://mcp.monday.com/sse", 26 | "headers": [ 27 | { 28 | "name": "Authorization", 29 | "description": "monday.com API token (format: 'Bearer your_token_here' or just 'your_token_here')", 30 | "isRequired": false, 31 | "isSecret": true 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/dashboard-tools/dashboard-queries.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | /** 4 | * GraphQL queries and mutations for dashboard operations 5 | */ 6 | 7 | export const createDashboard = gql` 8 | mutation CreateDashboard( 9 | $name: String! 10 | $workspace_id: ID! 11 | $board_ids: [ID!]! 12 | $kind: DashboardKind 13 | $board_folder_id: ID 14 | ) { 15 | create_dashboard( 16 | name: $name 17 | workspace_id: $workspace_id 18 | board_ids: $board_ids 19 | kind: $kind 20 | board_folder_id: $board_folder_id 21 | ) { 22 | id 23 | name 24 | workspace_id 25 | kind 26 | board_folder_id 27 | } 28 | } 29 | `; 30 | 31 | export const getAllWidgetsSchema = gql` 32 | query GetAllWidgetsSchema { 33 | all_widgets_schema { 34 | widget_type 35 | schema 36 | } 37 | } 38 | `; 39 | 40 | export const createWidget = gql` 41 | mutation CreateWidget($parent: WidgetParentInput!, $kind: ExternalWidget!, $name: String!, $settings: JSON!) { 42 | create_widget(parent: $parent, kind: $kind, name: $name, settings: $settings) { 43 | id 44 | name 45 | kind 46 | parent { 47 | kind 48 | id 49 | } 50 | } 51 | } 52 | `; 53 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/apps.consts.ts: -------------------------------------------------------------------------------- 1 | export enum AppFeatureType { 2 | AppFeatureStatusColumn = 'AppFeatureStatusColumn', 3 | AppFeatureAccountSettingsView = 'AppFeatureAccountSettingsView', 4 | AppFeatureBoardColumnExtension = 'AppFeatureBoardColumnExtension', 5 | AppFeatureGroupMenuAction = 'AppFeatureGroupMenuAction', 6 | AppFeatureProductView = 'AppFeatureProductView', 7 | AppFeatureWorkspaceView = 'AppFeatureWorkspaceView', 8 | AppFeatureSurfaceView = 'AppFeatureSurfaceView', 9 | AppFeatureModal = 'AppFeatureModal', 10 | AppFeatureDialog = 'AppFeatureDialog', 11 | AppFeatureAdminView = 'AppFeatureAdminView', 12 | AppFeatureDropdownColumn = 'AppFeatureDropdownColumn', 13 | AppFeatureDocActions = 'AppFeatureDocActions', 14 | AppFeatureItemMenuAction = 'AppFeatureItemMenuAction', 15 | AppFeatureItemBatchAction = 'AppFeatureItemBatchAction', 16 | AppFeatureItemView = 'AppFeatureItemView', 17 | AppFeatureBoardView = 'AppFeatureBoardView', 18 | AppFeatureDashboardWidget = 'AppFeatureDashboardWidget', 19 | } 20 | 21 | export enum MondayAppsToolCategory { 22 | APP = 'app', 23 | APP_VERSION = 'app_version', 24 | APP_FEATURE = 'app_feature', 25 | STORAGE = 'storage', 26 | MONDAY_CODE = 'monday_code', 27 | APP_DEVELOPMENT_ASSISTANT = 'app_development_assistant', 28 | } 29 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/utils/args/args.config.ts: -------------------------------------------------------------------------------- 1 | import { ArgConfig } from './args.types.js'; 2 | 3 | export const ARG_CONFIGS: ArgConfig[] = [ 4 | { 5 | name: 'token', 6 | flags: ['--token', '-t'], 7 | description: 'Monday API token', 8 | required: true, 9 | }, 10 | { 11 | name: 'version', 12 | flags: ['--version', '-v'], 13 | description: 'Monday API version', 14 | required: false, 15 | defaultValue: undefined, 16 | }, 17 | { 18 | name: 'readOnlyMode', 19 | flags: ['--read-only', '-ro'], 20 | description: 'Enable read-only mode', 21 | required: false, 22 | defaultValue: false, 23 | }, 24 | { 25 | name: 'mode', 26 | flags: ['--mode', '-m'], 27 | description: 28 | 'Set the mode for tool selection: "api" - API tools only, "apps" - (Beta) Monday Apps tools only, "atp" - ATP server mode with GraphQL exploration', 29 | required: false, 30 | defaultValue: 'api', 31 | }, 32 | { 33 | name: 'enableDynamicApiTools', 34 | flags: ['--enable-dynamic-api-tools', '-edat'], 35 | description: 36 | '(Beta) Enable dynamic API tools. Options: "true" (enables along with other tools), "only" (only dynamic API tools), "false" (disabled). Not supported when using read-only mode.', 37 | required: false, 38 | defaultValue: false, 39 | }, 40 | ]; 41 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workforms-tools/create-form-tool/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { GraphQLDescriptions } from '../workforms.consts'; 3 | import { BoardKind } from '../../../../../monday-graphql/generated/graphql/graphql'; 4 | 5 | export const createFormToolSchema = { 6 | destination_workspace_id: z.string().describe(GraphQLDescriptions.form.args.destinationWorkspaceId), 7 | destination_folder_id: z.string().optional().describe(GraphQLDescriptions.form.args.destinationFolderId), 8 | destination_folder_name: z.string().optional().describe(GraphQLDescriptions.form.args.destinationFolderName), 9 | board_kind: z.nativeEnum(BoardKind).optional().describe(GraphQLDescriptions.form.args.boardKind), 10 | destination_name: z.string().optional().describe(GraphQLDescriptions.form.args.destinationName), 11 | board_owner_ids: z.array(z.string()).optional().describe(GraphQLDescriptions.form.args.boardOwnerIds), 12 | board_owner_team_ids: z.array(z.string()).optional().describe(GraphQLDescriptions.form.args.boardOwnerTeamIds), 13 | board_subscriber_ids: z.array(z.string()).optional().describe(GraphQLDescriptions.form.args.boardSubscriberIds), 14 | board_subscriber_teams_ids: z 15 | .array(z.string()) 16 | .optional() 17 | .describe(GraphQLDescriptions.form.args.boardSubscriberTeamsIds), 18 | }; 19 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/schemas/app-version-schemas.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { MondayApiResponse } from '../../base-tool/base-monday-apps-tool'; 3 | 4 | export interface AppVersionsApiDataResponse extends MondayApiResponse { 5 | appVersions: Array<{ 6 | id: number; 7 | name: string; 8 | appId: number; 9 | versionNumber: string; 10 | status: string; 11 | mondayCodeConfig?: { 12 | isMultiRegion: boolean; 13 | }; 14 | }>; 15 | } 16 | 17 | export interface AppVersionApiDataResponse extends MondayApiResponse { 18 | appVersion: { 19 | id: number; 20 | name: string; 21 | appId: number; 22 | versionNumber: string; 23 | status: string; 24 | mondayCodeConfig?: { 25 | isMultiRegion: boolean; 26 | }; 27 | }; 28 | } 29 | 30 | export const getAppVersionsSchema = z.object({ 31 | appId: z.number().describe('The unique identifier of the app to retrieve version history for. Each app can have multiple versions (draft, live, deprecated). Get app IDs from get_all_apps'), 32 | }); 33 | 34 | export const getAppVersionSchema = z.object({ 35 | versionId: z.number().describe('The unique identifier of the specific app version to retrieve. Version IDs are returned from get_app_versions and represent individual snapshots of your app configuration'), 36 | }); 37 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/full-board-data-tool/full-board-data.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getBoardDataQuery = gql` 4 | query getBoardData($boardId: ID!, $itemsLimit: Int!) { 5 | boards(ids: [$boardId]) { 6 | id 7 | name 8 | items_page(limit: $itemsLimit) { 9 | items { 10 | id 11 | name 12 | column_values { 13 | id 14 | text 15 | type 16 | value 17 | ... on PeopleValue { 18 | persons_and_teams { 19 | id 20 | kind 21 | } 22 | } 23 | } 24 | updates { 25 | id 26 | creator_id 27 | text_body 28 | created_at 29 | replies { 30 | id 31 | text_body 32 | created_at 33 | creator_id 34 | } 35 | } 36 | } 37 | } 38 | columns { 39 | id 40 | title 41 | type 42 | settings 43 | } 44 | } 45 | } 46 | `; 47 | 48 | export const getUsersByIdsQuery = gql` 49 | query getUsersByIds($userIds: [ID!]!) { 50 | users(ids: $userIds) { 51 | id 52 | name 53 | photo_tiny 54 | } 55 | } 56 | `; 57 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/index.ts: -------------------------------------------------------------------------------- 1 | import { MondayAppsToolType } from './base-tool/base-monday-apps-tool'; 2 | import { MondayAppsToolCategory } from './consts/apps.consts'; 3 | import { storageTools } from './storage'; 4 | import { appTools } from './app'; 5 | import { appVersionTools } from './app-version'; 6 | import { appFeatureTools } from './app-feature'; 7 | import { codeTools } from './monday-code'; 8 | import { appDevelopmentAssistantTools } from './app-development-assistant'; 9 | 10 | export const mondayAppsTools = { 11 | [MondayAppsToolCategory.STORAGE]: storageTools, 12 | [MondayAppsToolCategory.APP]: appTools, 13 | [MondayAppsToolCategory.APP_VERSION]: appVersionTools, 14 | [MondayAppsToolCategory.APP_FEATURE]: appFeatureTools, 15 | [MondayAppsToolCategory.MONDAY_CODE]: codeTools, 16 | [MondayAppsToolCategory.APP_DEVELOPMENT_ASSISTANT]: appDevelopmentAssistantTools, 17 | }; 18 | 19 | export const allMondayAppsTools: MondayAppsToolType[] = [ 20 | ...storageTools, 21 | ...appTools, 22 | ...appVersionTools, 23 | ...appFeatureTools, 24 | ...codeTools, 25 | ...appDevelopmentAssistantTools, 26 | ]; 27 | 28 | export * from './storage'; 29 | export * from './app'; 30 | export * from './app-version'; 31 | export * from './app-feature'; 32 | export * from './monday-code'; 33 | export * from './app-development-assistant'; 34 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-development-assistant/schemas/assistant-schemas.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { MondayApiResponse } from '../../base-tool/base-monday-apps-tool'; 3 | 4 | export enum AppDevelopmentContextType { 5 | FULL = 'full', 6 | QUICK_START = 'quick_start', 7 | SDK_REFERENCE = 'sdk_reference', 8 | MONDAY_CODE_DEPLOYMENT = 'monday_code_deployment', 9 | BEST_PRACTICES = 'best_practices', 10 | TROUBLESHOOTING = 'troubleshooting', 11 | } 12 | 13 | export interface AppDevelopmentContextResponse extends MondayApiResponse { 14 | contextType: AppDevelopmentContextType; 15 | content: string; 16 | } 17 | 18 | export const getAppDevelopmentContextSchema = z.object({ 19 | contextType: z 20 | .nativeEnum(AppDevelopmentContextType) 21 | .optional() 22 | .default(AppDevelopmentContextType.FULL) 23 | .describe( 24 | 'The type of development context to retrieve. Options: "full" (complete guide), "quick_start" (getting started), "sdk_reference" (SDK usage), "monday_code_deployment" (deployment guide), "best_practices" (coding standards), "troubleshooting" (common issues). Defaults to "full"', 25 | ), 26 | specificTopic: z 27 | .string() 28 | .optional() 29 | .describe( 30 | 'Optional specific topic to focus on within the context (e.g., "board views", "custom columns", "integrations", "OAuth", "storage API")', 31 | ), 32 | }); 33 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/string.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Removes all non-alphanumeric characters from a string, keeping only letters and digits. 3 | * 4 | * This function removes whitespaces, special characters (like $, ', ", %, etc.), and punctuation, 5 | * while preserving all Unicode letters (including accented characters like ł, é, ñ) and digits (0-9). 6 | * 7 | * **Regex Pattern Breakdown:** `/[^\p{L}\d]/gu` 8 | * - `[^ ... ]` - Negated character class (matches anything NOT inside the brackets) 9 | * - `\p{L}` - Unicode property escape matching any letter from any language 10 | * - Includes: a-z, A-Z, ł, é, ñ, 漢, א, etc. 11 | * - `\d` - Matches any digit (0-9) 12 | * - `g` - Global flag: replace all occurrences in the string 13 | * - `u` - Unicode flag: enables Unicode property escapes (\p{}) 14 | * 15 | * @param str - The input string to clean 16 | * @returns A new string containing only letters and digits 17 | * 18 | * @example 19 | * ```typescript 20 | * cleanAlphanumeric("Hello World! 123") // "HelloWorld123" 21 | * cleanAlphanumeric("łódź 50%") // "łódź50" 22 | * cleanAlphanumeric("Price: $99.99") // "Price9999" 23 | * cleanAlphanumeric("café, naïve & résumé") // "cafénaïverésumé" 24 | * cleanAlphanumeric("Test$123'abc\"") // "Test123abc" 25 | * ``` 26 | */ 27 | export const normalizeString = (str: string): string => { 28 | return str.toLocaleLowerCase().replace(/[^\p{L}\d]/gu, ''); 29 | } -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-doc-tool/create-doc-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | // Get item board and its columns (used to discover or create a doc column for item-attached docs) 4 | export const getItemBoard = gql` 5 | query getItemBoard($itemId: ID!) { 6 | items(ids: [$itemId]) { 7 | id 8 | board { 9 | id 10 | columns { 11 | id 12 | type 13 | } 14 | } 15 | } 16 | } 17 | `; 18 | 19 | // Create a new monday doc (works for both workspace and board/item locations via CreateDocInput) 20 | export const createDoc = gql` 21 | mutation createDoc($location: CreateDocInput!) { 22 | create_doc(location: $location) { 23 | id 24 | url 25 | name 26 | } 27 | } 28 | `; 29 | 30 | // Add markdown content to an existing monday doc (API version 2025-10) 31 | export const addContentToDocFromMarkdown = gql` 32 | mutation addContentToDocFromMarkdown($docId: ID!, $markdown: String!, $afterBlockId: String) { 33 | add_content_to_doc_from_markdown(docId: $docId, markdown: $markdown, afterBlockId: $afterBlockId) { 34 | success 35 | block_ids 36 | error 37 | } 38 | } 39 | `; 40 | 41 | // Update the name/title of an existing monday doc (API version 2025-10) 42 | export const updateDocName = gql` 43 | mutation updateDocName($docId: ID!, $name: String!) { 44 | update_doc_name(docId: $docId, name: $name) 45 | } 46 | `; 47 | 48 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/delete-item-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { DeleteItemMutation, DeleteItemMutationVariables } from 'src/monday-graphql/generated/graphql/graphql'; 3 | import { deleteItem } from 'src/monday-graphql/queries.graphql'; 4 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 5 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 6 | 7 | export const deleteItemToolSchema = { 8 | itemId: z.number(), 9 | }; 10 | 11 | export class DeleteItemTool extends BaseMondayApiTool { 12 | name = 'delete_item'; 13 | type = ToolType.WRITE; 14 | annotations = createMondayApiAnnotations({ 15 | title: 'Delete Item', 16 | readOnlyHint: false, 17 | destructiveHint: true, 18 | idempotentHint: false, 19 | }); 20 | 21 | getDescription(): string { 22 | return 'Delete an item'; 23 | } 24 | 25 | getInputSchema(): typeof deleteItemToolSchema { 26 | return deleteItemToolSchema; 27 | } 28 | 29 | protected async executeInternal(input: ToolInputType): Promise> { 30 | const variables: DeleteItemMutationVariables = { 31 | id: input.itemId.toString(), 32 | }; 33 | 34 | const res = await this.mondayApi.request(deleteItem, variables); 35 | 36 | return { 37 | content: `Item ${res.delete_item?.id} successfully deleted`, 38 | }; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app/schemas/app-schemas.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { MondayApiResponse } from '../../base-tool/base-monday-apps-tool'; 3 | 4 | export interface AppApiDataResponse extends MondayApiResponse { 5 | apps: Array<{ 6 | id: number; 7 | name: string; 8 | mondayCodeConfig?: { 9 | isMultiRegion: boolean; 10 | }; 11 | }>; 12 | } 13 | 14 | export interface PromoteAppResponse extends MondayApiResponse { 15 | appId: number; 16 | } 17 | 18 | export const promoteAppSchema = z.object({ 19 | appId: z.number().describe('The unique identifier of the app to promote. You can get this from the get_all_apps tool'), 20 | versionId: z 21 | .number() 22 | .optional() 23 | .describe('The specific version ID to promote to live/production. If not provided, the latest draft version will be automatically promoted. Use get_app_versions to find available version IDs'), 24 | }); 25 | 26 | export interface CreateAppResponse extends MondayApiResponse { 27 | app: { 28 | id: number; 29 | name: string; 30 | }; 31 | app_version: { 32 | id: number; 33 | name: string; 34 | }; 35 | } 36 | 37 | export const createPlainAppSchema = z.object({ 38 | name: z.string().describe('The display name for your app. This will be visible to users in the monday.com marketplace and UI. Should be clear and descriptive'), 39 | description: z.string().optional().describe('An optional detailed description of what your app does and its main features. This helps users understand the app\'s purpose'), 40 | }); 41 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/monday-api-mcp", 3 | "version": "1.13.0", 4 | "description": "MCP server for using the monday.com API", 5 | "mcpName": "com.monday/monday.com", 6 | "license": "MIT", 7 | "bin": { 8 | "mcp-server-monday-api": "dist/index.js" 9 | }, 10 | "main": "dist/lib.js", 11 | "files": [ 12 | "dist" 13 | ], 14 | "scripts": { 15 | "build": "tsc && shx chmod +x dist/*.js", 16 | "watch": "tsc --watch", 17 | "start": "yarn build && node dist/index.js", 18 | "test": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js --config jest.config.js", 19 | "prettier": "prettier --write \"src/**/*.ts\" --ignore-path \"../../.prettierignore\"", 20 | "lint": "eslint --fix \"src/**/*.ts\" --ignore-path \"../../.eslintignore\"" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/mondaycom/monday-ai/tree/master/packages/monday-api-mcp" 25 | }, 26 | "dependencies": { 27 | "@modelcontextprotocol/sdk": "^1.13.2", 28 | "@mondaydotcomorg/agent-toolkit": "*", 29 | "@mondaydotcomorg/atp-client": "^0.19.13", 30 | "@mondaydotcomorg/atp-mcp-adapter": "^0.19.17", 31 | "@mondaydotcomorg/atp-server": "^0.19.17", 32 | "dotenv": "^16.4.7", 33 | "zod": "^3.25.0" 34 | }, 35 | "devDependencies": { 36 | "@types/jest": "^29.5.12", 37 | "eslint": "^8.56.0", 38 | "jest": "^29.7.0", 39 | "prettier": "^3.2.4", 40 | "shx": "^0.3.4", 41 | "ts-jest": "^29.3.1", 42 | "typescript": "^5.6.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-board-items-page-tool/get-board-items-page-tool.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getBoardItemsPage = gql` 4 | fragment ItemDataFragment on Item { 5 | id 6 | name 7 | created_at 8 | updated_at 9 | column_values(ids: $columnIds) @include(if: $includeColumns) { 10 | id 11 | type 12 | text 13 | value 14 | 15 | ... on FormulaValue { 16 | display_value 17 | } 18 | 19 | ... on BoardRelationValue { 20 | linked_items { 21 | id 22 | name 23 | board { 24 | id 25 | name 26 | } 27 | } 28 | } 29 | } 30 | } 31 | 32 | query GetBoardItemsPage($boardId: ID!, $limit: Int, $cursor: String, $includeColumns: Boolean!, $columnIds: [String!], $queryParams: ItemsQuery, $includeSubItems: Boolean!) { 33 | boards(ids: [$boardId]) { 34 | id 35 | name 36 | items_page(limit: $limit, cursor: $cursor, query_params: $queryParams) { 37 | items { 38 | ...ItemDataFragment 39 | 40 | subitems @include(if: $includeSubItems) { 41 | ...ItemDataFragment 42 | } 43 | } 44 | cursor 45 | } 46 | } 47 | } 48 | `; 49 | 50 | export const smartSearchGetBoardItemIds = gql` 51 | query SmartSearchBoardItemIds($searchTerm: String!, $board_ids: [ID!]) { 52 | search_items(board_ids: $board_ids, query: $searchTerm, size: 100) { 53 | results { 54 | data { 55 | id 56 | } 57 | } 58 | } 59 | } 60 | `; -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/error.utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * GraphQL error response structure 3 | */ 4 | interface GraphQLErrorResponse { 5 | response?: { 6 | errors?: Array<{ message: string }>; 7 | }; 8 | } 9 | 10 | /** 11 | * Rethrows an error with a formatted message, extracting GraphQL errors if available. 12 | * 13 | * This utility handles two types of errors: 14 | * 1. GraphQL errors - extracts and joins error messages from response.errors 15 | * 2. Standard errors - uses the error message or falls back to 'Unknown error' 16 | * 17 | * @param error - The caught error (can be Error, GraphQL error response, or unknown) 18 | * @param operation - Description of the operation that failed (e.g., "create item", "update board") 19 | * @throws Always throws an Error with formatted message "Failed to {operation}: {error details}" 20 | * 21 | * @example 22 | * ```typescript 23 | * try { 24 | * await mondayApi.createItem(...); 25 | * } catch (error) { 26 | * rethrowWithContext(error, 'create item'); 27 | * } 28 | * ``` 29 | */ 30 | export function rethrowWithContext(error: unknown, operation: string): never { 31 | // Try to extract GraphQL errors from the response 32 | const graphQLErrors = (error as GraphQLErrorResponse)?.response?.errors 33 | ?.map((e) => e.message) 34 | ?.join(', '); 35 | 36 | if (graphQLErrors) { 37 | throw new Error(`Failed to ${operation}: ${graphQLErrors}`); 38 | } 39 | 40 | // Fallback to standard error message 41 | const errorMessage = error instanceof Error ? error.message : 'Unknown error'; 42 | throw new Error(`Failed to ${operation}: ${errorMessage}`); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /packages/agent-toolkit/LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, monday.com 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; 3 | import { MondayAgentToolkit } from '@mondaydotcomorg/agent-toolkit/mcp'; 4 | import { ToolMode } from '@mondaydotcomorg/agent-toolkit/core'; 5 | import { parseArgs, validateArgs } from './utils/args/args.service.js'; 6 | import { runAtpMcpServer } from './domains/atp/index.js'; 7 | import dotenv from 'dotenv'; 8 | 9 | dotenv.config(); 10 | 11 | async function runMcpServer(validatedArgs: ReturnType): Promise { 12 | const toolkit = new MondayAgentToolkit({ 13 | mondayApiToken: validatedArgs.token, 14 | mondayApiVersion: validatedArgs.version, 15 | mondayApiRequestConfig: {}, 16 | toolsConfiguration: { 17 | readOnlyMode: validatedArgs.readOnlyMode, 18 | enableDynamicApiTools: validatedArgs.enableDynamicApiTools, 19 | mode: validatedArgs.mode, 20 | enableToolManager: false, 21 | }, 22 | }); 23 | 24 | const transport = new StdioServerTransport(); 25 | await toolkit.connect(transport); 26 | } 27 | 28 | async function runServer(): Promise { 29 | const args = process.argv.slice(2); 30 | const parsedArgs = parseArgs(args); 31 | const validatedArgs = validateArgs(parsedArgs); 32 | 33 | if (validatedArgs.mode === ToolMode.ATP) { 34 | await runAtpMcpServer({ 35 | token: validatedArgs.token, 36 | version: validatedArgs.version, 37 | }); 38 | } else { 39 | await runMcpServer(validatedArgs); 40 | } 41 | } 42 | 43 | runServer().catch((error) => { 44 | console.error('Fatal error in main():', error); 45 | process.exit(1); 46 | }); 47 | -------------------------------------------------------------------------------- /packages/agent-toolkit/rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import typescript from '@rollup/plugin-typescript'; 4 | import terser from '@rollup/plugin-terser'; 5 | import json from '@rollup/plugin-json'; 6 | import del from 'rollup-plugin-delete'; 7 | import dts from 'rollup-plugin-dts'; 8 | 9 | const subPaths = ['mcp', 'core', 'openai']; 10 | 11 | const subpathConfigs = subPaths.map((dir) => ({ 12 | input: `src/${dir}/index.ts`, 13 | output: [ 14 | { 15 | file: `dist/cjs/${dir}/index.js`, 16 | format: 'cjs', 17 | sourcemap: true, 18 | }, 19 | { 20 | file: `dist/esm/${dir}/index.js`, 21 | format: 'es', 22 | sourcemap: true, 23 | }, 24 | ], 25 | plugins: [ 26 | del({ targets: [`dist/cjs/${dir}/*`, `dist/esm/${dir}/*`] }), 27 | resolve({ 28 | preferBuiltins: true, 29 | }), 30 | commonjs(), 31 | typescript({ 32 | tsconfig: './tsconfig.json', 33 | declaration: true, 34 | declarationDir: `dist/temp/${dir}`, 35 | rootDir: 'src', 36 | }), 37 | json(), 38 | terser(), 39 | ].filter(Boolean), 40 | external: ['@mondaydotcomorg/api', 'zod', 'zod-to-json-schema'], 41 | })); 42 | 43 | // Subpath types 44 | const subpathTypesConfigs = subPaths.map((dir) => ({ 45 | input: `src/${dir}/index.ts`, 46 | output: [ 47 | { file: `dist/cjs/${dir}/index.d.ts`, format: 'es' }, 48 | { file: `dist/esm/${dir}/index.d.ts`, format: 'es' }, 49 | ], 50 | plugins: [dts(), del({ targets: [`dist/cjs/${dir}/temp`, `dist/esm/${dir}/temp`] })], 51 | })); 52 | 53 | export default [...subpathConfigs, ...subpathTypesConfigs]; 54 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/tests/string.utils.test.ts: -------------------------------------------------------------------------------- 1 | import { normalizeString } from '../string.utils'; 2 | 3 | describe('normalizeString', () => { 4 | it('converts to lowercase and removes spaces and punctuation', () => { 5 | expect(normalizeString('Hello World! 123')).toBe('helloworld123'); 6 | }); 7 | 8 | it('preserves Unicode letters and digits, removes symbols', () => { 9 | expect(normalizeString('ŁÓDŹ 50%')).toBe('łódź50'); 10 | }); 11 | 12 | it('removes emojis and symbols while keeping letters and digits', () => { 13 | expect(normalizeString('foo😀bar—baz_123')).toBe('foobarbaz123'); 14 | }); 15 | 16 | it('preserves accented characters', () => { 17 | expect(normalizeString('café, naïve & résumé')).toBe('cafénaïverésumé'); 18 | }); 19 | 20 | it('strips currency symbols and punctuation inside numbers', () => { 21 | expect(normalizeString('Price: $99.99')).toBe('price9999'); 22 | }); 23 | 24 | it('handles empty string', () => { 25 | expect(normalizeString('')).toBe(''); 26 | }); 27 | 28 | it('returns empty string when input contains only symbols', () => { 29 | expect(normalizeString("$%^&*()—_+=[]{}|;:'\"<>,.?/`~")) 30 | .toBe(''); 31 | }); 32 | 33 | it('preserves CJK characters', () => { 34 | expect(normalizeString('漢字テスト123!')).toBe('漢字テスト123'); 35 | }); 36 | 37 | it('preserves RTL scripts (Hebrew/Arabic)', () => { 38 | expect(normalizeString('שלום123!')).toBe('שלום123'); 39 | expect(normalizeString('مرحبا 456?')).toBe('مرحبا456'); 40 | }); 41 | 42 | it('removes quotes and special punctuation', () => { 43 | expect(normalizeString('Test$123\'abc"')) 44 | .toBe('test123abc'); 45 | }); 46 | }); 47 | 48 | 49 | -------------------------------------------------------------------------------- /.github/workflows/npm_publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to NPM 2 | on: 3 | workflow_dispatch: 4 | push: 5 | tags: 6 | - 'v*.*.*' 7 | branches: 8 | - master 9 | 10 | jobs: 11 | publish-npm: 12 | environment: prod 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | fetch-depth: 0 18 | 19 | - uses: actions/setup-node@v3 20 | with: 21 | node-version: '20.18.1' 22 | registry-url: https://registry.npmjs.org/ 23 | 24 | - name: Install Yarn 25 | run: npm install -g yarn@1.22.21 26 | 27 | - run: yarn install 28 | 29 | # Build packages using Turborepo 30 | - name: Build packages 31 | run: yarn build 32 | 33 | - name: Get changed packages 34 | id: changed 35 | run: | 36 | CHANGED=$(git diff --name-only HEAD^ HEAD | grep "^packages/" | cut -d/ -f2 | sort -u | jq -R -s -c 'split("\n")[:-1]') 37 | echo "packages=$CHANGED" >> $GITHUB_OUTPUT 38 | 39 | - name: Configure Git 40 | run: | 41 | git config --global user.email "github-actions@github.com" 42 | git config --global user.name "GitHub Actions" 43 | 44 | - name: Publish changed packages 45 | if: steps.changed.outputs.packages != '[]' 46 | run: | 47 | echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" > .npmrc 48 | PACKAGES=$(echo '${{ steps.changed.outputs.packages }}' | jq -r '.[]') 49 | for PKG in $PACKAGES; do 50 | cd packages/$PKG 51 | yarn publish --access public 52 | cd ../.. 53 | done 54 | env: 55 | NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} 56 | -------------------------------------------------------------------------------- /.github/workflows/version_check.yml: -------------------------------------------------------------------------------- 1 | name: Version Check 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - labeled 7 | 8 | jobs: 9 | version-preview: 10 | if: github.event.action == 'labeled' 11 | runs-on: ubuntu-latest 12 | permissions: 13 | pull-requests: write 14 | contents: read 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Preview version bump 21 | id: preview 22 | uses: haya14busa/action-bumpr@v1 23 | with: 24 | github_token: ${{ secrets.GITHUB_TOKEN }} 25 | dry_run: true 26 | 27 | - name: Comment on PR 28 | uses: actions/github-script@v7 29 | with: 30 | script: | 31 | const labels = context.payload.pull_request.labels.map(label => label.name); 32 | const versionLabels = labels.filter(label => label.startsWith('bump:')); 33 | 34 | if (versionLabels.length > 0) { 35 | const versionType = versionLabels[0].replace('bump:', ''); 36 | const currentVersion = '${{ steps.preview.outputs.current_version }}' || 'current'; 37 | const nextVersion = '${{ steps.preview.outputs.next_version }}' || 'unknown'; 38 | 39 | await github.rest.issues.createComment({ 40 | issue_number: context.issue.number, 41 | owner: context.repo.owner, 42 | repo: context.repo.repo, 43 | body: `🏷️ **Version Bump Preview**\n\n**Type:** ${versionType}\n**Current:** ${currentVersion}\n**Next:** ${nextVersion}\n\n✅ This is just a preview! The actual version bump will happen when this PR is merged.` 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/schemas/storage-schemas.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { MondayApiResponse } from '../../base-tool/base-monday-apps-tool'; 3 | 4 | export interface StorageRecordsResponse extends MondayApiResponse { 5 | term: string; 6 | records: Array<{ 7 | key: string; 8 | value: string; 9 | backendOnly: boolean; 10 | }>; 11 | cursor?: string; 12 | } 13 | 14 | export const searchStorageRecordsSchema = z.object({ 15 | appId: z.number().describe('The unique identifier of the app whose storage you want to search. Get this from get_all_apps'), 16 | accountId: z.number().describe('The monday.com account ID to search storage within. Storage is isolated per account. Get this from the monday.com platform API'), 17 | term: z.string().describe('The search term to query against storage record keys and values. Supports partial matching to help find relevant records'), 18 | cursor: z.string().optional().describe('Pagination cursor returned from a previous search. Use this to fetch the next page of results when there are many matching records'), 19 | }); 20 | 21 | export interface ExportStorageDataResponse extends MondayApiResponse { 22 | downloadUrl?: string; 23 | } 24 | 25 | export const exportStorageDataSchema = z.object({ 26 | appId: z.number().describe('The unique identifier of the app whose storage data you want to export. Get this from get_all_apps'), 27 | accountId: z.number().describe('The monday.com account ID to export storage from. Each account has isolated storage data'), 28 | fileFormat: z.enum(['JSON', 'CSV']).optional().describe('The desired export format. JSON preserves data structure and is best for re-importing; CSV is easier to view in spreadsheet applications. Defaults to JSON if not specified'), 29 | }); 30 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/schemas/code-schemas.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { MondayApiResponse } from '../../base-tool/base-monday-apps-tool'; 3 | 4 | export interface DeploymentStatusResponse extends MondayApiResponse { 5 | status?: string; 6 | creationDate?: string; 7 | activeFromVersionId?: number; 8 | } 9 | 10 | export const getDeploymentStatusSchema = z.object({ 11 | appVersionId: z.number().describe('The unique identifier of the app version to check deployment status for. Use this after running mapps code:push to monitor the deployment progress and verify it completed successfully'), 12 | }); 13 | 14 | export interface TunnelTokenResponse extends MondayApiResponse { 15 | token: string; 16 | domain: string; 17 | } 18 | 19 | export interface EnvVarResponse extends MondayApiResponse { 20 | success?: boolean; 21 | } 22 | 23 | export const setEnvVarSchema = z.object({ 24 | appId: z.number().describe('The unique identifier of the app to manage environment variables for. Environment variables are app-level settings available to all versions'), 25 | key: z.string().describe('The environment variable key/name (e.g., API_KEY, DATABASE_URL, DEBUG_MODE). Use uppercase with underscores by convention'), 26 | value: z.string().describe('The value to set for this environment variable. Can be any string (API keys, URLs, configuration values, etc.). Values are stored securely and available at runtime'), 27 | }); 28 | 29 | export interface EnvVarKeysResponse extends MondayApiResponse { 30 | keys: string[]; 31 | } 32 | 33 | export const listEnvVarKeysSchema = z.object({ 34 | appId: z.number().describe('The unique identifier of the app to list environment variable keys for. Returns only the keys (not values) for security. Get app IDs from get_all_apps'), 35 | }); 36 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/move-item-to-group-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | MoveItemToGroupMutation, 4 | MoveItemToGroupMutationVariables, 5 | } from 'src/monday-graphql/generated/graphql/graphql'; 6 | import { moveItemToGroup } from 'src/monday-graphql/queries.graphql'; 7 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 8 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 9 | 10 | export const moveItemToGroupToolSchema = { 11 | itemId: z.number().describe('The id of the item to which the update will be added'), 12 | groupId: z.string().describe('The id of the group to which the item will be moved'), 13 | }; 14 | 15 | export class MoveItemToGroupTool extends BaseMondayApiTool { 16 | name = 'move_item_to_group'; 17 | type = ToolType.WRITE; 18 | annotations = createMondayApiAnnotations({ 19 | title: 'Move Item to Group', 20 | readOnlyHint: false, 21 | destructiveHint: false, 22 | idempotentHint: true, 23 | }); 24 | 25 | getDescription(): string { 26 | return 'Move an item to a group in a monday.com board'; 27 | } 28 | 29 | getInputSchema(): typeof moveItemToGroupToolSchema { 30 | return moveItemToGroupToolSchema; 31 | } 32 | 33 | protected async executeInternal( 34 | input: ToolInputType, 35 | ): Promise> { 36 | const variables: MoveItemToGroupMutationVariables = { 37 | itemId: input.itemId.toString(), 38 | groupId: input.groupId, 39 | }; 40 | 41 | const res = await this.mondayApi.request(moveItemToGroup, variables); 42 | 43 | return { 44 | content: `Item ${res.move_item_to_group?.id} successfully moved to group ${input.groupId}`, 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workforms-tools/get-form-tool/index.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { GetFormQuery, GetFormQueryVariables } from '../../../../../monday-graphql/generated/graphql/graphql'; 3 | import { getForm } from '../workforms.graphql'; 4 | import { ToolInputType, ToolOutputType, ToolType } from '../../../../tool'; 5 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../../base-monday-api-tool'; 6 | import { getFormToolSchema } from './schema'; 7 | 8 | export class GetFormTool extends BaseMondayApiTool { 9 | name = 'get_form'; 10 | type = ToolType.READ; 11 | annotations = createMondayApiAnnotations({ 12 | title: 'Get Form', 13 | readOnlyHint: true, 14 | destructiveHint: false, 15 | }); 16 | 17 | getDescription(): string { 18 | return 'Get a monday.com form by its form token. Form tokens can be extracted from the form’s url. Given a form url, such as https://forms.monday.com/forms/abc123def456ghi789?r=use1, the token is the alphanumeric string that appears right after /forms/ and before the ?. In the example, the token is abc123def456ghi789.'; 19 | } 20 | 21 | getInputSchema(): typeof getFormToolSchema { 22 | return getFormToolSchema; 23 | } 24 | 25 | protected async executeInternal(input: ToolInputType): Promise> { 26 | const variables: GetFormQueryVariables = { 27 | formToken: input.formToken, 28 | }; 29 | 30 | const res = await this.mondayApi.request(getForm, variables); 31 | 32 | if (!res.form) { 33 | return { 34 | content: `Form with token ${input.formToken} not found or you don't have access to it.`, 35 | }; 36 | } 37 | 38 | return { 39 | content: `The form with the token ${input.formToken} is: ${JSON.stringify(res.form, null, 2)}`, 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MONDAY.md: -------------------------------------------------------------------------------- 1 | # monday.com Gemini CLI Extension 2 | 3 | ## Overview 4 | 5 | This extension connects Gemini CLI to monday.com's hosted Model Context Protocol (MCP) server at `https://mcp.monday.com/mcp`. 6 | 7 | Prior to using tools from the monday.com MCP server you must authenticate. This is done by running `/mcp auth monday` which will open a OAuth flow in your browser. 8 | 9 | ## Custom Commands 10 | 11 | Several custom slash commands are available to interact with monday.com. These commands are shortcuts for common monday.com tasks. 12 | 13 | They all are prefixed with `/monday:`: 14 | 15 | - **/monday:analyze-board**: Analyze a monday.com board to provide insights (requires Board ID). 16 | - **/monday:create-item**: Create a new item in a monday.com board (requires Board ID and Item Name). 17 | - **/monday:update-item**: Update a monday.com item (task, bug, epic, etc.) with a comment or change column values (requires Item ID and text of update for comment, or Board ID, Item ID, and column key-value pairs for column updates). 18 | - **/monday:save-my-user-id**: Fetches the current monday.com user ID and saves it to long-term memory. 19 | - **/monday:sprint-summary**: Get a comprehensive summary of a monday.com sprint (requires Sprint ID). 20 | 21 | ## Troubleshooting 22 | 23 | Before using the monday.com MCP server, you need an admin to install the Monday MCP app in your monday.com account 24 | from the marketplace: 25 | 26 | 1. Visit [monday MCP app in the marketplace](https://monday.com/marketplace/listing/10000806/monday-mcp) 27 | 2. Click "Install" and follow the instructions to add it to your account 28 | 29 | If you have already installed the app, below are some common troubleshooting 30 | steps: 31 | 32 | - Run `/mcp list` to confirm the `monday` server is connected. 33 | - Run `/mcp desc monday` to see detailed overview of available tools. 34 | - Run `/mcp auth monday` to authenticate with monday.com. 35 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-board-info/get-board-info.graphql.ts: -------------------------------------------------------------------------------- 1 | import { gql } from 'graphql-request'; 2 | 3 | export const getBoardInfo = gql` 4 | query GetBoardInfo($boardId: ID!) { 5 | boards(ids: [$boardId]) { 6 | # Basic Board Metadata 7 | id 8 | name 9 | description 10 | state 11 | board_kind 12 | permissions 13 | url 14 | 15 | # Timestamps 16 | updated_at 17 | 18 | # Board Configuration 19 | item_terminology 20 | items_count 21 | items_limit 22 | 23 | # Creator Information 24 | creator { 25 | id 26 | name 27 | email 28 | } 29 | 30 | # Workspace Information 31 | workspace { 32 | id 33 | name 34 | kind 35 | description 36 | } 37 | 38 | board_folder_id 39 | 40 | # All Columns with Full Metadata 41 | columns { 42 | id 43 | title 44 | description 45 | type 46 | settings 47 | } 48 | 49 | # All Groups with Metadata 50 | groups { 51 | id 52 | title 53 | } 54 | 55 | # Board Owners (Individual Users) 56 | owners { 57 | id 58 | name 59 | } 60 | 61 | # Team Owners 62 | team_owners { 63 | id 64 | name 65 | picture_url 66 | } 67 | 68 | # Board Tags 69 | tags { 70 | id 71 | name 72 | } 73 | 74 | # Top Group (default group) 75 | top_group { 76 | id 77 | } 78 | } 79 | } 80 | `; 81 | 82 | export const getBoardInfoJustColumns = gql` 83 | query GetBoardInfoJustColumns($boardId: ID!) { 84 | boards(ids: [$boardId]) { 85 | columns { 86 | id 87 | title 88 | description 89 | type 90 | settings 91 | } 92 | 93 | } 94 | } 95 | `; 96 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/fetch-custom-activity-tool.ts: -------------------------------------------------------------------------------- 1 | import { FetchCustomActivityQuery } from 'src/monday-graphql/generated/graphql/graphql'; 2 | import { fetchCustomActivity } from '../../../monday-graphql/queries.graphql'; 3 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 4 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 5 | 6 | export const fetchCustomActivityToolSchema = {}; 7 | 8 | export class FetchCustomActivityTool extends BaseMondayApiTool { 9 | name = 'fetch_custom_activity'; 10 | type = ToolType.READ; 11 | annotations = createMondayApiAnnotations({ 12 | title: 'Fetch Custom Activities', 13 | readOnlyHint: true, 14 | destructiveHint: false, 15 | idempotentHint: true, 16 | }); 17 | 18 | getDescription(): string { 19 | return 'Get custom activities from the E&A app'; 20 | } 21 | 22 | getInputSchema(): typeof fetchCustomActivityToolSchema { 23 | return fetchCustomActivityToolSchema; 24 | } 25 | 26 | protected async executeInternal( 27 | input: ToolInputType, 28 | ): Promise> { 29 | const res = await this.mondayApi.request(fetchCustomActivity); 30 | 31 | if (!res.custom_activity || res.custom_activity.length === 0) { 32 | return { 33 | content: 'No custom activities found', 34 | }; 35 | } 36 | 37 | const activities = res.custom_activity.map((activity) => { 38 | return { 39 | id: activity.id, 40 | name: activity.name, 41 | color: activity.color, 42 | icon_id: activity.icon_id, 43 | type: activity.type, 44 | }; 45 | }); 46 | 47 | return { 48 | content: `Found ${activities.length} custom activities: ${JSON.stringify(activities, null, 2)}`, 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-board-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | BoardKind, 4 | CreateBoardMutation, 5 | CreateBoardMutationVariables, 6 | } from '../../../monday-graphql/generated/graphql/graphql'; 7 | import { createBoard } from '../../../monday-graphql/queries.graphql'; 8 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 9 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 10 | 11 | export const createBoardToolSchema = { 12 | boardName: z.string().describe('The name of the board to create'), 13 | boardKind: z.nativeEnum(BoardKind).default(BoardKind.Public).describe('The kind of board to create'), 14 | boardDescription: z.string().optional().describe('The description of the board to create'), 15 | workspaceId: z.string().optional().describe('The ID of the workspace to create the board in'), 16 | }; 17 | 18 | export class CreateBoardTool extends BaseMondayApiTool { 19 | name = 'create_board'; 20 | type = ToolType.WRITE; 21 | annotations = createMondayApiAnnotations({ 22 | title: 'Create Board', 23 | readOnlyHint: false, 24 | destructiveHint: false, 25 | idempotentHint: false, 26 | }); 27 | 28 | getDescription(): string { 29 | return 'Create a monday.com board'; 30 | } 31 | 32 | getInputSchema(): typeof createBoardToolSchema { 33 | return createBoardToolSchema; 34 | } 35 | 36 | protected async executeInternal(input: ToolInputType): Promise> { 37 | const variables: CreateBoardMutationVariables = { 38 | boardName: input.boardName, 39 | boardKind: input.boardKind, 40 | boardDescription: input.boardDescription, 41 | workspaceId: input.workspaceId, 42 | }; 43 | 44 | const res = await this.mondayApi.request(createBoard, variables); 45 | 46 | return { 47 | content: `Board ${res.create_board?.id} successfully created`, 48 | }; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/token.utils.ts: -------------------------------------------------------------------------------- 1 | import jwt from 'jsonwebtoken'; 2 | 3 | /** 4 | * JWT token payload structure from monday.com API 5 | */ 6 | export interface MondayTokenPayload { 7 | tid: number; // team/account ID 8 | aai: number; // API app ID 9 | uid: number; // user ID 10 | iad: string; // issued at date 11 | per: string; // permissions 12 | actid: number; // account ID 13 | rgn: string; // region 14 | } 15 | 16 | /** 17 | * Normalizes a token by removing common prefixes and whitespace 18 | * @param token - The token to normalize (may include "Bearer " prefix) 19 | * @returns The clean token string 20 | */ 21 | export const normalizeToken = (token: string): string => { 22 | return token.trim().replace(/^Bearer\s+/i, ''); 23 | }; 24 | 25 | /** 26 | * Decodes a JWT token to extract the payload 27 | * @param token - The JWT token to decode (should be a clean token without "Bearer " prefix) 28 | * @returns The decoded payload or null if invalid 29 | */ 30 | export const decodeJwtToken = (token: string): MondayTokenPayload | null => { 31 | try { 32 | // Use jsonwebtoken library to decode (without verification) 33 | const decoded = jwt.decode(token) as MondayTokenPayload | null; 34 | return decoded; 35 | } catch (error) { 36 | // If decoding fails, return null 37 | return null; 38 | } 39 | }; 40 | 41 | /** 42 | * Extracts token information for tracking 43 | * @param token - The monday.com API token (may include "Bearer " prefix) 44 | * @returns Token information object or empty object if extraction fails 45 | */ 46 | export const extractTokenInfo = (token: string): Partial => { 47 | const normalizedToken = normalizeToken(token); 48 | const tokenPayload = decodeJwtToken(normalizedToken); 49 | if (!tokenPayload) { 50 | return {}; 51 | } 52 | 53 | return { 54 | tid: tokenPayload.tid, 55 | aai: tokenPayload.aai, 56 | uid: tokenPayload.uid, 57 | actid: tokenPayload.actid, 58 | rgn: tokenPayload.rgn, 59 | per: tokenPayload.per, 60 | }; 61 | }; 62 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/tools/tools-filtering.utils.ts: -------------------------------------------------------------------------------- 1 | import { ApiClient } from '@mondaydotcomorg/api'; 2 | import { allGraphqlApiTools, allMondayAppsTools, allMondayDevTools, Tool, ToolType } from '../../core'; 3 | import { ToolMode, ToolsConfiguration } from '../../core/monday-agent-toolkit'; 4 | import { toolFactory } from './initializing.utils'; 5 | import { MondayApiToolContext } from '../../core/tools/platform-api-tools/base-monday-api-tool'; 6 | 7 | export const getFilteredToolInstances = ( 8 | instanceOptions: { apiClient: ApiClient; apiToken: string; context?: MondayApiToolContext }, 9 | config?: ToolsConfiguration, 10 | ): Tool[] => { 11 | let allToolConstructors: Array Tool> = []; 12 | if (config?.mode === ToolMode.APPS) { 13 | allToolConstructors = [...allMondayAppsTools]; 14 | } else if (config?.mode === ToolMode.API || !config?.mode) { 15 | allToolConstructors = [...allGraphqlApiTools, ...allMondayDevTools]; 16 | } 17 | 18 | const allToolInstances = allToolConstructors.map((ctor) => toolFactory(ctor, instanceOptions)); 19 | 20 | return allToolInstances.filter((toolInstance) => { 21 | if (!config) { 22 | return toolInstance.type !== ToolType.ALL_API; 23 | } 24 | 25 | if (config.mode === ToolMode.API) { 26 | if (config.enableDynamicApiTools === 'only') { 27 | return toolInstance.type === ToolType.ALL_API; 28 | } 29 | } 30 | 31 | let shouldFilter = false; 32 | if (config.mode === ToolMode.API && config.enableDynamicApiTools === false) { 33 | shouldFilter = shouldFilter || toolInstance.type === ToolType.ALL_API; 34 | } 35 | if (config.readOnlyMode) { 36 | shouldFilter = shouldFilter || toolInstance.type !== ToolType.READ; 37 | } 38 | if (config.include) { 39 | shouldFilter = shouldFilter || !config.include?.includes(toolInstance.name); 40 | } else if (config.exclude) { 41 | shouldFilter = shouldFilter || config.exclude?.includes(toolInstance.name); 42 | } 43 | return !shouldFilter; 44 | }); 45 | }; 46 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/delete-column-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { DeleteColumnMutation, DeleteColumnMutationVariables } from 'src/monday-graphql/generated/graphql/graphql'; 3 | import { deleteColumn } from 'src/monday-graphql/queries.graphql'; 4 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 5 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 6 | 7 | export const deleteColumnToolSchema = { 8 | columnId: z.string().describe('The id of the column to be deleted'), 9 | }; 10 | 11 | export const deleteColumnInBoardToolSchema = { 12 | boardId: z.number().describe('The id of the board to which the new column will be added'), 13 | ...deleteColumnToolSchema, 14 | }; 15 | 16 | export type DeleteColumnToolInput = typeof deleteColumnToolSchema | typeof deleteColumnInBoardToolSchema; 17 | 18 | export class DeleteColumnTool extends BaseMondayApiTool { 19 | name = 'delete_column'; 20 | type = ToolType.WRITE; 21 | annotations = createMondayApiAnnotations({ 22 | title: 'Delete Column', 23 | readOnlyHint: false, 24 | destructiveHint: true, 25 | idempotentHint: false, 26 | }); 27 | 28 | getDescription(): string { 29 | return 'Delete a column from a monday.com board'; 30 | } 31 | 32 | getInputSchema(): DeleteColumnToolInput { 33 | if (this.context?.boardId) { 34 | return deleteColumnToolSchema; 35 | } 36 | 37 | return deleteColumnInBoardToolSchema; 38 | } 39 | 40 | protected async executeInternal(input: ToolInputType): Promise> { 41 | const boardId = this.context?.boardId ?? (input as ToolInputType).boardId; 42 | 43 | const variables: DeleteColumnMutationVariables = { 44 | boardId: boardId.toString(), 45 | columnId: input.columnId, 46 | }; 47 | 48 | const res = await this.mondayApi.request(deleteColumn, variables); 49 | 50 | return { 51 | content: `Column ${res.delete_column?.id} successfully deleted`, 52 | }; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-custom-activity-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | CreateCustomActivityMutation, 4 | CreateCustomActivityMutationVariables, 5 | CustomActivityColor, 6 | CustomActivityIcon, 7 | } from '../../../monday-graphql/generated/graphql/graphql'; 8 | import { createCustomActivity } from '../../../monday-graphql/queries.graphql'; 9 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 10 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 11 | 12 | export const createCustomActivityToolSchema = { 13 | color: z.nativeEnum(CustomActivityColor).describe('The color of the custom activity'), 14 | icon_id: z.nativeEnum(CustomActivityIcon).describe('The icon ID of the custom activity'), 15 | name: z.string().describe('The name of the custom activity'), 16 | }; 17 | 18 | export class CreateCustomActivityTool extends BaseMondayApiTool { 19 | name = 'create_custom_activity'; 20 | type = ToolType.WRITE; 21 | annotations = createMondayApiAnnotations({ 22 | title: 'Create Custom Activity', 23 | readOnlyHint: false, 24 | destructiveHint: false, 25 | idempotentHint: false, 26 | }); 27 | 28 | getDescription(): string { 29 | return 'Create a new custom activity in the E&A app'; 30 | } 31 | 32 | getInputSchema(): typeof createCustomActivityToolSchema { 33 | return createCustomActivityToolSchema; 34 | } 35 | 36 | protected async executeInternal( 37 | input: ToolInputType, 38 | ): Promise> { 39 | const variables: CreateCustomActivityMutationVariables = { 40 | color: input.color as CustomActivityColor, 41 | icon_id: input.icon_id as CustomActivityIcon, 42 | name: input.name, 43 | }; 44 | 45 | const res = await this.mondayApi.request(createCustomActivity, variables); 46 | 47 | return { 48 | content: `Custom activity '${input.name}' with color ${input.color} and icon ${input.icon_id} successfully created`, 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-board-schema-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { GetBoardSchemaQuery, GetBoardSchemaQueryVariables } from 'src/monday-graphql/generated/graphql/graphql'; 3 | import { getBoardSchema } from '../../../monday-graphql/queries.graphql'; 4 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 5 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 6 | 7 | export const getBoardSchemaToolSchema = { 8 | boardId: z.number().describe('The id of the board to get the schema of'), 9 | }; 10 | 11 | export class GetBoardSchemaTool extends BaseMondayApiTool { 12 | name = 'get_board_schema'; 13 | type = ToolType.READ; 14 | annotations = createMondayApiAnnotations({ 15 | title: 'Get Board Schema', 16 | readOnlyHint: true, 17 | destructiveHint: false, 18 | idempotentHint: true, 19 | }); 20 | 21 | getDescription(): string { 22 | return 'Get board schema (columns and groups) by board id'; 23 | } 24 | 25 | getInputSchema(): typeof getBoardSchemaToolSchema | undefined { 26 | if (this.context?.boardId) { 27 | return undefined; 28 | } 29 | 30 | return getBoardSchemaToolSchema; 31 | } 32 | 33 | protected async executeInternal( 34 | input: ToolInputType, 35 | ): Promise> { 36 | const boardId = this.context?.boardId ?? (input as ToolInputType).boardId; 37 | const variables: GetBoardSchemaQueryVariables = { 38 | boardId: boardId.toString(), 39 | }; 40 | 41 | const res = await this.mondayApi.request(getBoardSchema, variables); 42 | 43 | return { 44 | content: `The current schema of the board ${boardId} is: 45 | \n\nColumns:\n ${res.boards?.[0]?.columns?.map((column) => `Id - ${column?.id}\n Title - ${column?.title}\n Type - ${column?.type}`).join('\n')} 46 | \n\nGroups:\n ${res.boards?.[0]?.groups?.map((group) => `Id - ${group?.id}\n Title - ${group?.title}`).join('\n')}`, 47 | }; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { CreateAppResponse, createPlainAppSchema } from './schemas/app-schemas'; 6 | 7 | export class CreateAppTool extends BaseMondayAppsTool { 8 | name = 'monday_apps_create_app'; 9 | category = MondayAppsToolCategory.APP; 10 | type: ToolType = ToolType.WRITE; 11 | annotations = createMondayAppsAnnotations({ 12 | title: 'Create App', 13 | }); 14 | 15 | getDescription(): string { 16 | return 'Create a new monday.com app with basic information (name and optional description). This creates both a new app and its initial draft version. Use this when starting development of a new app from scratch.'; 17 | } 18 | 19 | getInputSchema() { 20 | return createPlainAppSchema.shape; 21 | } 22 | 23 | protected async executeInternal( 24 | input: ToolInputType, 25 | ): Promise> { 26 | try { 27 | const response = await this.executeApiRequest(HttpMethod.POST, API_ENDPOINTS.APPS.CREATE, { 28 | data: { 29 | name: input.name, 30 | description: input.description || '', 31 | }, 32 | }); 33 | 34 | return { 35 | content: `Created app "${input.name}" (ID: ${response.app.id}, Version: ${response.app_version.id})`, 36 | metadata: response, 37 | }; 38 | } catch (error) { 39 | const errorMessage = error instanceof Error ? error.message : String(error); 40 | return { 41 | content: `Failed to create app: ${errorMessage}`, 42 | metadata: { 43 | statusCode: 500, 44 | error: errorMessage, 45 | app: { id: 0, name: '' }, 46 | app_version: { id: 0, name: '' }, 47 | }, 48 | }; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-workspace-tool/create-workspace-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | CreateWorkspaceMutation, 4 | CreateWorkspaceMutationVariables, 5 | WorkspaceKind, 6 | } from '../../../../monday-graphql/generated/graphql/graphql'; 7 | import { createWorkspace } from './create-workspace-tool.graphql'; 8 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 9 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 10 | 11 | export const createWorkspaceToolSchema = { 12 | name: z.string().describe('The name of the new workspace to be created'), 13 | workspaceKind: z.nativeEnum(WorkspaceKind).describe('The kind of workspace to create'), 14 | description: z.string().optional().describe('The description of the new workspace'), 15 | accountProductId: z.string().optional().describe('The account product ID associated with the workspace'), 16 | }; 17 | 18 | export type CreateWorkspaceToolInput = typeof createWorkspaceToolSchema; 19 | 20 | export class CreateWorkspaceTool extends BaseMondayApiTool { 21 | name = 'create_workspace'; 22 | type = ToolType.WRITE; 23 | annotations = createMondayApiAnnotations({ 24 | title: 'Create Workspace', 25 | readOnlyHint: false, 26 | destructiveHint: false, 27 | idempotentHint: false, 28 | }); 29 | 30 | getDescription(): string { 31 | return 'Create a new workspace in monday.com'; 32 | } 33 | 34 | getInputSchema(): CreateWorkspaceToolInput { 35 | return createWorkspaceToolSchema; 36 | } 37 | 38 | protected async executeInternal(input: ToolInputType): Promise> { 39 | const variables: CreateWorkspaceMutationVariables = { 40 | name: input.name, 41 | workspaceKind: input.workspaceKind, 42 | description: input.description, 43 | accountProductId: input.accountProductId, 44 | }; 45 | 46 | const res = await this.mondayApi.request(createWorkspace, variables); 47 | 48 | return { 49 | content: `Workspace ${res.create_workspace?.id} successfully created`, 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workforms-tools/form-questions-editor-tool/index.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../../tool'; 2 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../../base-monday-api-tool'; 3 | import { FormQuestionActions } from '../workforms.types'; 4 | import { formQuestionsEditorToolSchema } from './schema'; 5 | import { FormQuestionsEditorToolHelpers } from '../utils/form-questions-editor-tool-helpers'; 6 | import { fallbackToStringifiedVersionIfNull } from 'src/utils/microsoft-copilot.utils'; 7 | 8 | export class FormQuestionsEditorTool extends BaseMondayApiTool { 9 | name = 'form_questions_editor'; 10 | type = ToolType.WRITE; 11 | annotations = createMondayApiAnnotations({ 12 | title: 'Form Questions Editor', 13 | readOnlyHint: false, 14 | destructiveHint: true, 15 | idempotentHint: false, 16 | }); 17 | 18 | private helpers = new FormQuestionsEditorToolHelpers(this.mondayApi); 19 | 20 | private readonly actionHandlers = new Map< 21 | FormQuestionActions, 22 | (input: ToolInputType) => Promise> 23 | >([ 24 | [FormQuestionActions.Delete, this.helpers.deleteQuestion.bind(this.helpers)], 25 | [FormQuestionActions.Update, this.helpers.updateQuestion.bind(this.helpers)], 26 | [FormQuestionActions.Create, this.helpers.createQuestion.bind(this.helpers)], 27 | ]); 28 | 29 | getDescription(): string { 30 | return 'Create, update, or delete a question in a monday.com form'; 31 | } 32 | 33 | getInputSchema(): typeof formQuestionsEditorToolSchema { 34 | return formQuestionsEditorToolSchema; 35 | } 36 | 37 | protected async executeInternal( 38 | input: ToolInputType, 39 | ): Promise> { 40 | const handler = this.actionHandlers.get(input.action); 41 | 42 | if (!handler) { 43 | return { 44 | content: `Unknown action: ${input.action}`, 45 | }; 46 | } 47 | 48 | fallbackToStringifiedVersionIfNull(input, 'question', formQuestionsEditorToolSchema.question); 49 | return await handler(input); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/set-environment-variable.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { EnvVarResponse, setEnvVarSchema } from './schemas/code-schemas'; 6 | 7 | export class SetEnvironmentVariableTool extends BaseMondayAppsTool { 8 | name = 'monday_apps_set_environment_variable'; 9 | category = MondayAppsToolCategory.MONDAY_CODE; 10 | type: ToolType = ToolType.WRITE; 11 | annotations = createMondayAppsAnnotations({ 12 | title: 'Set Environment Variable', 13 | destructiveHint: true, 14 | }); 15 | 16 | getDescription(): string { 17 | return 'Set or update an environment variable for an app\'s monday-code backend. Environment variables are used to configure your app\'s runtime behavior (API keys, configuration values, etc.). The variable will be available to all versions of the app. Use this to manage app configuration securely.'; 18 | } 19 | 20 | getInputSchema() { 21 | return setEnvVarSchema.shape; 22 | } 23 | 24 | protected async executeInternal( 25 | input: ToolInputType, 26 | ): Promise> { 27 | try { 28 | const { appId, key, value } = input; 29 | 30 | const response = await this.executeApiRequest( 31 | HttpMethod.PUT, 32 | API_ENDPOINTS.CODE.MANAGE_ENV(appId, key), 33 | { data: { value } }, 34 | ); 35 | 36 | return { 37 | content: `Successfully set environment variable '${key}' for app ID ${appId}.`, 38 | metadata: response, 39 | }; 40 | } catch (error) { 41 | const errorMessage = error instanceof Error ? error.message : String(error); 42 | return { 43 | content: `Failed to set environment variable: ${errorMessage}`, 44 | metadata: { 45 | statusCode: 500, 46 | error: errorMessage, 47 | } as EnvVarResponse, 48 | }; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workforms-tools/create-form-tool/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateFormMutation, CreateFormMutationVariables } from '../../../../../monday-graphql/generated/graphql/graphql'; 2 | import { createForm } from '../workforms.graphql'; 3 | import { ToolInputType, ToolOutputType, ToolType } from '../../../../tool'; 4 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../../base-monday-api-tool'; 5 | import { createFormToolSchema } from './schema'; 6 | 7 | export class CreateFormTool extends BaseMondayApiTool { 8 | name = 'create_form'; 9 | type = ToolType.WRITE; 10 | annotations = createMondayApiAnnotations({ 11 | title: 'Create Form', 12 | readOnlyHint: false, 13 | destructiveHint: false, 14 | idempotentHint: false, 15 | }); 16 | 17 | getDescription(): string { 18 | return 'Create a monday.com form. This will create a new form as well as a new board for which the form’s responses will be stored. The returned board_id is the ID of the board that was created while the returned formToken can be used for all future queries and mutations to continue editing the form.'; 19 | } 20 | 21 | getInputSchema(): typeof createFormToolSchema { 22 | return createFormToolSchema; 23 | } 24 | 25 | protected async executeInternal(input: ToolInputType): Promise> { 26 | const variables: CreateFormMutationVariables = { 27 | destination_workspace_id: input.destination_workspace_id, 28 | destination_folder_id: input.destination_folder_id, 29 | destination_folder_name: input.destination_folder_name, 30 | board_kind: input.board_kind, 31 | destination_name: input.destination_name, 32 | board_owner_ids: input.board_owner_ids, 33 | board_owner_team_ids: input.board_owner_team_ids, 34 | board_subscriber_ids: input.board_subscriber_ids, 35 | board_subscriber_teams_ids: input.board_subscriber_teams_ids, 36 | }; 37 | 38 | const res = await this.mondayApi.request(createForm, variables); 39 | 40 | return { 41 | content: `Form created successfully. Board ID: ${res.create_form?.boardId}, Token: ${res.create_form?.token}`, 42 | }; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-column-type-info/get-column-type-info-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { getColumnTypeSchema } from './get-column-type-schema.graphql'; 3 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 4 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 5 | import { NonDeprecatedColumnType } from 'src/utils/types'; 6 | 7 | export const getNonDeprecatedColumnTypeInfoToolSchema = { 8 | columnType: z.nativeEnum(NonDeprecatedColumnType).describe('The column type to retrieve information for (e.g., "text", "status", "date", "numbers")'), 9 | }; 10 | 11 | export class GetColumnTypeInfoTool extends BaseMondayApiTool { 12 | name = 'get_column_type_info'; 13 | type = ToolType.READ; 14 | annotations = createMondayApiAnnotations({ 15 | title: 'Get Column Type Info', 16 | readOnlyHint: true, 17 | destructiveHint: false, 18 | idempotentHint: true, 19 | }); 20 | 21 | getDescription(): string { 22 | return 'Retrieves comprehensive information about a specific column type, including JSON schema definition and other metadata. Use this before creating columns with the create_column tool to understand the structure, validation rules, and available properties for column settings.'; 23 | } 24 | 25 | getInputSchema(): typeof getNonDeprecatedColumnTypeInfoToolSchema { 26 | return getNonDeprecatedColumnTypeInfoToolSchema; 27 | } 28 | 29 | protected async executeInternal(input: ToolInputType): Promise> { 30 | const variables = { 31 | type: input.columnType, 32 | }; 33 | 34 | const res = await this.mondayApi.request(getColumnTypeSchema, variables); 35 | 36 | if (!res?.get_column_type_schema) { 37 | return { 38 | content: `Information for column type "${input.columnType}" not found or not available.`, 39 | }; 40 | } 41 | 42 | const columnTypeInfo = { 43 | schema: res.get_column_type_schema, 44 | }; 45 | 46 | return { 47 | content: `Column Type Information for "${input.columnType}":\n\n${JSON.stringify(columnTypeInfo, null, 2)}`, 48 | }; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/list-environment-variable-keys.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { EnvVarKeysResponse, listEnvVarKeysSchema } from './schemas/code-schemas'; 6 | 7 | export class ListEnvironmentVariableKeysTool extends BaseMondayAppsTool< 8 | typeof listEnvVarKeysSchema.shape, 9 | EnvVarKeysResponse 10 | > { 11 | name = 'monday_apps_list_environment_variable_keys'; 12 | category = MondayAppsToolCategory.MONDAY_CODE; 13 | type: ToolType = ToolType.READ; 14 | annotations = createMondayAppsAnnotations({ 15 | readOnlyHint: true, 16 | title: 'List Environment Variable Keys', 17 | }); 18 | 19 | getDescription(): string { 20 | return 'List all environment variable keys configured for an app\'s monday-code backend. Returns only the keys (not values) for security reasons. Use this to see what environment variables are currently configured for your app before adding or updating them.'; 21 | } 22 | 23 | getInputSchema() { 24 | return listEnvVarKeysSchema.shape; 25 | } 26 | 27 | protected async executeInternal( 28 | input: ToolInputType, 29 | ): Promise> { 30 | try { 31 | const { appId } = input; 32 | 33 | const response = await this.executeApiRequest( 34 | HttpMethod.GET, 35 | API_ENDPOINTS.CODE.GET_ENV_KEYS(appId), 36 | ); 37 | 38 | return { 39 | content: `Found ${response.keys.length} environment variable keys for app ID ${appId}.`, 40 | metadata: response, 41 | }; 42 | } catch (error) { 43 | const errorMessage = error instanceof Error ? error.message : String(error); 44 | return { 45 | content: `Failed to list environment variable keys: ${errorMessage}`, 46 | metadata: { 47 | statusCode: 500, 48 | error: errorMessage, 49 | keys: [], 50 | } as EnvVarKeysResponse, 51 | }; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app/get-all-apps.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { AppApiDataResponse } from './schemas/app-schemas'; 6 | 7 | export class GetAllAppsTool extends BaseMondayAppsTool { 8 | name = 'monday_apps_get_all_apps'; 9 | category = MondayAppsToolCategory.APP; 10 | type: ToolType = ToolType.READ; 11 | annotations = createMondayAppsAnnotations({ 12 | readOnlyHint: true, 13 | title: 'Get All Apps', 14 | }); 15 | 16 | getDescription(): string { 17 | return 'Retrieve all the development apps that the user has collaboration permissions for. Returns a list of apps with their IDs, names, and multi-region configuration. Use this to discover available apps before performing other operations that require an app ID'; 18 | } 19 | 20 | getInputSchema() { 21 | return undefined; 22 | } 23 | 24 | protected async executeInternal(_input?: ToolInputType): Promise> { 25 | try { 26 | const response = await this.executeApiRequest(HttpMethod.GET, API_ENDPOINTS.APPS.GET_ALL); 27 | 28 | // Format the apps data for display 29 | const appsDetails = response.apps 30 | .map((app) => { 31 | const multiRegion = app.mondayCodeConfig?.isMultiRegion ? ' (Multi-Region)' : ''; 32 | return `- ID: ${app.id}, Name: ${app.name}${multiRegion}`; 33 | }) 34 | .join('\n'); 35 | 36 | return { 37 | content: `Retrieved ${response.apps.length} apps:\n${appsDetails}`, 38 | metadata: response, 39 | }; 40 | } catch (error) { 41 | const errorMessage = error instanceof Error ? error.message : String(error); 42 | return { 43 | content: `Failed to retrieve apps: ${errorMessage}`, 44 | metadata: { 45 | statusCode: 500, 46 | error: errorMessage, 47 | apps: [], // Add required apps property 48 | } as AppApiDataResponse, 49 | }; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/update-workspace-tool/update-workspace-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { updateWorkspace } from './update-workspace-tool.graphql'; 3 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 4 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 5 | import { WorkspaceKind } from 'src/monday-graphql/generated/graphql/graphql'; 6 | 7 | export const updateWorkspaceToolSchema = { 8 | id: z.string().describe('The ID of the workspace to update'), 9 | attributeAccountProductId: z.number().optional().describe("The target account product's ID to move the workspace to"), 10 | attributeDescription: z.string().optional().describe("The description of the workspace to update"), 11 | attributeKind: z.nativeEnum(WorkspaceKind).optional().describe("The kind of the workspace to update (open / closed / template)"), 12 | attributeName: z.string().optional().describe("The name of the workspace to update"), 13 | }; 14 | 15 | export type UpdateWorkspaceToolInput = typeof updateWorkspaceToolSchema; 16 | 17 | export class UpdateWorkspaceTool extends BaseMondayApiTool { 18 | name = 'update_workspace'; 19 | type = ToolType.WRITE; 20 | annotations = createMondayApiAnnotations({ 21 | title: 'Update Workspace', 22 | readOnlyHint: false, 23 | destructiveHint: false, 24 | idempotentHint: true, 25 | }); 26 | 27 | getDescription(): string { 28 | return 'Update an existing workspace in monday.com'; 29 | } 30 | 31 | getInputSchema(): UpdateWorkspaceToolInput { 32 | return updateWorkspaceToolSchema; 33 | } 34 | 35 | protected async executeInternal(input: ToolInputType): Promise> { 36 | const variables = { 37 | id: input.id, 38 | attributes: { 39 | account_product_id:input.attributeAccountProductId, 40 | description: input.attributeDescription, 41 | kind: input.attributeKind, 42 | name: input.attributeName, 43 | }, 44 | }; 45 | 46 | const res = await this.mondayApi.request<{ update_workspace: { id: string } }>(updateWorkspace, variables); 47 | 48 | return { 49 | content: `Workspace ${res.update_workspace?.id} successfully updated`, 50 | }; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app/promote-app.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { PromoteAppResponse, promoteAppSchema } from './schemas/app-schemas'; 6 | 7 | export class PromoteAppTool extends BaseMondayAppsTool { 8 | name = 'monday_apps_promote_app'; 9 | category = MondayAppsToolCategory.APP; 10 | type: ToolType = ToolType.WRITE; 11 | annotations = createMondayAppsAnnotations({ 12 | destructiveHint: true, 13 | title: 'Promote App', 14 | }); 15 | 16 | getDescription(): string { 17 | return 'Promote a specific app version to live/production status. This makes the app version available to end users if the app is published. You can specify a version ID to promote, or if omitted, the latest draft version will be promoted. This is a critical operation that deploys your app changes.'; 18 | } 19 | 20 | getInputSchema() { 21 | return promoteAppSchema.shape; 22 | } 23 | 24 | protected async executeInternal( 25 | input: ToolInputType, 26 | ): Promise> { 27 | try { 28 | const { appId, versionId } = input; 29 | const data = versionId ? { versionId } : undefined; 30 | 31 | const response = await this.executeApiRequest( 32 | HttpMethod.POST, 33 | API_ENDPOINTS.APPS.PROMOTE(appId), 34 | { data }, 35 | ); 36 | 37 | return { 38 | content: `Successfully started promotion for app ID ${appId}${versionId ? ` and version ID ${versionId}` : ''}.`, 39 | metadata: response, 40 | }; 41 | } catch (error) { 42 | const errorMessage = error instanceof Error ? error.message : String(error); 43 | return { 44 | content: `Failed to promote app: ${errorMessage}`, 45 | metadata: { 46 | statusCode: 500, 47 | error: errorMessage, 48 | appId: input.appId, // Add required appId property 49 | } as PromoteAppResponse, 50 | }; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/routes.consts.ts: -------------------------------------------------------------------------------- 1 | export enum HttpMethod { 2 | GET = 'GET', 3 | POST = 'POST', 4 | PUT = 'PUT', 5 | DELETE = 'DELETE', 6 | } 7 | 8 | export const MONDAY_APPS_DOMAIN = 'https://monday-apps-ms.monday.com'; 9 | 10 | const BASE_API = '/api'; 11 | const BASE_APPS = `${BASE_API}/apps`; 12 | const BASE_APP_VERSIONS = `${BASE_API}/app-versions`; 13 | const BASE_CODE = `${BASE_API}/code`; 14 | const BASE_STORAGE = `${BASE_API}/storage`; 15 | 16 | const APPS_URL = `${MONDAY_APPS_DOMAIN}${BASE_APPS}`; 17 | const APP_VERSIONS_URL = `${MONDAY_APPS_DOMAIN}${BASE_APP_VERSIONS}`; 18 | const CODE_URL = `${MONDAY_APPS_DOMAIN}${BASE_CODE}`; 19 | const STORAGE_URL = `${MONDAY_APPS_DOMAIN}${BASE_STORAGE}`; 20 | 21 | export const API_ENDPOINTS = { 22 | APPS: { 23 | GET_ALL: APPS_URL, 24 | CREATE: APPS_URL, 25 | CREATE_FROM_MANIFEST: `${APPS_URL}/manifest`, 26 | PROMOTE: (appId: number) => `${APPS_URL}/${appId}/promote`, 27 | }, 28 | 29 | APP_VERSIONS: { 30 | GET_ALL: (appId: number) => `${APPS_URL}/${appId}/versions`, 31 | GET_BY_ID: (versionId: number) => `${APP_VERSIONS_URL}/${versionId}`, 32 | }, 33 | 34 | APP_FEATURES: { 35 | GET_ALL: (appVersionId: number) => `${APP_VERSIONS_URL}/${appVersionId}/app-features`, 36 | CREATE: (appId: number, appVersionId: number) => `${APPS_URL}/${appId}/app-versions/${appVersionId}/app-features`, 37 | }, 38 | 39 | STORAGE: { 40 | GET_BY_TERM: (appId: number, accountId: number, term: string) => 41 | `${STORAGE_URL}/app/${appId}/account/${accountId}/records?term=${encodeURI(term)}`, 42 | EXPORT_DATA: (appId: number, accountId: number) => 43 | `${STORAGE_URL}/app/${appId}/account/${accountId}/records/export`, 44 | }, 45 | 46 | CODE: { 47 | GET_DEPLOYMENT_STATUS: (appVersionId: number) => `${CODE_URL}/${appVersionId}/deployments`, 48 | GET_DEPLOYMENT_SIGNED_URL: (appVersionId: number) => `${CODE_URL}/${appVersionId}/deployments/signed-url`, 49 | GET_ENV_KEYS: (appId: number) => `${CODE_URL}/${appId}/env-keys`, 50 | MANAGE_ENV: (appId: number, key: string) => `${CODE_URL}/${appId}/env/${key}`, 51 | }, 52 | PLATFORM_BUILDING_BLOCKS_SCHEMAS: { 53 | GET_ALL: `${MONDAY_APPS_DOMAIN}/apps_ms/public/platform-building-blocks-schemas`, 54 | }, 55 | }; 56 | 57 | export const APPS_MS_TIMEOUT_IN_MS = 30000; 58 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-folder-tool/create-folder-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | FolderColor, 4 | FolderFontWeight, 5 | FolderCustomIcon, 6 | CreateFolderMutation, 7 | CreateFolderMutationVariables, 8 | } from '../../../../monday-graphql/generated/graphql/graphql'; 9 | import { createFolderTool } from './create-folder-tool.graphql'; 10 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 11 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 12 | 13 | export const createFolderToolSchema = { 14 | workspaceId: z.string().describe('The ID of the workspace where the folder will be created'), 15 | name: z.string().describe('The name of the folder to be created'), 16 | color: z.nativeEnum(FolderColor).optional().describe('The color of the folder'), 17 | fontWeight: z.nativeEnum(FolderFontWeight).optional().describe('The font weight of the folder'), 18 | customIcon: z.nativeEnum(FolderCustomIcon).optional().describe('The custom icon of the folder'), 19 | parentFolderId: z.string().optional().describe('The ID of the parent folder'), 20 | }; 21 | 22 | export type CreateFolderToolInput = typeof createFolderToolSchema; 23 | 24 | export class CreateFolderTool extends BaseMondayApiTool { 25 | name = 'create_folder'; 26 | type = ToolType.WRITE; 27 | annotations = createMondayApiAnnotations({ 28 | title: 'Create Folder', 29 | readOnlyHint: false, 30 | destructiveHint: false, 31 | idempotentHint: false, 32 | }); 33 | 34 | getDescription(): string { 35 | return 'Create a new folder in a monday.com workspace'; 36 | } 37 | 38 | getInputSchema(): CreateFolderToolInput { 39 | return createFolderToolSchema; 40 | } 41 | 42 | protected async executeInternal(input: ToolInputType): Promise> { 43 | const variables: CreateFolderMutationVariables = { 44 | workspaceId: input.workspaceId, 45 | name: input.name, 46 | color: input.color, 47 | fontWeight: input.fontWeight, 48 | customIcon: input.customIcon, 49 | parentFolderId: input.parentFolderId, 50 | }; 51 | 52 | const res = await this.mondayApi.request(createFolderTool, variables); 53 | 54 | return { 55 | content: `Folder ${res.create_folder?.id} successfully created`, 56 | }; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/board-insights/board-insights.consts.ts: -------------------------------------------------------------------------------- 1 | import { AggregateSelectFunctionName } from 'src/monday-graphql/generated/graphql/graphql'; 2 | 3 | export const DEFAULT_LIMIT = 1000; 4 | export const MAX_LIMIT = 1000; 5 | 6 | // Functions to exclude from BoardInsightsAggregationFunction 7 | const excludedFunctions = new Set([ 8 | AggregateSelectFunctionName.Case, 9 | AggregateSelectFunctionName.Between, 10 | AggregateSelectFunctionName.Left, 11 | AggregateSelectFunctionName.Raw, 12 | AggregateSelectFunctionName.None, 13 | AggregateSelectFunctionName.CountKeys, 14 | ]); 15 | 16 | // Programmatically create array of allowed aggregation functions 17 | export const BoardInsightsAggregationFunction = Object.values(AggregateSelectFunctionName).filter( 18 | (fn) => !excludedFunctions.has(fn), 19 | ) as [AggregateSelectFunctionName, ...AggregateSelectFunctionName[]]; 20 | 21 | export const transformativeFunctions = new Set([ 22 | AggregateSelectFunctionName.Left, 23 | AggregateSelectFunctionName.Trim, 24 | AggregateSelectFunctionName.Upper, 25 | AggregateSelectFunctionName.Lower, 26 | AggregateSelectFunctionName.DateTruncDay, 27 | AggregateSelectFunctionName.DateTruncWeek, 28 | AggregateSelectFunctionName.DateTruncMonth, 29 | AggregateSelectFunctionName.DateTruncQuarter, 30 | AggregateSelectFunctionName.DateTruncYear, 31 | AggregateSelectFunctionName.Color, 32 | AggregateSelectFunctionName.Label, 33 | AggregateSelectFunctionName.EndDate, 34 | AggregateSelectFunctionName.StartDate, 35 | AggregateSelectFunctionName.Hour, 36 | AggregateSelectFunctionName.PhoneCountryShortName, 37 | AggregateSelectFunctionName.Person, 38 | AggregateSelectFunctionName.Upper, 39 | AggregateSelectFunctionName.Lower, 40 | AggregateSelectFunctionName.Order, 41 | AggregateSelectFunctionName.Length, 42 | AggregateSelectFunctionName.Flatten, 43 | AggregateSelectFunctionName.IsDone, 44 | ]); 45 | 46 | export const aggregativeFunctions = new Set([ 47 | AggregateSelectFunctionName.Count, 48 | AggregateSelectFunctionName.CountDistinct, 49 | AggregateSelectFunctionName.CountSubitems, 50 | AggregateSelectFunctionName.CountItems, 51 | AggregateSelectFunctionName.First, 52 | AggregateSelectFunctionName.Sum, 53 | AggregateSelectFunctionName.Average, 54 | AggregateSelectFunctionName.Median, 55 | AggregateSelectFunctionName.Min, 56 | AggregateSelectFunctionName.Max, 57 | AggregateSelectFunctionName.MinMax, 58 | ]); 59 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/export-storage-data.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from 'src/core/tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { ExportStorageDataResponse, exportStorageDataSchema } from './schemas/storage-schemas'; 6 | 7 | export class ExportStorageDataTool extends BaseMondayAppsTool< 8 | typeof exportStorageDataSchema.shape, 9 | ExportStorageDataResponse 10 | > { 11 | name = 'monday_apps_export_storage_data'; 12 | category = MondayAppsToolCategory.STORAGE; 13 | type: ToolType = ToolType.READ; 14 | annotations = createMondayAppsAnnotations({ 15 | readOnlyHint: true, 16 | title: 'Export Storage Data', 17 | }); 18 | 19 | getDescription(): string { 20 | return 'Export all storage data from a monday.com app for a specific account. You can choose the export format (JSON or CSV). Returns a download URL to retrieve the exported data. Use this for data backup, migration, or analysis purposes.'; 21 | } 22 | 23 | getInputSchema() { 24 | return exportStorageDataSchema.shape; 25 | } 26 | 27 | protected async executeInternal( 28 | input: ToolInputType, 29 | ): Promise> { 30 | try { 31 | const { appId, accountId, fileFormat } = input; 32 | 33 | const query: Record = {}; 34 | if (fileFormat) { 35 | query.fileFormat = fileFormat; 36 | } 37 | 38 | const response = await this.executeApiRequest( 39 | HttpMethod.GET, 40 | API_ENDPOINTS.STORAGE.EXPORT_DATA(appId, accountId), 41 | { query }, 42 | ); 43 | 44 | return { 45 | content: `Successfully exported storage data for app ID ${appId}, account ID ${accountId}.${ 46 | response.downloadUrl ? ` Download URL: ${response.downloadUrl}` : '' 47 | }`, 48 | metadata: response, 49 | }; 50 | } catch (error) { 51 | const errorMessage = error instanceof Error ? error.message : String(error); 52 | return { 53 | content: `Failed to export storage data: ${errorMessage}`, 54 | metadata: { 55 | statusCode: 500, 56 | error: errorMessage, 57 | } as ExportStorageDataResponse, 58 | }; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/search-storage-records.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from 'src/core/tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { StorageRecordsResponse, searchStorageRecordsSchema } from './schemas/storage-schemas'; 6 | 7 | export class SearchStorageRecordsTool extends BaseMondayAppsTool< 8 | typeof searchStorageRecordsSchema.shape, 9 | StorageRecordsResponse 10 | > { 11 | name = 'monday_apps_search_storage_records'; 12 | category = MondayAppsToolCategory.STORAGE; 13 | type: ToolType = ToolType.READ; 14 | annotations = createMondayAppsAnnotations({ 15 | readOnlyHint: true, 16 | title: 'Search Storage Records', 17 | }); 18 | 19 | getDescription(): string { 20 | return 'Search for storage records in a monday.com app by search term. This allows you to query the app\'s storage data for a specific account. Supports pagination via cursor. Use this to find and inspect data stored by your app in monday.com\'s apps framework storage service'; 21 | } 22 | 23 | getInputSchema() { 24 | return searchStorageRecordsSchema.shape; 25 | } 26 | 27 | protected async executeInternal( 28 | input: ToolInputType, 29 | ): Promise> { 30 | try { 31 | const { appId, accountId, term, cursor } = input; 32 | 33 | const query: Record = { term }; 34 | if (cursor) { 35 | query.cursor = cursor; 36 | } 37 | 38 | const response = await this.executeApiRequest( 39 | HttpMethod.GET, 40 | API_ENDPOINTS.STORAGE.GET_BY_TERM(appId, accountId, term), 41 | { query }, 42 | ); 43 | 44 | return { 45 | content: `Found ${response.records.length} storage records matching term '${term}' for app ID ${appId}, account ID ${accountId}.`, 46 | metadata: response, 47 | }; 48 | } catch (error) { 49 | const errorMessage = error instanceof Error ? error.message : String(error); 50 | return { 51 | content: `Failed to search storage records: ${errorMessage}`, 52 | metadata: { 53 | statusCode: 500, 54 | error: errorMessage, 55 | term: input.term, 56 | records: [], 57 | } as StorageRecordsResponse, 58 | }; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/utils/microsoft-copilot.utils.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType } from "src/core/tool"; 2 | import { ZodRawShape, ZodSchema } from "zod"; 3 | 4 | export const STRINGIFIED_SUFFIX = 'Stringified' as const; 5 | 6 | /** 7 | * Extract keys from an object that have a corresponding "Stringified" version. 8 | * For example, if the object has both `form` and `formStringified`, then 'form' is extracted. 9 | */ 10 | type KeysWithStringifiedVersion = { 11 | [K in keyof T]: K extends string 12 | ? `${K}${typeof STRINGIFIED_SUFFIX}` extends keyof T 13 | ? K 14 | : never 15 | : never 16 | }[keyof T]; 17 | 18 | /** 19 | * Parses a stringified JSON field and assigns it to another field in the input object. 20 | * This is useful for handling Microsoft Copilot's stringified parameters. 21 | * 22 | * @param input - The input object containing the fields 23 | * @param jsonKey - The key where the parsed JSON should be assigned (must have a corresponding stringified version) 24 | * @param schema - The Zod schema to validate the parsed JSON against 25 | * 26 | * Type safety: Only keys that have a corresponding `${key}Stringified` property can be passed as jsonKey. 27 | * For example, if input has `form` and `formStringified`, you can pass 'form' as jsonKey. 28 | */ 29 | export const fallbackToStringifiedVersionIfNull = < 30 | TInput extends ToolInputType, 31 | K extends KeysWithStringifiedVersion = KeysWithStringifiedVersion 32 | >( 33 | input: TInput, 34 | jsonKey: K, 35 | schema: ZodSchema 36 | ) => { 37 | const stringifiedJsonKey = `${String(jsonKey)}${STRINGIFIED_SUFFIX}`; 38 | if (input[jsonKey] || !input[stringifiedJsonKey]) { 39 | return; 40 | } 41 | 42 | let parsedResult: any; 43 | try { 44 | parsedResult = JSON.parse(input[stringifiedJsonKey] as string); 45 | } catch { 46 | throw new Error(`${String(stringifiedJsonKey)} is not a valid JSON`); 47 | } 48 | 49 | // Copilot might send data object directly e.g { ... } or wrap it in anobject with jsonKey as key e.g. { jsonKey: { ... } } 50 | const didCopilotWrapTheObject = typeof(parsedResult) === 'object' && !!parsedResult && jsonKey in parsedResult && Object.keys(parsedResult).length === 1; 51 | const data = didCopilotWrapTheObject ? parsedResult[jsonKey] : parsedResult; 52 | 53 | const parseResult = schema.safeParse(data); 54 | if(!parseResult.success) { 55 | throw new Error(`JSON string defined as ${String(stringifiedJsonKey)} does not match the specified schema`); 56 | } 57 | 58 | (input as any)[jsonKey] = parseResult.data; 59 | }; -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-version.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { AppVersionApiDataResponse, getAppVersionSchema } from './schemas/app-version-schemas'; 6 | 7 | export class GetAppVersionTool extends BaseMondayAppsTool { 8 | name = 'monday_apps_get_app_version'; 9 | category = MondayAppsToolCategory.APP_VERSION; 10 | type: ToolType = ToolType.READ; 11 | annotations = createMondayAppsAnnotations({ 12 | readOnlyHint: true, 13 | }); 14 | 15 | getDescription(): string { 16 | return 'Retrieve detailed data for a specific app version by version ID. Returns comprehensive information including the version name, number, status, associated app ID, and configuration details. Use this to inspect a particular version\'s configuration.'; 17 | } 18 | 19 | getInputSchema() { 20 | return getAppVersionSchema.shape; 21 | } 22 | 23 | protected async executeInternal( 24 | input: ToolInputType, 25 | ): Promise> { 26 | try { 27 | const { versionId } = input; 28 | 29 | const response = await this.executeApiRequest( 30 | HttpMethod.GET, 31 | API_ENDPOINTS.APP_VERSIONS.GET_BY_ID(versionId), 32 | ); 33 | 34 | return { 35 | content: 36 | `Successfully retrieved details for app version ID ${versionId}:\n` + 37 | `Name: ${response.appVersion.name}\n` + 38 | `App ID: ${response.appVersion.appId}\n` + 39 | `Version Number: ${response.appVersion.versionNumber}\n` + 40 | `Status: ${response.appVersion.status}`, 41 | metadata: response, 42 | }; 43 | } catch (error) { 44 | const errorMessage = error instanceof Error ? error.message : String(error); 45 | return { 46 | content: `Failed to retrieve app version: ${errorMessage}`, 47 | metadata: { 48 | appVersion: { 49 | id: input.versionId, 50 | name: '', 51 | appId: 0, 52 | versionNumber: '', 53 | status: '', 54 | mondayCodeConfig: { 55 | isMultiRegion: false, 56 | }, 57 | }, 58 | } as AppVersionApiDataResponse, 59 | }; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/agent-toolkit/README.md: -------------------------------------------------------------------------------- 1 | # @mondaydotcomorg/agent-toolkit 2 | 3 | A powerful toolkit for building AI agents that interact with the monday.com API. This package provides a set of tools and utilities to help you create AI-powered integrations with monday.com through Model Context Protocol (MCP) implementation. 4 | 5 | ## Installation 6 | 7 | ```bash 8 | npm install @mondaydotcomorg/agent-toolkit 9 | ``` 10 | 11 | ## Subpath Exports 12 | 13 | The package provides several modular components that can be imported separately: 14 | 15 | - `@mondaydotcomorg/agent-toolkit/mcp` - MCP server implementation 16 | - `@mondaydotcomorg/agent-toolkit/core` - Core utilities and base classes 17 | - `@mondaydotcomorg/agent-toolkit/openai` - OpenAI integration 18 | 19 | ## Available Tools 20 | 21 | The toolkit includes several pre-built tools for common monday.com operations, organized by functionality: 22 | 23 | ### Item Operations 24 | - `CreateItemTool` - Create a new item in a monday.com board 25 | - `DeleteItemTool` - Delete an item from a board 26 | - `GetBoardItemsPageTool` - Get items by board id and apply filters 27 | - `CreateUpdateTool` - Create a new update on a specific item 28 | - `ChangeItemColumnValuesTool` - Change the column values of an item in a monday.com board 29 | - `MoveItemToGroupTool` - Move an item to a group in a monday.com board 30 | 31 | ### Board Operations 32 | - `CreateBoardTool` - Create a monday.com board 33 | - `GetBoardSchemaTool` - Get board schema (columns and groups) by board id 34 | - `CreateGroupTool` - Create a new group in a monday.com board 35 | - `CreateColumnTool` - Create a new column in a monday.com board 36 | - `DeleteColumnTool` - Delete a column from a monday.com board 37 | 38 | ### WorkForms Operations 39 | - `CreateFormTool` - Create a monday.com form 40 | - `GetFormTool` - Get a form by its token, found in the form's URL 41 | - `UpdateFormTool` - Update a monday.com form, including updating the form's feature settings, appearance settings, accessibility settings, title, description, question order, form tags, and form password 42 | - `FormQuestionsEditorTool` - Create, update, or delete a question in a monday.com form 43 | 44 | ### Account Operations 45 | - `ListUsersAndTeams` - Get users or teams, either by ids, names or by searching the account 46 | 47 | ### Dynamic API Tools 48 | - `AllMondayApiTool` - Execute any monday.com API operation by generating GraphQL queries and mutations dynamically 49 | - `GetGraphQLSchemaTool` - Fetch the monday.com GraphQL schema structure including query and mutation definitions 50 | - `GetTypeDetailsTool` - Get detailed information about a specific GraphQL type from the monday.com API schema 51 | 52 | ## Usage 53 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-versions.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { AppVersionsApiDataResponse, getAppVersionsSchema } from './schemas/app-version-schemas'; 6 | 7 | export class GetAppVersionsTool extends BaseMondayAppsTool< 8 | typeof getAppVersionsSchema.shape, 9 | AppVersionsApiDataResponse 10 | > { 11 | name = 'monday_apps_get_app_versions'; 12 | category = MondayAppsToolCategory.APP_VERSION; 13 | type: ToolType = ToolType.READ; 14 | annotations = createMondayAppsAnnotations({ 15 | readOnlyHint: true, 16 | }); 17 | 18 | getDescription(): string { 19 | return 'Retrieve all versions of a specific app. Returns detailed information including version numbers, IDs, names, and status (draft, live, etc.) for each version. Use this to view the version history and current state of your app.'; 20 | } 21 | 22 | getInputSchema() { 23 | return getAppVersionsSchema.shape; 24 | } 25 | 26 | protected async executeInternal( 27 | input: ToolInputType, 28 | ): Promise> { 29 | try { 30 | const { appId } = input; 31 | 32 | const response = await this.executeApiRequest( 33 | HttpMethod.GET, 34 | API_ENDPOINTS.APP_VERSIONS.GET_ALL(appId), 35 | ); 36 | 37 | // Create a detailed summary of versions 38 | const versionsSummary = response.appVersions 39 | .map((version) => 40 | [ 41 | `- Version ${version.versionNumber} (ID: ${version.id})`, 42 | ` Name: ${version.name}`, 43 | ` Status: ${version.status}`, 44 | ].join('\n'), 45 | ) 46 | .join('\n'); 47 | 48 | return { 49 | content: `Successfully retrieved ${response.appVersions.length} versions for app ID ${appId}:\n\n${versionsSummary}`, 50 | metadata: response, 51 | }; 52 | } catch (error) { 53 | const errorMessage = error instanceof Error ? error.message : String(error); 54 | return { 55 | content: `Failed to retrieve app versions: ${errorMessage}`, 56 | metadata: { 57 | statusCode: 500, 58 | error: errorMessage, 59 | appVersions: [], // Add required appVersions property 60 | } as AppVersionsApiDataResponse, 61 | }; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/agent-toolkit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mondaydotcomorg/agent-toolkit", 3 | "version": "2.30.0", 4 | "description": "monday.com agent toolkit", 5 | "exports": { 6 | "./mcp": { 7 | "types": "./dist/esm/mcp/index.d.ts", 8 | "import": "./dist/esm/mcp/index.js", 9 | "require": "./dist/cjs/mcp/index.js" 10 | }, 11 | "./core": { 12 | "types": "./dist/esm/core/index.d.ts", 13 | "import": "./dist/esm/core/index.js", 14 | "require": "./dist/cjs/core/index.js" 15 | }, 16 | "./openai": { 17 | "types": "./dist/esm/openai/index.d.ts", 18 | "import": "./dist/esm/openai/index.js", 19 | "require": "./dist/cjs/openai/index.js" 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "LICENSE" 25 | ], 26 | "scripts": { 27 | "build": "rollup -c", 28 | "prettier": "prettier --write \"src/**/*.ts\" --ignore-path \"../../.prettierignore\"", 29 | "lint": "eslint --fix \"src/**/*.ts\" --ignore-path \"../../.eslintignore\"", 30 | "test": "jest -c", 31 | "watch": "rollup -c -w", 32 | "fetch:schema": "bash fetch-schema.sh", 33 | "codegen": "graphql-codegen", 34 | "fetch:generate": "yarn fetch:schema && yarn codegen" 35 | }, 36 | "engines": { 37 | "node": ">= 16.20.0" 38 | }, 39 | "author": "monday.com AI Team", 40 | "license": "MIT", 41 | "keywords": [ 42 | "monday", 43 | "api", 44 | "agent-toolkit" 45 | ], 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/mondaycom/monday-ai/tree/master/packages/agent-toolkit" 49 | }, 50 | "dependencies": { 51 | "@mondaydotcomorg/api": "^10.0.5", 52 | "axios": "^1.10.0", 53 | "jsonwebtoken": "^9.0.2", 54 | "zod": "^3.24.2", 55 | "zod-to-json-schema": "^3.24.5" 56 | }, 57 | "devDependencies": { 58 | "@graphql-codegen/cli": "^5.0.5", 59 | "@graphql-codegen/typescript": "^4.1.6", 60 | "@graphql-codegen/typescript-operations": "^4.6.0", 61 | "@rollup/plugin-commonjs": "^25.0.7", 62 | "@rollup/plugin-json": "^6.1.0", 63 | "@rollup/plugin-node-resolve": "^15.2.3", 64 | "@rollup/plugin-terser": "^0.4.4", 65 | "@rollup/plugin-typescript": "^11.1.6", 66 | "@types/jest": "^29.5.12", 67 | "@types/jsonwebtoken": "^9.0.10", 68 | "@types/node": "^20.11.18", 69 | "jest": "^29.7.0", 70 | "moment": "^2.30.1", 71 | "openai": "^4.93.0", 72 | "rollup": "^2.79.1", 73 | "rollup-plugin-delete": "^2.0.0", 74 | "rollup-plugin-dts": "^4.2.3", 75 | "ts-jest": "^29.1.2", 76 | "typescript": "^4.9.5" 77 | }, 78 | "peerDependencies": { 79 | "@modelcontextprotocol/sdk": "^1.13.2", 80 | "openai": "^4.93.0" 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-group/create-group-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | PositionRelative, 4 | CreateGroupMutation, 5 | CreateGroupMutationVariables, 6 | } from '../../../../monday-graphql/generated/graphql/graphql'; 7 | import { createGroup } from './create-group.graphql'; 8 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 9 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 10 | import { GROUP_COLORS } from './create-group.consts'; 11 | 12 | export const createGroupToolSchema = { 13 | boardId: z.string().describe('The ID of the board to create the group in'), 14 | groupName: z.string().max(255).describe('The name of the new group (maximum 255 characters)'), 15 | groupColor: z.enum(GROUP_COLORS).optional().describe(`The color for the group. Must be one of the predefined Monday.com group colors: ${GROUP_COLORS.join(', ')}`), 16 | relativeTo: z.string().optional().describe('The ID of the group to position this new group relative to'), 17 | positionRelativeMethod: z.nativeEnum(PositionRelative).optional().describe('Whether to position the new group before or after the relativeTo group'), 18 | }; 19 | 20 | export class CreateGroupTool extends BaseMondayApiTool { 21 | name = 'create_group'; 22 | type = ToolType.WRITE; 23 | annotations = createMondayApiAnnotations({ 24 | title: 'Create Group', 25 | readOnlyHint: false, 26 | destructiveHint: false, 27 | idempotentHint: false, 28 | }); 29 | 30 | getDescription(): string { 31 | return 'Create a new group in a monday.com board. Groups are sections that organize related items. Use when users want to add structure, categorize items, or create workflow phases. Groups can be positioned relative to existing groups and assigned predefined colors. Items will always be created in the top group and so the top group should be the most relevant one for new item creation'; 32 | } 33 | 34 | getInputSchema(): typeof createGroupToolSchema { 35 | return createGroupToolSchema; 36 | } 37 | 38 | protected async executeInternal(input: ToolInputType): Promise> { 39 | const variables: CreateGroupMutationVariables = { 40 | boardId: input.boardId, 41 | groupName: input.groupName, 42 | groupColor: input.groupColor, 43 | relativeTo: input.relativeTo, 44 | positionRelativeMethod: input.positionRelativeMethod, 45 | }; 46 | 47 | const res = await this.mondayApi.request(createGroup, variables); 48 | 49 | return { 50 | content: `Group "${res.create_group?.title}" (ID: ${res.create_group?.id}) successfully created`, 51 | }; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-board-info/get-board-info-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { GetBoardInfoJustColumnsQuery, GetBoardInfoQuery, GetBoardInfoQueryVariables } from '../../../../monday-graphql/generated/graphql/graphql'; 3 | import { getBoardInfo, getBoardInfoJustColumns } from './get-board-info.graphql'; 4 | import { BoardInfoData, BoardInfoJustColumnsData, formatBoardInfoAsJson } from './helpers'; 5 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 6 | import { BaseMondayApiTool, createMondayApiAnnotations } from './../base-monday-api-tool'; 7 | import { NonDeprecatedColumnType } from 'src/utils/types'; 8 | 9 | export const getBoardInfoToolSchema = { 10 | boardId: z.number().describe('The id of the board to get information for'), 11 | }; 12 | 13 | export class GetBoardInfoTool extends BaseMondayApiTool { 14 | name = 'get_board_info'; 15 | type = ToolType.READ; 16 | annotations = createMondayApiAnnotations({ 17 | title: 'Get Board Info', 18 | readOnlyHint: true, 19 | destructiveHint: false, 20 | idempotentHint: true, 21 | }); 22 | 23 | getDescription(): string { 24 | return 'Get comprehensive board information including metadata, structure, owners, and configuration'; 25 | } 26 | 27 | getInputSchema(): typeof getBoardInfoToolSchema { 28 | return getBoardInfoToolSchema; 29 | } 30 | 31 | protected async executeInternal(input: ToolInputType): Promise> { 32 | const variables: GetBoardInfoQueryVariables = { 33 | boardId: input.boardId.toString(), 34 | }; 35 | 36 | const res = await this.mondayApi.request(getBoardInfo, variables); 37 | 38 | const board = res.boards?.[0]; 39 | 40 | if (!board) { 41 | return { 42 | content: `Board with id ${input.boardId} not found or you don't have access to it.`, 43 | }; 44 | } 45 | 46 | const subItemsBoard = await this.getSubItemsBoardAsync(board); 47 | 48 | return { 49 | content: JSON.stringify(formatBoardInfoAsJson(board, subItemsBoard), null, 2) 50 | }; 51 | } 52 | 53 | private async getSubItemsBoardAsync(board: BoardInfoData): Promise { 54 | const subTasksColumn = board.columns?.find((column) => column?.type === NonDeprecatedColumnType.Subtasks); 55 | if(!subTasksColumn) { 56 | return null; 57 | } 58 | 59 | const subItemsBoardId = subTasksColumn.settings.boardIds[0]; 60 | 61 | const response = await this.mondayApi.request(getBoardInfoJustColumns, { boardId: subItemsBoardId }); 62 | const subItemsBoard = response.boards?.[0] ?? null; 63 | 64 | return subItemsBoard; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-deployment-status.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { DeploymentStatusResponse, getDeploymentStatusSchema } from './schemas/code-schemas'; 6 | 7 | export class GetDeploymentStatusTool extends BaseMondayAppsTool< 8 | typeof getDeploymentStatusSchema.shape, 9 | DeploymentStatusResponse 10 | > { 11 | name = 'monday_apps_get_deployment_status'; 12 | category = MondayAppsToolCategory.MONDAY_CODE; 13 | type: ToolType = ToolType.READ; 14 | annotations = createMondayAppsAnnotations({ 15 | readOnlyHint: true, 16 | }); 17 | 18 | getDescription(): string { 19 | return 'Get the deployment status for a specific app version in monday-code (serverless backend). Returns status, start time, end time, any errors, and deployment logs. Use this to monitor the progress and outcome of app deployments, especially after pushing code with mapps code:push'; 20 | } 21 | 22 | getInputSchema() { 23 | return getDeploymentStatusSchema.shape; 24 | } 25 | 26 | protected async executeInternal( 27 | input: ToolInputType, 28 | ): Promise> { 29 | try { 30 | const { appVersionId } = input; 31 | 32 | const response = await this.executeApiRequest( 33 | HttpMethod.GET, 34 | API_ENDPOINTS.CODE.GET_DEPLOYMENT_STATUS(appVersionId), 35 | ); 36 | 37 | // Create a more detailed status message 38 | const statusDetails = [ 39 | `Status: ${response.status || 'Unknown'}`, 40 | response.startTime ? `Started: ${new Date(response.startTime).toLocaleString()}` : null, 41 | response.endTime ? `Completed: ${new Date(response.endTime).toLocaleString()}` : null, 42 | response.error ? `Error: ${response.error}` : null, 43 | response.logs ? `Logs: ${response.logs}` : null, 44 | ] 45 | .filter(Boolean) 46 | .join('\n'); 47 | 48 | return { 49 | content: `Deployment status for app version ID ${appVersionId}:\n${statusDetails}`, 50 | metadata: response, 51 | }; 52 | } catch (error) { 53 | const errorMessage = error instanceof Error ? error.message : String(error); 54 | return { 55 | content: `Failed to get deployment status: ${errorMessage}`, 56 | metadata: { 57 | statusCode: 500, 58 | error: errorMessage, 59 | } as DeploymentStatusResponse, 60 | }; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-column-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { CreateColumnMutation, CreateColumnMutationVariables } from 'src/monday-graphql/generated/graphql/graphql'; 3 | import { createColumn } from '../../../monday-graphql/queries.graphql'; 4 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 5 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 6 | import { NonDeprecatedColumnType } from 'src/utils/types'; 7 | 8 | export const createColumnToolSchema = { 9 | columnType: z.nativeEnum(NonDeprecatedColumnType).describe('The type of the column to be created'), 10 | columnTitle: z.string().describe('The title of the column to be created'), 11 | columnDescription: z.string().optional().describe('The description of the column to be created'), 12 | columnSettings: z 13 | .string() 14 | .optional() 15 | .describe( 16 | 'Column-specific configuration settings as a JSON string. Use the get_column_type_info tool to fetch the JSON schema for the given column type.', 17 | ), 18 | }; 19 | 20 | export const createColumnInBoardToolSchema = { 21 | boardId: z.number().describe('The id of the board to which the new column will be added'), 22 | ...createColumnToolSchema, 23 | }; 24 | 25 | export type CreateColumnToolInput = typeof createColumnToolSchema | typeof createColumnInBoardToolSchema; 26 | 27 | export class CreateColumnTool extends BaseMondayApiTool { 28 | name = 'create_column'; 29 | type = ToolType.WRITE; 30 | annotations = createMondayApiAnnotations({ 31 | title: 'Create Column', 32 | readOnlyHint: false, 33 | destructiveHint: false, 34 | idempotentHint: false, 35 | }); 36 | 37 | getDescription(): string { 38 | return 'Create a new column in a monday.com board'; 39 | } 40 | 41 | getInputSchema(): CreateColumnToolInput { 42 | if (this.context?.boardId) { 43 | return createColumnToolSchema; 44 | } 45 | 46 | return createColumnInBoardToolSchema; 47 | } 48 | 49 | protected async executeInternal(input: ToolInputType): Promise> { 50 | const boardId = this.context?.boardId ?? (input as ToolInputType).boardId; 51 | 52 | const variables: CreateColumnMutationVariables = { 53 | boardId: boardId?.toString() ?? '', 54 | columnType: input.columnType, 55 | columnTitle: input.columnTitle, 56 | columnDescription: input.columnDescription, 57 | columnSettings: 58 | typeof input.columnSettings === 'string' ? JSON.parse(input.columnSettings) : input.columnSettings, 59 | }; 60 | 61 | const res = await this.mondayApi.request(createColumn, variables); 62 | 63 | return { 64 | content: `Column ${res.create_column?.id} successfully created`, 65 | }; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/schemas/app-feature-schemas.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { AppFeatureType } from '../../consts/apps.consts'; 3 | import { MondayApiResponse } from '../../base-tool/base-monday-apps-tool'; 4 | 5 | export interface AppFeature { 6 | id: number; 7 | app_id: number; 8 | app_version_id: number; 9 | app_feature_reference_id: number; 10 | source_app_feature_id: number | null; 11 | name: string; 12 | type: AppFeatureType | string; 13 | state: string; 14 | user_id: number; 15 | data: Record; 16 | schema: boolean | null; 17 | status: string | null; 18 | [key: string]: any; 19 | } 20 | 21 | export interface AppFeaturesResponse extends MondayApiResponse { 22 | appFeatures: AppFeature[]; 23 | } 24 | 25 | export const getAppFeaturesSchema = z.object({ 26 | appVersionId: z.number().describe('The unique identifier of the app version to retrieve features from. Features are version-specific. Get version IDs from get_app_versions'), 27 | type: z 28 | .union([z.nativeEnum(AppFeatureType), z.string()]) 29 | .optional() 30 | .describe('Optional filter to retrieve only features of a specific type. Examples: AppFeatureStatusColumn, AppFeatureBoardView, AppFeatureItemView, AppFeatureDashboardWidget, AppFeatureObject. Leave empty to get all features'), 31 | }); 32 | 33 | export interface AppFeatureReference { 34 | id: number; 35 | created_at: string; 36 | updated_at: string; 37 | live_app_feature_id: number; 38 | app_feature_reference_id: number; 39 | } 40 | 41 | export interface DetailedAppFeature extends AppFeature { 42 | client_instance_token: string; 43 | created_at: string; 44 | updated_at: string; 45 | current_release: string | null; 46 | configured_secret_names: string[]; 47 | } 48 | 49 | export interface CreateAppFeatureResponse extends MondayApiResponse { 50 | app_feature: DetailedAppFeature; 51 | app_feature_reference: AppFeatureReference; 52 | } 53 | 54 | export const createAppFeatureSchema = z.object({ 55 | appId: z.number().describe('The unique identifier of the app to add the feature to. Get from get_all_apps'), 56 | appVersionId: z.number().describe('The specific version ID to add the feature to (typically a draft version). Features are tied to specific versions. Get from get_app_versions'), 57 | name: z.string().describe('A descriptive name for this feature instance. This helps identify the feature in your app configuration and management UI'), 58 | type: z.union([z.nativeEnum(AppFeatureType), z.string()]).describe('The feature type that determines how it integrates with monday.com. Examples: AppFeatureStatusColumn (custom status column), AppFeatureBoardView (board view), AppFeatureItemView (item view), AppFeatureDashboardWidget (widget)'), 59 | data: z.record(z.any()).optional().describe('Feature-specific configuration data as a JSON object. The structure depends on the feature type'), 60 | }); 61 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/get-app-features.ts: -------------------------------------------------------------------------------- 1 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 2 | import { BaseMondayAppsTool, createMondayAppsAnnotations } from '../base-tool/base-monday-apps-tool'; 3 | import { MondayAppsToolCategory } from '../consts/apps.consts'; 4 | import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; 5 | import { AppFeaturesResponse, getAppFeaturesSchema } from './schemas/app-feature-schemas'; 6 | 7 | export class GetAppFeaturesTool extends BaseMondayAppsTool { 8 | name = 'monday_apps_get_app_features'; 9 | category = MondayAppsToolCategory.APP_FEATURE; 10 | type: ToolType = ToolType.READ; 11 | annotations = createMondayAppsAnnotations({ 12 | readOnlyHint: true, 13 | }); 14 | 15 | getDescription(): string { 16 | return 'Retrieve all features (views, columns, integrations, etc.) for a specific app version. Optionally filter by feature type (e.g., AppFeatureStatusColumn, AppFeatureBoardView, AppFeatureItemView). Returns feature names, IDs, types, and states. Use this to inspect what features are configured in an app version.'; 17 | } 18 | 19 | getInputSchema() { 20 | return getAppFeaturesSchema.shape; 21 | } 22 | 23 | protected async executeInternal( 24 | input: ToolInputType, 25 | ): Promise> { 26 | try { 27 | const { appVersionId, type } = input; 28 | 29 | const query: Record = {}; 30 | if (type) { 31 | query.type = type; 32 | } 33 | 34 | const response = await this.executeApiRequest( 35 | HttpMethod.GET, 36 | API_ENDPOINTS.APP_FEATURES.GET_ALL(appVersionId), 37 | { query }, 38 | ); 39 | 40 | const features = response.appFeatures || []; 41 | const featuresCount = features.length; 42 | 43 | const featuresSummary = features 44 | .map((feature) => `${feature.name} (ID: ${feature.id}, Type: ${feature.type}, State: ${feature.state})`) 45 | .join(', '); 46 | 47 | return { 48 | content: 49 | `Successfully retrieved ${featuresCount} app features for app version ID ${appVersionId}${type ? ` of type ${type}` : ''}.\n` + 50 | `Features: ${featuresSummary || 'No features found'}`, 51 | metadata: { 52 | ...response, 53 | statusCode: response.statusCode, 54 | headers: response.headers, 55 | }, 56 | }; 57 | } catch (error) { 58 | const errorMessage = error instanceof Error ? error.message : String(error); 59 | return { 60 | content: `Failed to retrieve app features: ${errorMessage}`, 61 | metadata: { 62 | statusCode: 500, 63 | error: errorMessage, 64 | appFeatures: [], 65 | } as AppFeaturesResponse, 66 | }; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # vitepress build output 108 | **/.vitepress/dist 109 | 110 | # vitepress cache directory 111 | **/.vitepress/cache 112 | 113 | # Docusaurus cache and generated files 114 | .docusaurus 115 | 116 | # Serverless directories 117 | .serverless/ 118 | 119 | # FuseBox cache 120 | .fusebox/ 121 | 122 | # DynamoDB Local files 123 | .dynamodb/ 124 | 125 | # TernJS port file 126 | .tern-port 127 | 128 | # Stores VSCode versions used for testing VSCode extensions 129 | .vscode-test 130 | 131 | # yarn v2 132 | .yarn/cache 133 | .yarn/unplugged 134 | .yarn/build-state.yml 135 | .yarn/install-state.gz 136 | .pnp.* 137 | 138 | # turbo 139 | .turbo 140 | .idea/ 141 | .qodo 142 | 143 | #claude 144 | .claude 145 | claude.md 146 | 147 | # macOS 148 | .DS_Store 149 | .DS_Store? 150 | -------------------------------------------------------------------------------- /packages/monday-api-mcp/src/utils/args/args.service.ts: -------------------------------------------------------------------------------- 1 | import { ParsedArgs, ValidatedArgs } from './args.types.js'; 2 | import { ARG_CONFIGS } from './args.config.js'; 3 | 4 | /** 5 | * Parse command line arguments based on the defined configurations 6 | * Also checks environment variables if command line args are not provided 7 | * @param args Command line arguments (process.argv.slice(2)) 8 | * @returns Object with parsed arguments 9 | */ 10 | export function parseArgs(args: string[]): ParsedArgs { 11 | const result: ParsedArgs = {}; 12 | 13 | ARG_CONFIGS.forEach((config) => { 14 | let argValue: string | undefined; 15 | 16 | // Try to get value from command line arguments 17 | for (const flag of config.flags) { 18 | const flagIndex = args.findIndex((arg) => arg === flag); 19 | if (flagIndex !== -1 && flagIndex + 1 < args.length) { 20 | argValue = args[flagIndex + 1]; 21 | break; 22 | } 23 | } 24 | 25 | // If not found in command line args, try environment variables 26 | if (argValue === undefined) { 27 | const envVarName = `MONDAY_${config.name.toUpperCase()}`; 28 | if (process.env[envVarName]) { 29 | argValue = process.env[envVarName]; 30 | } 31 | } 32 | 33 | // If still not found, use default value if provided 34 | if (argValue === undefined && config.defaultValue !== undefined) { 35 | argValue = String(config.defaultValue); 36 | } 37 | 38 | result[config.name] = argValue; 39 | }); 40 | 41 | return result; 42 | } 43 | 44 | /** 45 | * Validates required arguments and displays error messages for missing ones 46 | * @param parsedArgs The parsed arguments to validate 47 | * @returns Strongly typed validated arguments 48 | */ 49 | export function validateArgs(parsedArgs: ParsedArgs): ValidatedArgs { 50 | const missingArgs = ARG_CONFIGS.filter((config) => config.required && !parsedArgs[config.name]); 51 | 52 | if (missingArgs.length > 0) { 53 | console.error('Error: The following required arguments are missing:'); 54 | 55 | missingArgs.forEach((config) => { 56 | console.error(` - ${config.name}: ${config.description}`); 57 | console.error(' You can provide it using:'); 58 | 59 | const flagsString = config.flags.join(' or '); 60 | console.error(` ${flagsString} command line argument`); 61 | }); 62 | 63 | process.exit(1); 64 | } 65 | 66 | const typedArgs: Record = { ...parsedArgs }; 67 | 68 | ARG_CONFIGS.forEach((config) => { 69 | if (typeof config.defaultValue === 'boolean' && parsedArgs[config.name] !== undefined) { 70 | const stringValue = parsedArgs[config.name] as string; 71 | 72 | // Special handling for enableDynamicApiTools to support "only" option 73 | if (config.name === 'enableDynamicApiTools' && stringValue.toLowerCase() === 'only') { 74 | typedArgs[config.name] = 'only'; 75 | } else { 76 | typedArgs[config.name] = stringValue.toLowerCase() === 'true'; 77 | } 78 | } 79 | }); 80 | 81 | return typedArgs as unknown as ValidatedArgs; 82 | } 83 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/change-item-column-values-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | ChangeItemColumnValuesMutation, 4 | ChangeItemColumnValuesMutationVariables, 5 | } from 'src/monday-graphql/generated/graphql/graphql'; 6 | import { changeItemColumnValues } from '../../../monday-graphql/queries.graphql'; 7 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 8 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 9 | 10 | export const changeItemColumnValuesToolSchema = { 11 | itemId: z.number().describe('The ID of the item to be updated'), 12 | columnValues: z 13 | .string() 14 | .describe( 15 | `A string containing the new column values for the item following this structure: {\\"column_id\\": \\"value\\",... you can change multiple columns at once, note that for status column you must use nested value with 'label' as a key and for date column use 'date' as key} - example: "{\\"text_column_id\\":\\"New text\\", \\"status_column_id\\":{\\"label\\":\\"Done\\"}, \\"date_column_id\\":{\\"date\\":\\"2023-05-25\\"}, \\"phone_id\\":\\"123-456-7890\\", \\"email_id\\":\\"test@example.com\\"}"`, 16 | ), 17 | }; 18 | 19 | export const changeItemColumnValuesInBoardToolSchema = { 20 | boardId: z.number().describe('The ID of the board that contains the item to be updated'), 21 | ...changeItemColumnValuesToolSchema, 22 | }; 23 | 24 | export type ChangeItemColumnValuesToolInput = 25 | | typeof changeItemColumnValuesToolSchema 26 | | typeof changeItemColumnValuesInBoardToolSchema; 27 | 28 | export class ChangeItemColumnValuesTool extends BaseMondayApiTool { 29 | name = 'change_item_column_values'; 30 | type = ToolType.WRITE; 31 | annotations = createMondayApiAnnotations({ 32 | title: 'Change Item Column Values', 33 | readOnlyHint: false, 34 | destructiveHint: false, 35 | idempotentHint: true, 36 | }); 37 | 38 | getDescription(): string { 39 | return 'Change the column values of an item in a monday.com board'; 40 | } 41 | 42 | getInputSchema(): ChangeItemColumnValuesToolInput { 43 | if (this.context?.boardId) { 44 | return changeItemColumnValuesToolSchema; 45 | } 46 | 47 | return changeItemColumnValuesInBoardToolSchema; 48 | } 49 | 50 | protected async executeInternal( 51 | input: ToolInputType, 52 | ): Promise> { 53 | const boardId = 54 | this.context?.boardId ?? (input as ToolInputType).boardId; 55 | const variables: ChangeItemColumnValuesMutationVariables = { 56 | boardId: boardId.toString(), 57 | itemId: input.itemId.toString(), 58 | columnValues: input.columnValues, 59 | }; 60 | 61 | const res = await this.mondayApi.request(changeItemColumnValues, variables); 62 | 63 | return { 64 | content: `Item ${res.change_multiple_column_values?.id} successfully updated with the new column values`, 65 | }; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workspace-info-tool/helpers.ts: -------------------------------------------------------------------------------- 1 | import { GetWorkspaceInfoQuery } from 'src/monday-graphql/generated/graphql/graphql'; 2 | import { OrganizedWorkspaceInfo } from './types'; 3 | 4 | export function organizeWorkspaceInfoHierarchy(response: GetWorkspaceInfoQuery): OrganizedWorkspaceInfo { 5 | const { workspaces, boards, docs, folders } = response; 6 | 7 | // Get the workspace info (assuming single workspace) 8 | const workspace = workspaces?.[0]; 9 | if (!workspace) throw new Error('No workspace found'); 10 | 11 | // Create folder map 12 | const folderMap = new Map( 13 | (folders || []) 14 | .filter( 15 | (folder): folder is NonNullable => folder != null && folder.id != null && folder.name != null, 16 | ) 17 | .map((folder) => [ 18 | folder.id!, 19 | { 20 | id: folder.id!, 21 | name: folder.name!, 22 | boards: [] as Array<{ id: string; name: string }>, 23 | docs: [] as Array<{ id: string; name: string }>, 24 | }, 25 | ]), 26 | ); 27 | 28 | // Organize boards 29 | const rootBoards: Array<{ id: string; name: string }> = []; 30 | (boards || []) 31 | .filter((board): board is NonNullable => board != null && board.id != null && board.name != null) 32 | .forEach((board) => { 33 | const boardItem = { id: board.id!, name: board.name! }; 34 | if (board.board_folder_id && folderMap.has(board.board_folder_id)) { 35 | folderMap.get(board.board_folder_id)!.boards.push(boardItem); 36 | } else { 37 | rootBoards.push(boardItem); 38 | } 39 | }); 40 | 41 | // Organize docs 42 | const rootDocs: Array<{ id: string; name: string }> = []; 43 | (docs || []) 44 | .filter((doc): doc is NonNullable => doc != null && doc.id != null && doc.name != null) 45 | .forEach((doc) => { 46 | const docItem = { id: doc.id!, name: doc.name! }; 47 | if (doc.doc_folder_id && folderMap.has(doc.doc_folder_id)) { 48 | folderMap.get(doc.doc_folder_id)!.docs.push(docItem); 49 | } else { 50 | rootDocs.push(docItem); 51 | } 52 | }); 53 | 54 | return { 55 | workspace: { 56 | id: workspace.id!, 57 | name: workspace.name!, 58 | description: workspace.description || '', 59 | kind: workspace.kind || '', 60 | created_at: workspace.created_at || '', 61 | state: workspace.state || '', 62 | is_default_workspace: workspace.is_default_workspace || false, 63 | owners_subscribers: (workspace.owners_subscribers || []) 64 | .filter( 65 | (owner): owner is NonNullable => 66 | owner != null && owner.id != null && owner.name != null && owner.email != null, 67 | ) 68 | .map((owner) => ({ 69 | id: owner.id!, 70 | name: owner.name!, 71 | email: owner.email!, 72 | })), 73 | }, 74 | folders: Array.from(folderMap.values()), 75 | root_items: { 76 | boards: rootBoards, 77 | docs: rootDocs, 78 | }, 79 | }; 80 | } 81 | -------------------------------------------------------------------------------- /docs/version-bumping.md: -------------------------------------------------------------------------------- 1 | # Automated Version Bumping 2 | 3 | This repository uses automated version bumping based on Pull Request labels. When you merge a PR, the version will be automatically bumped and a new release will be created. 4 | 5 | ## How it Works 6 | 7 | ### Version Control with Labels 8 | 9 | Add one of these labels to your Pull Request to control the version bump: 10 | 11 | - **`bump:major`** - For breaking changes (1.0.0 → 2.0.0) 12 | - **`bump:minor`** - For new features (1.0.0 → 1.1.0) 13 | - **`bump:patch`** - For bug fixes (1.0.0 → 1.0.1) 14 | 15 | ### Default Behavior 16 | 17 | If no bump label is added, the version will be bumped as a **patch** release by default. 18 | 19 | ### What Happens When You Work 20 | 21 | #### 1. During PR Review (Preview) 22 | 23 | - **Workflow**: "Version Check" 24 | - **Trigger**: When you add a bump label 25 | - **Action**: Shows a preview comment of what version will be bumped 26 | - **Note**: This is just a preview - nothing is actually changed! 27 | 28 | #### 2. After PR Merge (Actual Release) 29 | 30 | - **Workflow**: "Release" 31 | - **Trigger**: When PR is merged to master 32 | - **Actions**: 33 | - Updates all package.json files with new version 34 | - Creates git tag (e.g., `v1.2.3`) 35 | - Creates GitHub release 36 | - Triggers NPM publish 37 | 38 | ## Workflow Examples 39 | 40 | ### Adding a New Feature 41 | 42 | ``` 43 | 1. Create PR with your feature 44 | 2. Add label: `bump:minor` 45 | 3. See preview comment: "1.0.0 → 1.1.0" 46 | 4. Merge PR 47 | 5. "Release" workflow runs automatically 48 | ``` 49 | 50 | ### Fixing a Bug 51 | 52 | ``` 53 | 1. Create PR with your fix 54 | 2. Add label: `bump:patch` (or no label) 55 | 3. See preview comment: "1.1.0 → 1.1.1" 56 | 4. Merge PR 57 | 5. "Release" workflow runs automatically 58 | ``` 59 | 60 | ### Breaking Change 61 | 62 | ``` 63 | 1. Create PR with breaking change 64 | 2. Add label: `bump:major` 65 | 3. See preview comment: "1.1.1 → 2.0.0" 66 | 4. Merge PR 67 | 5. "Release" workflow runs automatically 68 | ``` 69 | 70 | ## Manual Override 71 | 72 | You can also manually trigger publishing by: 73 | 74 | 1. Going to Actions → "Publish Package to NPM" 75 | 2. Clicking "Run workflow" 76 | 3. This will publish the current versions without bumping 77 | 78 | ## Skipping Releases 79 | 80 | To merge changes without creating a release, don't add any bump labels and include `[skip ci]` in your commit message. 81 | 82 | ## Monorepo Behavior 83 | 84 | This setup treats all packages as a unified version. When any package changes, all packages get the same new version number. This ensures consistency across the monorepo. 85 | 86 | ### Current Packages 87 | 88 | - `@mondaydotcomorg/agent-toolkit` 89 | - `@mondaydotcomorg/monday-api-mcp` 90 | - Root package: `monday-ai` 91 | 92 | ## Workflow Summary 93 | 94 | | Workflow Name | When It Runs | What It Does | 95 | |---------------|--------------|--------------| 96 | | **Version Check** | PR labeled with `bump:*` | Shows preview comment | 97 | | **Release** | PR merged to master | Actually bumps version & releases | 98 | | **Publish Package to NPM** | Tag created or manual trigger | Publishes to NPM | 99 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/test-utils/mock-api-client.ts: -------------------------------------------------------------------------------- 1 | import { ApiClient } from "@mondaydotcomorg/api"; 2 | import { MondayAgentToolkitConfig, ToolMode } from "src/core/monday-agent-toolkit"; 3 | import { MondayAgentToolkit } from "src/mcp/toolkit"; 4 | 5 | export interface MockApiResponse { 6 | data?: T; 7 | errors?: Array<{ 8 | message: string; 9 | path?: string[]; 10 | }>; 11 | } 12 | 13 | /** 14 | * Creates a mock API client for testing 15 | * @returns An object with the mock API client and helper functions 16 | */ 17 | export function createMockApiClient() { 18 | const mockRequest = jest.fn(); 19 | const mockApiClient = { 20 | request: mockRequest 21 | } as any; 22 | 23 | return { 24 | mockApiClient, 25 | mockRequest, 26 | 27 | setResponse: (data: any) => mockRequest.mockResolvedValue(data), 28 | setResponseOnce: (data: any) => mockRequest.mockResolvedValueOnce(data), 29 | 30 | setError: (messageOrError: string | Error, path: string[] = []) => { 31 | if (typeof messageOrError === 'string') { 32 | const error = new Error(messageOrError); 33 | (error as any).errors = [{ message: messageOrError, path }]; 34 | mockRequest.mockRejectedValue(error); 35 | } else { 36 | mockRequest.mockRejectedValue(messageOrError); 37 | } 38 | }, 39 | 40 | 41 | reset: () => { 42 | mockRequest.mockReset(); 43 | }, 44 | 45 | getMockRequest: () => mockRequest 46 | }; 47 | } 48 | 49 | /** 50 | * Calls a tool by name and returns the parsed result. It's suggested to mock the API client and set the response before calling this function. 51 | * @param toolName - The name of the tool to call 52 | * @param args - The arguments to pass to the tool 53 | * @returns The parsed result of the tool ca ll 54 | */ 55 | export async function callToolByNameAsync(toolName: string, args: any, config?: MondayAgentToolkitConfig): Promise { 56 | const result = await callToolByNameRawAsync(toolName, args, config); 57 | 58 | const parsedResult = JSON.parse(result.content[0].text); 59 | return parsedResult; 60 | } 61 | 62 | /** 63 | * Calls a tool by name and returns the raw result. It's suggested to mock the API client and set the response before calling this function. 64 | * @param toolName - The name of the tool to call 65 | * @param args - The arguments to pass to the tool 66 | * @returns The raw result of the tool call 67 | */ 68 | export async function callToolByNameRawAsync(toolName: string, args: any, config?: MondayAgentToolkitConfig): Promise { 69 | config ??= {mondayApiToken: 'test-token', toolsConfiguration: { mode: ToolMode.API } }; 70 | const toolkit = new MondayAgentToolkit(config); 71 | 72 | const toolNames = toolkit.getDynamicToolNames(); 73 | expect(toolNames).toContain(toolName); 74 | expect(toolkit.isToolEnabled(toolName)).toBe(true); 75 | 76 | // Get the registered MCP tool handler 77 | const server = toolkit.getServer(); 78 | const tool = (server as any)._registeredTools[toolName]; 79 | 80 | expect(tool).toBeDefined(); 81 | 82 | // Call the tool through the MCP interface 83 | const result = await tool.callback(args, {}); 84 | return result; 85 | } -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-board-activity/get-board-activity-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | GetBoardAllActivityQuery, 4 | GetBoardAllActivityQueryVariables, 5 | } from '../../../../monday-graphql/generated/graphql/graphql'; 6 | import { getBoardAllActivity } from './get-board-activity.graphql'; 7 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 8 | import { BaseMondayApiTool, createMondayApiAnnotations } from './../base-monday-api-tool'; 9 | import { TIME_IN_MILLISECONDS } from '../../../../utils'; 10 | 11 | export const getBoardActivityToolSchema = { 12 | boardId: z.number().describe('The id of the board to get activity for'), 13 | fromDate: z 14 | .string() 15 | .optional() 16 | .describe('Start date for activity range (ISO8601DateTime format). Defaults to 30 days ago'), 17 | toDate: z.string().optional().describe('End date for activity range (ISO8601DateTime format). Defaults to now'), 18 | }; 19 | 20 | export class GetBoardActivityTool extends BaseMondayApiTool { 21 | name = 'get_board_activity'; 22 | type = ToolType.READ; 23 | annotations = createMondayApiAnnotations({ 24 | title: 'Get Board Activity', 25 | readOnlyHint: true, 26 | destructiveHint: false, 27 | idempotentHint: true, 28 | }); 29 | 30 | private defaultLimit = 1000; 31 | 32 | getDescription(): string { 33 | return 'Get board activity logs for a specified time range (defaults to last 30 days)'; 34 | } 35 | 36 | getInputSchema(): typeof getBoardActivityToolSchema { 37 | return getBoardActivityToolSchema; 38 | } 39 | 40 | protected async executeInternal( 41 | input: ToolInputType, 42 | ): Promise> { 43 | // Calculate default date range (last 30 days) 44 | const now = new Date(); 45 | const thirtyDaysAgo = new Date(now.getTime() - TIME_IN_MILLISECONDS.MONTH30Days); 46 | 47 | const fromDate = input?.fromDate || thirtyDaysAgo.toISOString(); 48 | const toDate = input?.toDate || now.toISOString(); 49 | 50 | const variables: GetBoardAllActivityQueryVariables = { 51 | boardId: input.boardId.toString(), 52 | fromDate, 53 | toDate, 54 | limit: this.defaultLimit, 55 | page: 1, 56 | }; 57 | 58 | const res = await this.mondayApi.request(getBoardAllActivity, variables); 59 | 60 | const activityLogs = res.boards?.[0]?.activity_logs; 61 | 62 | if (!activityLogs || activityLogs.length === 0) { 63 | return { 64 | content: `No activity found for board ${input.boardId} in the specified time range (${fromDate} to ${toDate}).`, 65 | }; 66 | } 67 | 68 | const formattedActivity = activityLogs 69 | .filter((log): log is NonNullable => log !== null && log !== undefined) 70 | .map((log) => { 71 | return `• ${log.created_at}: ${log.event} on ${log.entity} by user ${log.user_id}${log.data ? ` - Data: ${log.data}` : ''}`; 72 | }) 73 | .join('\n'); 74 | 75 | return { 76 | content: `Activity logs for board ${input.boardId} from ${fromDate} to ${toDate} (${activityLogs.length} entries): 77 | 78 | ${formattedActivity}`, 79 | }; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-timeline-item-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | CreateTimelineItemMutation, 4 | CreateTimelineItemMutationVariables, 5 | } from '../../../monday-graphql/generated/graphql/graphql'; 6 | import { createTimelineItem } from '../../../monday-graphql/queries.graphql'; 7 | import { ToolInputType, ToolOutputType, ToolType } from '../../tool'; 8 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 9 | 10 | export const createTimelineItemToolSchema = { 11 | item_id: z.number().describe('The ID of the item to create the new timeline item on'), 12 | custom_activity_id: z.string().describe('The ID of the custom activity for the timeline item'), 13 | title: z.string().describe('The title of the new timeline item'), 14 | summary: z.string().optional().describe('The summary of the new timeline item (max 255 characters)'), 15 | content: z.string().optional().describe('The content of the new timeline item'), 16 | timestamp: z 17 | .string() 18 | .describe('The creation time of the new timeline item in ISO8601 format (e.g., 2024-06-06T18:00:30Z)'), 19 | start_timestamp: z.string().optional().describe('The start time of the timeline item in ISO8601 format'), 20 | end_timestamp: z.string().optional().describe('The end time of the timeline item in ISO8601 format'), 21 | location: z.string().optional().describe('The location to add to the new timeline item'), 22 | phone: z.string().optional().describe('The phone number to add to the new timeline item'), 23 | url: z.string().optional().describe('The URL to add to the new timeline item'), 24 | }; 25 | 26 | export class CreateTimelineItemTool extends BaseMondayApiTool { 27 | name = 'create_timeline_item'; 28 | type = ToolType.WRITE; 29 | annotations = createMondayApiAnnotations({ 30 | title: 'Create Timeline Item', 31 | readOnlyHint: false, 32 | destructiveHint: false, 33 | idempotentHint: false, 34 | }); 35 | 36 | getDescription(): string { 37 | return 'Create a new timeline item in the E&A app'; 38 | } 39 | 40 | getInputSchema(): typeof createTimelineItemToolSchema { 41 | return createTimelineItemToolSchema; 42 | } 43 | 44 | protected async executeInternal( 45 | input: ToolInputType, 46 | ): Promise> { 47 | const variables: CreateTimelineItemMutationVariables = { 48 | item_id: input.item_id.toString(), 49 | custom_activity_id: input.custom_activity_id, 50 | title: input.title, 51 | timestamp: input.timestamp, 52 | summary: input.summary, 53 | content: input.content, 54 | location: input.location, 55 | phone: input.phone, 56 | url: input.url, 57 | }; 58 | 59 | if (input.start_timestamp && input.end_timestamp) { 60 | variables.time_range = { 61 | start_timestamp: input.start_timestamp, 62 | end_timestamp: input.end_timestamp, 63 | }; 64 | } 65 | 66 | const res = await this.mondayApi.request(createTimelineItem, variables); 67 | 68 | return { 69 | content: `Timeline item '${input.title}' with ID ${res.create_timeline_item?.id} successfully created on item ${input.item_id}`, 70 | }; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workforms-tools/utils/form-questions-editor-tool-helpers.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CreateFormQuestionMutation, 3 | CreateFormQuestionMutationVariables, 4 | DeleteFormQuestionMutation, 5 | DeleteFormQuestionMutationVariables, 6 | UpdateFormQuestionMutation, 7 | UpdateFormQuestionMutationVariables, 8 | } from '../../../../../monday-graphql/generated/graphql/graphql'; 9 | import { createFormQuestion, deleteFormQuestion, updateFormQuestion } from '../workforms.graphql'; 10 | import { ToolInputType, ToolOutputType } from '../../../../tool'; 11 | import { ApiClient } from '@mondaydotcomorg/api'; 12 | import { formQuestionsEditorToolSchema } from '../form-questions-editor-tool/schema'; 13 | 14 | export class FormQuestionsEditorToolHelpers { 15 | constructor(private mondayApi: ApiClient) {} 16 | 17 | async deleteQuestion(input: ToolInputType): Promise> { 18 | const questionId = input.questionId; 19 | if (!questionId) { 20 | return { 21 | content: `Question ID is required when deleting a question.`, 22 | }; 23 | } 24 | 25 | const deleteVariables: DeleteFormQuestionMutationVariables = { 26 | formToken: input.formToken, 27 | questionId, 28 | }; 29 | 30 | await this.mondayApi.request(deleteFormQuestion, deleteVariables); 31 | 32 | return { 33 | content: `Form question with id ${questionId} deleted successfully.`, 34 | }; 35 | } 36 | 37 | async updateQuestion(input: ToolInputType): Promise> { 38 | const questionId = input.questionId; 39 | if (!questionId) { 40 | return { 41 | content: `Question ID is required when updating a question.`, 42 | }; 43 | } 44 | 45 | const question = input.question; 46 | if (!question) { 47 | return { 48 | content: `Must provide updated patch props for the question when updating.`, 49 | }; 50 | } 51 | 52 | const updateVariables: UpdateFormQuestionMutationVariables = { 53 | formToken: input.formToken, 54 | questionId, 55 | question, 56 | }; 57 | 58 | await this.mondayApi.request(updateFormQuestion, updateVariables); 59 | 60 | return { 61 | content: `Form question with id ${questionId} updated successfully.`, 62 | }; 63 | } 64 | 65 | async createQuestion(input: ToolInputType): Promise> { 66 | const question = input.question; 67 | if (!question) { 68 | return { 69 | content: `Must provide a full question payload when creating a question.`, 70 | }; 71 | } 72 | 73 | if (!question.title) { 74 | return { 75 | content: `Must provide a title for the question when creating a question.`, 76 | }; 77 | } 78 | 79 | const createVariables: CreateFormQuestionMutationVariables = { 80 | formToken: input.formToken, 81 | question: { 82 | ...question, 83 | title: question.title, 84 | }, 85 | }; 86 | 87 | const result = await this.mondayApi.request(createFormQuestion, createVariables); 88 | 89 | return { 90 | content: `Form question created successfully. ID: ${result.create_form_question?.id}`, 91 | }; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/base-monday-api-tool.ts: -------------------------------------------------------------------------------- 1 | import { ApiClient } from '@mondaydotcomorg/api'; 2 | import { ZodRawShape } from 'zod'; 3 | import { ToolAnnotations } from '@modelcontextprotocol/sdk/types'; 4 | import { Tool, ToolInputType, ToolOutputType, ToolType } from '../../tool'; 5 | import { trackEvent } from '../../../utils/tracking.utils'; 6 | import { extractTokenInfo } from '../../../utils/token.utils'; 7 | 8 | export type MondayApiToolContext = { 9 | // Operational context 10 | boardId?: number; 11 | 12 | // Agent metadata (for tracking) 13 | agentType?: string; 14 | agentClientName?: string; 15 | clientRedirectUris?: string[]; 16 | }; 17 | 18 | export type BaseMondayApiToolConstructor = new (api: ApiClient, token?: string) => BaseMondayApiTool; 19 | 20 | // Helper function to merge annotations with default openWorldHint 21 | export function createMondayApiAnnotations(annotations: ToolAnnotations): ToolAnnotations { 22 | return { 23 | openWorldHint: true, 24 | ...annotations, 25 | }; 26 | } 27 | 28 | export abstract class BaseMondayApiTool< 29 | Input extends ZodRawShape | undefined, 30 | Output extends Record = never, 31 | > implements Tool 32 | { 33 | abstract name: string; 34 | abstract type: ToolType; 35 | abstract annotations: ToolAnnotations; 36 | enabledByDefault?: boolean; 37 | 38 | constructor( 39 | protected readonly mondayApi: ApiClient, 40 | protected readonly apiToken?: string, 41 | protected readonly context?: MondayApiToolContext, 42 | ) {} 43 | 44 | abstract getDescription(): string; 45 | abstract getInputSchema(): Input; 46 | 47 | /** 48 | * Public execute method that automatically tracks execution 49 | */ 50 | async execute(input?: ToolInputType): Promise> { 51 | const startTime = Date.now(); 52 | let isError = false; 53 | 54 | try { 55 | const result = await this.executeInternal(input); 56 | return result; 57 | } catch (error) { 58 | isError = true; 59 | throw error; 60 | } finally { 61 | const executionTimeInMs = Date.now() - startTime; 62 | this.trackToolExecution(this.name, executionTimeInMs, isError); 63 | } 64 | } 65 | 66 | /** 67 | * Abstract method that subclasses should implement for their actual logic 68 | */ 69 | protected abstract executeInternal(input?: ToolInputType): Promise>; 70 | 71 | /** 72 | * Tracks tool execution with timing and error information 73 | * @param toolName - The name of the tool being executed 74 | * @param executionTimeInMs - The time taken to execute the tool in milliseconds 75 | * @param isError - Whether the execution resulted in an error 76 | * @param params - The parameters passed to the tool 77 | */ 78 | private trackToolExecution( 79 | toolName: string, 80 | executionTimeMs: number, 81 | isError: boolean, 82 | params?: Record, 83 | ): void { 84 | const tokenInfo = this.apiToken ? extractTokenInfo(this.apiToken) : {}; 85 | 86 | trackEvent({ 87 | name: 'monday_mcp_tool_execution', 88 | data: { 89 | toolName, 90 | executionTimeMs, 91 | isError, 92 | params, 93 | toolType: 'monday_api_tool', 94 | ...(this.context || {}), 95 | ...tokenInfo, 96 | }, 97 | }); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/update-folder-tool/update-folder-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { updateFolder } from './update-folder-tool.graphql'; 3 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 4 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 5 | import { FolderColor, FolderFontWeight, FolderCustomIcon, ObjectType } from 'src/monday-graphql/generated/graphql/graphql'; 6 | 7 | export const updateFolderToolSchema = { 8 | folderId: z.string().describe('The ID of the folder to update'), 9 | name: z.string().optional().describe('The new name of the folder'), 10 | color: z.nativeEnum(FolderColor).optional().describe('The new color of the folder'), 11 | fontWeight: z.nativeEnum(FolderFontWeight).optional().describe('The new font weight of the folder'), 12 | customIcon: z.nativeEnum(FolderCustomIcon).optional().describe('The new custom icon of the folder'), 13 | parentFolderId: z.string().optional().describe('The ID of the new parent folder'), 14 | workspaceId: z.string().optional().describe('The ID of the workspace containing the folder'), 15 | accountProductId: z.string().optional().describe('The account product ID associated with the folder'), 16 | position_object_id: z.string().optional().describe('The ID of the object to position the folder relative to. If this parameter is provided, position_object_type must be also provided.'), 17 | position_object_type: z.nativeEnum(ObjectType).optional().describe('The type of object to position the folder relative to. If this parameter is provided, position_object_id must be also provided.'), 18 | position_is_after: z.boolean().optional().describe('Whether to position the folder after the object'), 19 | }; 20 | 21 | export type UpdateFolderToolInput = typeof updateFolderToolSchema; 22 | 23 | export class UpdateFolderTool extends BaseMondayApiTool { 24 | name = 'update_folder'; 25 | type = ToolType.WRITE; 26 | annotations = createMondayApiAnnotations({ 27 | title: 'Update Folder', 28 | readOnlyHint: false, 29 | destructiveHint: false, 30 | idempotentHint: true, 31 | }); 32 | 33 | getDescription(): string { 34 | return 'Update an existing folder in monday.com'; 35 | } 36 | 37 | getInputSchema(): UpdateFolderToolInput { 38 | return updateFolderToolSchema; 39 | } 40 | 41 | protected async executeInternal(input: ToolInputType): Promise> { 42 | const { position_object_id, position_object_type, position_is_after } = input; 43 | 44 | if (!!position_object_id !== !!position_object_type) { 45 | throw new Error('position_object_id and position_object_type must be provided together'); 46 | } 47 | 48 | const variables = { 49 | folderId: input.folderId, 50 | name: input.name, 51 | color: input.color, 52 | fontWeight: input.fontWeight, 53 | customIcon: input.customIcon, 54 | parentFolderId: input.parentFolderId, 55 | workspaceId: input.workspaceId, 56 | accountProductId: input.accountProductId, 57 | position: !position_object_id ? undefined : { 58 | position_is_after, 59 | position_object_id, 60 | position_object_type 61 | }, 62 | }; 63 | 64 | const res = await this.mondayApi.request<{ update_folder: { id: string } }>(updateFolder, variables); 65 | 66 | return { 67 | content: `Folder ${res.update_folder?.id} successfully updated`, 68 | }; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/create-update-tool/create-update-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { 3 | CreateUpdateMutation, 4 | CreateUpdateMutationVariables, 5 | MentionType, 6 | UpdateMention, 7 | } from '../../../../monday-graphql/generated/graphql/graphql'; 8 | import { createUpdate } from './create-update.graphql'; 9 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 10 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 11 | import { rethrowWithContext } from '../../../../utils'; 12 | 13 | export const mentionSchema = z.object({ 14 | id: z.string().describe('The ID of the entity to mention'), 15 | type: z.nativeEnum(MentionType).describe('The type of mention: User, Team, Board, or Project'), 16 | }); 17 | 18 | export const mentionsListSchema = z.array(mentionSchema); 19 | 20 | export const createUpdateToolSchema = { 21 | itemId: z.number().describe('The id of the item to which the update will be added'), 22 | body: z 23 | .string() 24 | .describe('The update text to be created. Do not use @ to mention users, use the mentionsList field instead.'), 25 | mentionsList: z 26 | .string() 27 | .optional() 28 | .describe( 29 | 'Optional JSON array of mentions in the format: [{"id": "123", "type": "User"}, {"id": "456", "type": "Team"}]. Valid types are: User, Team, Board, Project', 30 | ), 31 | }; 32 | 33 | export class CreateUpdateTool extends BaseMondayApiTool { 34 | name = 'create_update'; 35 | type = ToolType.WRITE; 36 | annotations = createMondayApiAnnotations({ 37 | title: 'Create Update', 38 | readOnlyHint: false, 39 | destructiveHint: false, 40 | idempotentHint: false, 41 | }); 42 | 43 | getDescription(): string { 44 | return 'Create a new update (comment/post) on a monday.com item. Updates can be used to add comments, notes, or discussions to items. You can optionally mention users, teams, or boards in the update.'; 45 | } 46 | 47 | getInputSchema(): typeof createUpdateToolSchema { 48 | return createUpdateToolSchema; 49 | } 50 | 51 | protected async executeInternal(input: ToolInputType): Promise> { 52 | let parsedMentionsList: Array | undefined; 53 | 54 | if (input.mentionsList) { 55 | try { 56 | const parsedJson = JSON.parse(input.mentionsList); 57 | const validationResult = mentionsListSchema.safeParse(parsedJson); 58 | 59 | if (!validationResult.success) { 60 | throw new Error(`Invalid mentionsList format: ${validationResult.error.message}`); 61 | } 62 | 63 | parsedMentionsList = validationResult.data; 64 | } catch (error) { 65 | throw new Error(`Invalid mentionsList JSON format: ${(error as Error).message}`); 66 | } 67 | } 68 | 69 | try { 70 | const variables: CreateUpdateMutationVariables = { 71 | itemId: input.itemId.toString(), 72 | body: input.body, 73 | mentionsList: parsedMentionsList, 74 | }; 75 | 76 | const res = await this.mondayApi.request(createUpdate, variables); 77 | 78 | if (!res.create_update?.id) { 79 | throw new Error('Failed to create update: no update created'); 80 | } 81 | 82 | return { 83 | content: `Update ${res.create_update.id} successfully created on item ${input.itemId}`, 84 | }; 85 | } catch (error) { 86 | rethrowWithContext(error, 'create update'); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/list-users-and-teams-tool/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Type definitions for list_users_and_teams tool responses 3 | */ 4 | 5 | // Base team structure (minimal - for efficient queries) 6 | export interface BaseTeam { 7 | __typename?: 'Team'; 8 | id: string; 9 | name: string; 10 | } 11 | 12 | // Extended team structure (includes owners and members) 13 | export interface ExtendedTeam extends BaseTeam { 14 | is_guest?: boolean | null; 15 | picture_url?: string | null; 16 | owners: Array<{ 17 | __typename?: 'User'; 18 | id: string; 19 | name: string; 20 | email: string; 21 | }>; 22 | users?: Array<{ 23 | __typename?: 'User'; 24 | id: string; 25 | name: string; 26 | email: string; 27 | title?: string | null; 28 | is_admin?: boolean | null; 29 | is_guest?: boolean | null; 30 | is_pending?: boolean | null; 31 | is_verified?: boolean | null; 32 | is_view_only?: boolean | null; 33 | join_date?: any | null; 34 | last_activity?: any | null; 35 | location?: string | null; 36 | mobile_phone?: string | null; 37 | phone?: string | null; 38 | photo_thumb?: string | null; 39 | time_zone_identifier?: string | null; 40 | utc_hours_diff?: number | null; 41 | } | null> | null; 42 | } 43 | 44 | // User structure (for team memberships) 45 | export interface UserTeam { 46 | __typename?: 'Team'; 47 | id: string; 48 | name: string; 49 | is_guest?: boolean | null; 50 | picture_url?: string | null; 51 | } 52 | 53 | // User structure 54 | export interface User { 55 | __typename?: 'User'; 56 | id: string; 57 | name: string; 58 | title?: string | null; 59 | email: string; 60 | enabled: boolean; 61 | is_admin?: boolean | null; 62 | is_guest?: boolean | null; 63 | is_pending?: boolean | null; 64 | is_verified?: boolean | null; 65 | is_view_only?: boolean | null; 66 | join_date?: any | null; 67 | last_activity?: any | null; 68 | location?: string | null; 69 | mobile_phone?: string | null; 70 | phone?: string | null; 71 | photo_thumb?: string | null; 72 | time_zone_identifier?: string | null; 73 | utc_hours_diff?: number | null; 74 | teams?: Array | null; 75 | } 76 | 77 | // Response types for different query scenarios 78 | export interface UsersOnlyResponse { 79 | __typename?: 'Query'; 80 | users?: Array | null; 81 | } 82 | 83 | export interface TeamsResponse { 84 | __typename?: 'Query'; 85 | teams?: Array<(BaseTeam | ExtendedTeam) | null> | null; 86 | } 87 | 88 | export interface UsersAndTeamsResponse { 89 | __typename?: 'Query'; 90 | users?: Array | null; 91 | teams?: Array<(BaseTeam | ExtendedTeam) | null> | null; 92 | } 93 | 94 | // Union type for all possible responses 95 | export type FormattedResponse = 96 | | UsersOnlyResponse 97 | | TeamsResponse 98 | | UsersAndTeamsResponse; 99 | 100 | // Type guards 101 | export function isUsersOnlyResponse(data: FormattedResponse): data is UsersOnlyResponse { 102 | return 'users' in data && !('teams' in data); 103 | } 104 | 105 | export function isTeamsResponse(data: FormattedResponse): data is TeamsResponse { 106 | return 'teams' in data && !('users' in data); 107 | } 108 | 109 | export function isUsersAndTeamsResponse(data: FormattedResponse): data is UsersAndTeamsResponse { 110 | return 'users' in data && 'teams' in data; 111 | } 112 | 113 | export function isExtendedTeam(team: BaseTeam | ExtendedTeam): team is ExtendedTeam { 114 | return 'owners' in team; 115 | } 116 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/workspace-info-tool/workspace-info-tool.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; 3 | import { BaseMondayApiTool, createMondayApiAnnotations } from '../base-monday-api-tool'; 4 | import { getWorkspaceInfo } from '../../../../monday-graphql/queries.graphql'; 5 | import { organizeWorkspaceInfoHierarchy } from './helpers'; 6 | import { GetWorkspaceInfoQuery } from 'src/monday-graphql/generated/graphql/graphql'; 7 | 8 | export const workspaceInfoToolSchema = { 9 | workspace_id: z.number().describe('The ID of the workspace to get information for'), 10 | }; 11 | 12 | export class WorkspaceInfoTool extends BaseMondayApiTool { 13 | name = 'workspace_info'; 14 | type = ToolType.READ; 15 | annotations = createMondayApiAnnotations({ 16 | title: 'Get Workspace Information', 17 | readOnlyHint: true, 18 | destructiveHint: false, 19 | idempotentHint: true, 20 | }); 21 | 22 | getDescription(): string { 23 | return 'This tool returns the boards, docs and folders in a workspace and which folder they are in. It returns up to 100 of each object type, if you receive 100 assume there are additional objects of that type in the workspace.'; 24 | } 25 | 26 | getInputSchema(): typeof workspaceInfoToolSchema { 27 | return workspaceInfoToolSchema; 28 | } 29 | 30 | protected async executeInternal( 31 | input: ToolInputType, 32 | ): Promise> { 33 | const variables = { 34 | workspace_id: input.workspace_id, 35 | }; 36 | 37 | const res = await this.mondayApi.request(getWorkspaceInfo, variables); 38 | 39 | if (!res.workspaces || res.workspaces.length === 0) { 40 | return { 41 | content: `No workspace found with ID ${input.workspace_id}`, 42 | }; 43 | } 44 | 45 | const organizedInfo = organizeWorkspaceInfoHierarchy(res); 46 | 47 | return { 48 | content: `Workspace Information: 49 | 50 | **Workspace:** ${organizedInfo.workspace.name} (ID: ${organizedInfo.workspace.id}) 51 | - Description: ${organizedInfo.workspace.description || 'No description'} 52 | - Kind: ${organizedInfo.workspace.kind} 53 | - State: ${organizedInfo.workspace.state} 54 | - Default Workspace: ${organizedInfo.workspace.is_default_workspace ? 'Yes' : 'No'} 55 | - Created: ${organizedInfo.workspace.created_at} 56 | - Owners/Subscribers: ${organizedInfo.workspace.owners_subscribers.length} users 57 | 58 | **Folders (${organizedInfo.folders.length}):** 59 | ${organizedInfo.folders 60 | .map( 61 | (folder: any) => ` 62 | 📁 ${folder.name} (ID: ${folder.id}) 63 | - Boards (${folder.boards.length}): ${folder.boards.map((b: any) => `${b.name} (${b.id})`).join(', ') || 'None'} 64 | - Docs (${folder.docs.length}): ${folder.docs.map((d: any) => `${d.name} (${d.id})`).join(', ') || 'None'}`, 65 | ) 66 | .join('\n')} 67 | 68 | **Root Level Items:** 69 | - Boards (${organizedInfo.root_items.boards.length}): ${organizedInfo.root_items.boards.map((b: any) => `${b.name} (${b.id})`).join(', ') || 'None'} 70 | - Docs (${organizedInfo.root_items.docs.length}): ${organizedInfo.root_items.docs.map((d: any) => `${d.name} (${d.id})`).join(', ') || 'None'} 71 | 72 | **Summary:** 73 | - Total Folders: ${organizedInfo.folders.length} 74 | - Total Boards: ${organizedInfo.folders.reduce((sum: number, f: { boards: string | any[] }) => sum + f.boards.length, 0) + organizedInfo.root_items.boards.length} 75 | - Total Docs: ${organizedInfo.folders.reduce((sum: number, f: { docs: string | any[] }) => sum + f.docs.length, 0) + organizedInfo.root_items.docs.length} 76 | 77 | ${JSON.stringify(organizedInfo, null, 2)}`, 78 | }; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /packages/agent-toolkit/src/core/tools/platform-api-tools/get-graphql-schema-tool.ts: -------------------------------------------------------------------------------- 1 | import { ToolOutputType, ToolType, ToolInputType } from '../../tool'; 2 | import { BaseMondayApiTool, createMondayApiAnnotations } from './base-monday-api-tool'; 3 | import { getGraphQLSchema } from '../../../monday-graphql/queries.graphql'; 4 | import { GetGraphQlSchemaQuery } from 'src/monday-graphql/generated/graphql/graphql'; 5 | import { z } from 'zod'; 6 | 7 | export const getGraphQLSchemaToolSchema = { 8 | random_string: z.string().describe('Dummy parameter for no-parameter tools').optional(), 9 | operationType: z 10 | .enum(['read', 'write']) 11 | .describe('Type of operation: "read" for queries, "write" for mutations') 12 | .optional(), 13 | }; 14 | 15 | export class GetGraphQLSchemaTool extends BaseMondayApiTool { 16 | name = 'get_graphql_schema'; 17 | type = ToolType.ALL_API; 18 | annotations = createMondayApiAnnotations({ 19 | title: 'Get GraphQL Schema', 20 | readOnlyHint: true, 21 | destructiveHint: false, 22 | idempotentHint: true, 23 | }); 24 | 25 | getDescription(): string { 26 | return 'Fetch the monday.com GraphQL schema structure including query and mutation definitions. This tool returns available query fields, mutation fields, and a list of GraphQL types in the schema. You can filter results by operation type (read/write) to focus on either queries or mutations.'; 27 | } 28 | 29 | getInputSchema(): typeof getGraphQLSchemaToolSchema { 30 | return getGraphQLSchemaToolSchema; 31 | } 32 | 33 | protected async executeInternal( 34 | input?: ToolInputType, 35 | ): Promise> { 36 | try { 37 | const res = await this.mondayApi.request(getGraphQLSchema); 38 | const operationType = input?.operationType; 39 | 40 | const queryFields = 41 | res.queryType?.fields 42 | ?.map((field) => `- ${field.name}${field.description ? `: ${field.description}` : ''}`) 43 | .join('\n') || 'No query fields found'; 44 | 45 | const mutationFields = 46 | res.mutationType?.fields 47 | ?.map((field) => `- ${field.name}${field.description ? `: ${field.description}` : ''}`) 48 | .join('\n') || 'No mutation fields found'; 49 | 50 | const schemaAny = res.__schema as any; 51 | const typesList = 52 | schemaAny?.types 53 | ?.filter((type: any) => type.name && !type.name.startsWith('__')) // Filter out introspection types 54 | .map((type: any) => `- ${type.name} (${type.kind || 'unknown'})`) 55 | .join('\n') || 'No types found'; 56 | 57 | // Build response based on operation type 58 | let formattedResponse = '## GraphQL Schema\n'; 59 | 60 | if (!operationType || operationType === 'read') { 61 | formattedResponse += `- Query Type: ${res.__schema?.queryType?.name}\n\n`; 62 | formattedResponse += `## Query Fields\n${queryFields}\n\n`; 63 | } 64 | 65 | if (!operationType || operationType === 'write') { 66 | formattedResponse += `- Mutation Type: ${res.__schema?.mutationType?.name}\n\n`; 67 | formattedResponse += `## Mutation Fields\n${mutationFields}\n\n`; 68 | } 69 | 70 | formattedResponse += `## Available Types\n${typesList}\n\n`; 71 | formattedResponse += `To get detailed information about a specific type, use the get_type_details tool with the type name.\nFor example: get_type_details(typeName: "Board") to see Board type details.`; 72 | 73 | return { 74 | content: formattedResponse, 75 | }; 76 | } catch (error) { 77 | return { 78 | content: `Error fetching GraphQL schema: ${error instanceof Error ? error.message : 'Unknown error'}`, 79 | }; 80 | } 81 | } 82 | } 83 | --------------------------------------------------------------------------------