diff --git a/packages/agent-toolkit/package.json b/packages/agent-toolkit/package.json index bf26c97..08dbfaf 100644 --- a/packages/agent-toolkit/package.json +++ b/packages/agent-toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@mondaydotcomorg/agent-toolkit", - "version": "2.0.2", + "version": "2.0.3", "description": "monday.com agent toolkit", "exports": { "./mcp": { @@ -49,6 +49,7 @@ }, "dependencies": { "@mondaydotcomorg/api": "^9.0.1", + "axios": "^1.8.4", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5" }, diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/create-app-feature.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/create-app-feature.ts new file mode 100644 index 0000000..2fb3881 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/create-app-feature.ts @@ -0,0 +1,84 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { CreateAppFeatureResponse, createAppFeatureSchema } from './schemas/app-feature-schemas'; + +export class CreateAppFeatureTool extends BaseMondayAppsTool< + typeof createAppFeatureSchema.shape, + CreateAppFeatureResponse +> { + name = 'monday_apps_create_app_feature'; + category = MondayAppsToolCategory.APP_FEATURE; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Create a new app feature for an app version'; + } + + getInputSchema() { + return createAppFeatureSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { appId, appVersionId, name, type, data } = input; + + // Prepare the request body + const requestBody = { + name, + type, + data: data || {}, + }; + + const response = await this.executeApiRequest( + HttpMethod.POST, + API_ENDPOINTS.APP_FEATURES.CREATE(appId, appVersionId), + { data: requestBody }, + ); + + const { app_feature } = response; + return { + content: `Successfully created app feature '${app_feature.name}' (ID: ${app_feature.id}) of type ${app_feature.type} for app ID ${app_feature.app_id}, version ID ${app_feature.app_version_id}. Feature state: ${app_feature.state}`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to create app feature: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + app_feature: { + id: 0, + app_id: input.appId, + app_version_id: input.appVersionId, + app_feature_reference_id: 0, + source_app_feature_id: null, + name: input.name, + type: input.type, + state: 'error', + user_id: 0, + data: input.data || {}, + schema: null, + status: null, + client_instance_token: '', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + current_release: null, + configured_secret_names: [], + }, + app_feature_reference: { + id: 0, + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + live_app_feature_id: 0, + app_feature_reference_id: 0, + }, + } as CreateAppFeatureResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/get-app-features.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/get-app-features.ts new file mode 100644 index 0000000..7bc476a --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/get-app-features.ts @@ -0,0 +1,64 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { AppFeaturesResponse, getAppFeaturesSchema } from './schemas/app-feature-schemas'; + +export class GetAppFeaturesTool extends BaseMondayAppsTool { + name = 'monday_apps_get_app_features'; + category = MondayAppsToolCategory.APP_FEATURE; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Retrieve app features by app version id'; + } + + getInputSchema() { + return getAppFeaturesSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const { appVersionId, type } = input; + + const query: Record = {}; + if (type) { + query.type = type; + } + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.APP_FEATURES.GET_ALL(appVersionId), + { query }, + ); + + const features = response.appFeatures || []; + const featuresCount = features.length; + + const featuresSummary = features + .map((feature) => `${feature.name} (ID: ${feature.id}, Type: ${feature.type}, State: ${feature.state})`) + .join(', '); + + return { + content: + `Successfully retrieved ${featuresCount} app features for app version ID ${appVersionId}${type ? ` of type ${type}` : ''}.\n` + + `Features: ${featuresSummary || 'No features found'}`, + metadata: { + ...response, + statusCode: response.statusCode, + headers: response.headers, + }, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to retrieve app features: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + appFeatures: [], + } as AppFeaturesResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/index.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/index.ts new file mode 100644 index 0000000..dc597c1 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/index.ts @@ -0,0 +1,7 @@ +import { GetAppFeaturesTool } from './get-app-features'; +import { CreateAppFeatureTool } from './create-app-feature'; + +export const appFeatureTools = [GetAppFeaturesTool, CreateAppFeatureTool]; + +export * from './get-app-features'; +export * from './create-app-feature'; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/schemas/app-feature-schemas.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/schemas/app-feature-schemas.ts new file mode 100644 index 0000000..2ebfce8 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-feature/schemas/app-feature-schemas.ts @@ -0,0 +1,57 @@ +import { z } from 'zod'; +import { MondayApiResponse } from '../../base-tool/monday-apps-tool'; +import { AppFeatureType } from '../../consts/apps.consts'; + +export interface AppFeature { + id: number; + app_id: number; + app_version_id: number; + app_feature_reference_id: number; + source_app_feature_id: number | null; + name: string; + type: AppFeatureType; + state: string; + user_id: number; + data: Record; + schema: boolean | null; + status: string | null; + [key: string]: any; +} + +export interface AppFeaturesResponse extends MondayApiResponse { + appFeatures: AppFeature[]; +} + +export const getAppFeaturesSchema = z.object({ + appVersionId: z.number().describe('The ID of the app version to get features for'), + type: z.nativeEnum(AppFeatureType).optional().describe('Filter by app feature type'), +}); + +export interface AppFeatureReference { + id: number; + created_at: string; + updated_at: string; + live_app_feature_id: number; + app_feature_reference_id: number; +} + +export interface DetailedAppFeature extends AppFeature { + client_instance_token: string; + created_at: string; + updated_at: string; + current_release: string | null; + configured_secret_names: string[]; +} + +export interface CreateAppFeatureResponse extends MondayApiResponse { + app_feature: DetailedAppFeature; + app_feature_reference: AppFeatureReference; +} + +export const createAppFeatureSchema = z.object({ + appId: z.number().describe('The ID of the app'), + appVersionId: z.number().describe('The ID of the app version'), + name: z.string().describe('The name of the app feature'), + type: z.nativeEnum(AppFeatureType).describe('The type of the app feature'), + data: z.record(z.any()).optional().describe('Additional data for the app feature'), +}); diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-version.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-version.ts new file mode 100644 index 0000000..abc393f --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-version.ts @@ -0,0 +1,59 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { AppVersionApiDataResponse, getAppVersionSchema } from './schemas/app-version-schemas'; + +export class GetAppVersionTool extends BaseMondayAppsTool { + name = 'monday_apps_get_app_version'; + category = MondayAppsToolCategory.APP_VERSION; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Retrieve the app version data'; + } + + getInputSchema() { + return getAppVersionSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { versionId } = input; + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.APP_VERSIONS.GET_BY_ID(versionId), + ); + + return { + content: + `Successfully retrieved details for app version ID ${versionId}:\n` + + `Name: ${response.appVersion.name}\n` + + `App ID: ${response.appVersion.appId}\n` + + `Version Number: ${response.appVersion.versionNumber}\n` + + `Status: ${response.appVersion.status}`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to retrieve app version: ${errorMessage}`, + metadata: { + appVersion: { + id: input.versionId, + name: '', + appId: 0, + versionNumber: '', + status: '', + mondayCodeConfig: { + isMultiRegion: false, + }, + }, + } as AppVersionApiDataResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-versions.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-versions.ts new file mode 100644 index 0000000..3005880 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/get-app-versions.ts @@ -0,0 +1,61 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { AppVersionsApiDataResponse, getAppVersionsSchema } from './schemas/app-version-schemas'; + +export class GetAppVersionsTool extends BaseMondayAppsTool< + typeof getAppVersionsSchema.shape, + AppVersionsApiDataResponse +> { + name = 'monday_apps_get_app_versions'; + category = MondayAppsToolCategory.APP_VERSION; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Retrieve all the app versions of an app'; + } + + getInputSchema() { + return getAppVersionsSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { appId } = input; + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.APP_VERSIONS.GET_ALL(appId), + ); + + // Create a detailed summary of versions + const versionsSummary = response.appVersions + .map((version) => + [ + `- Version ${version.versionNumber} (ID: ${version.id})`, + ` Name: ${version.name}`, + ` Status: ${version.status}`, + ].join('\n'), + ) + .join('\n'); + + return { + content: `Successfully retrieved ${response.appVersions.length} versions for app ID ${appId}:\n\n${versionsSummary}`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to retrieve app versions: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + appVersions: [], // Add required appVersions property + } as AppVersionsApiDataResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/index.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/index.ts new file mode 100644 index 0000000..36083c0 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/index.ts @@ -0,0 +1,7 @@ +import { GetAppVersionsTool } from './get-app-versions'; +import { GetAppVersionTool } from './get-app-version'; + +export const appVersionTools = [GetAppVersionsTool, GetAppVersionTool]; + +export * from './get-app-versions'; +export * from './get-app-version'; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/schemas/app-version-schemas.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/schemas/app-version-schemas.ts new file mode 100644 index 0000000..5056400 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app-version/schemas/app-version-schemas.ts @@ -0,0 +1,36 @@ +import { z } from 'zod'; +import { MondayApiResponse } from '../../base-tool/monday-apps-tool'; + +export interface AppVersionsApiDataResponse extends MondayApiResponse { + appVersions: Array<{ + id: number; + name: string; + appId: number; + versionNumber: string; + status: string; + mondayCodeConfig?: { + isMultiRegion: boolean; + }; + }>; +} + +export interface AppVersionApiDataResponse extends MondayApiResponse { + appVersion: { + id: number; + name: string; + appId: number; + versionNumber: string; + status: string; + mondayCodeConfig?: { + isMultiRegion: boolean; + }; + }; +} + +export const getAppVersionsSchema = z.object({ + appId: z.number().describe('The ID of the app to get versions for'), +}); + +export const getAppVersionSchema = z.object({ + versionId: z.number().describe('The ID of the app version to get'), +}); diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app-from-manifest.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app-from-manifest.ts new file mode 100644 index 0000000..999053e --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app-from-manifest.ts @@ -0,0 +1,58 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { CreateAppResponse, createAppSchema } from './schemas/app-schemas'; + +export class CreateAppFromManifestTool extends BaseMondayAppsTool { + name = 'monday_apps_create_app_from_manifest'; + category = MondayAppsToolCategory.APP; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Create a new app from a manifest file (Not ready to use yet)'; + } + + getInputSchema() { + return createAppSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + // Convert base64 to Blob for form data + const manifestData = Buffer.from(input.manifestFile, 'base64'); + + // Create FormData + const formData = new FormData(); + const blob = new Blob([manifestData], { type: 'application/zip' }); + formData.append('file', blob, 'manifest.zip'); + + const response = await this.executeApiRequest( + HttpMethod.POST, + API_ENDPOINTS.APPS.CREATE_FROM_MANIFEST, + { + data: formData, + headers: { + 'Content-Type': 'multipart/form-data', + }, + }, + ); + + return { + content: `Successfully created app- ${JSON.stringify(response)}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to create app from manifest: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + app: { id: 0, name: '' }, + app_version: { id: 0, name: '' }, + }, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app.ts new file mode 100644 index 0000000..93cb334 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/create-app.ts @@ -0,0 +1,46 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { CreateAppResponse, createPlainAppSchema } from './schemas/app-schemas'; + +export class CreateAppTool extends BaseMondayAppsTool { + name = 'monday_apps_create_app'; + category = MondayAppsToolCategory.APP; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Create a new app with basic information'; + } + + getInputSchema() { + return createPlainAppSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const response = await this.executeApiRequest(HttpMethod.POST, API_ENDPOINTS.APPS.CREATE, { + data: { + name: input.name, + description: input.description || '', + }, + }); + + return { + content: `Created app "${input.name}" (ID: ${response.app.id}, Version: ${response.app_version.id})`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to create app: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + app: { id: 0, name: '' }, + app_version: { id: 0, name: '' }, + }, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/get-all-apps.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/get-all-apps.ts new file mode 100644 index 0000000..c1dceac --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/get-all-apps.ts @@ -0,0 +1,48 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { AppApiDataResponse } from './schemas/app-schemas'; + +export class GetAllAppsTool extends BaseMondayAppsTool { + name = 'monday_apps_get_all_apps'; + category = MondayAppsToolCategory.APP; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Retrieve all the development apps that the user has collaboration permissions for'; + } + + getInputSchema() { + return undefined; + } + + async execute(_input?: ToolInputType): Promise> { + try { + const response = await this.executeApiRequest(HttpMethod.GET, API_ENDPOINTS.APPS.GET_ALL); + + // Format the apps data for display + const appsDetails = response.apps + .map((app) => { + const multiRegion = app.mondayCodeConfig?.isMultiRegion ? ' (Multi-Region)' : ''; + return `- ID: ${app.id}, Name: ${app.name}${multiRegion}`; + }) + .join('\n'); + + return { + content: `Retrieved ${response.apps.length} apps:\n${appsDetails}`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to retrieve apps: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + apps: [], // Add required apps property + } as AppApiDataResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/index.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/index.ts new file mode 100644 index 0000000..fd3e360 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/index.ts @@ -0,0 +1,11 @@ +import { GetAllAppsTool } from './get-all-apps'; +import { PromoteAppTool } from './promote-app'; +import { CreateAppFromManifestTool } from './create-app-from-manifest'; +import { CreateAppTool } from './create-app'; + +export const appTools = [GetAllAppsTool, PromoteAppTool, CreateAppFromManifestTool, CreateAppTool]; + +export * from './get-all-apps'; +export * from './promote-app'; +export * from './create-app-from-manifest'; +export * from './create-app'; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/promote-app.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/promote-app.ts new file mode 100644 index 0000000..3ccf776 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/promote-app.ts @@ -0,0 +1,47 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { PromoteAppResponse, promoteAppSchema } from './schemas/app-schemas'; + +export class PromoteAppTool extends BaseMondayAppsTool { + name = 'monday_apps_promote_app'; + category = MondayAppsToolCategory.APP; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Promote an app version to live'; + } + + getInputSchema() { + return promoteAppSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const { appId, versionId } = input; + const data = versionId ? { versionId } : undefined; + + const response = await this.executeApiRequest( + HttpMethod.POST, + API_ENDPOINTS.APPS.PROMOTE(appId), + { data }, + ); + + return { + content: `Successfully started promotion for app ID ${appId}${versionId ? ` and version ID ${versionId}` : ''}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to promote app: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + appId: input.appId, // Add required appId property + } as PromoteAppResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/schemas/app-schemas.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/schemas/app-schemas.ts new file mode 100644 index 0000000..500d66a --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/app/schemas/app-schemas.ts @@ -0,0 +1,44 @@ +import { z } from 'zod'; +import { MondayApiResponse } from '../../base-tool/monday-apps-tool'; + +export interface AppApiDataResponse extends MondayApiResponse { + apps: Array<{ + id: number; + name: string; + mondayCodeConfig?: { + isMultiRegion: boolean; + }; + }>; +} + +export interface PromoteAppResponse extends MondayApiResponse { + appId: number; +} + +export const promoteAppSchema = z.object({ + appId: z.number().describe('The ID of the app to promote'), + versionId: z + .number() + .optional() + .describe('The version ID to promote. If not provided, the latest draft will be used'), +}); + +export interface CreateAppResponse extends MondayApiResponse { + app: { + id: number; + name: string; + }; + app_version: { + id: number; + name: string; + }; +} + +export const createAppSchema = z.object({ + manifestFile: z.string().describe('The base64 encoded manifest file content'), +}); + +export const createPlainAppSchema = z.object({ + name: z.string().describe('The name of the app'), + description: z.string().optional().describe('The description of the app'), +}); diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/base-tool/monday-apps-tool.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/base-tool/monday-apps-tool.ts new file mode 100644 index 0000000..d37716e --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/base-tool/monday-apps-tool.ts @@ -0,0 +1,99 @@ +import axios, { AxiosRequestConfig } from 'axios'; +import * as crypto from 'crypto'; +import * as https from 'https'; +import { ZodRawShape } from 'zod'; +import { Tool, ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { APPS_MS_TIMEOUT_IN_MS } from '../consts/routes.consts'; + +export interface MondayApiResponse { + statusCode: number; + headers?: Record; + [key: string]: any; +} + +export type MondayAppsToolType = new (mondayApiToken?: string) => BaseMondayAppsTool; + +export abstract class BaseMondayAppsTool< + Input extends ZodRawShape | undefined, + Output extends Record = never, +> implements Tool +{ + abstract name: string; + abstract type: ToolType; + abstract category: MondayAppsToolCategory; + private mondayApiToken?: string; + + constructor(mondayApiToken?: string) { + this.mondayApiToken = mondayApiToken; + } + + abstract getDescription(): string; + abstract getInputSchema(): Input; + abstract execute(input?: ToolInputType): Promise>; + + /** + * Execute an API request to the Monday.com API + */ + protected async executeApiRequest( + method: string, + endpoint: string, + options: { + data?: any; + query?: Record; + headers?: Record; + timeout?: number; + } = {}, + ): Promise { + if (!this.mondayApiToken) { + throw new Error('Monday API token is required to execute Monday.com API requests'); + } + + const { data, query, headers = {}, timeout = APPS_MS_TIMEOUT_IN_MS } = options; + const headersWithToken = { + ...headers, + Authorization: `${this.mondayApiToken}`, + 'Content-Type': 'application/json', + }; + + try { + // Create a custom HTTPS agent to handle self-signed certificates + const httpsAgent = new https.Agent({ + secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT, + rejectUnauthorized: false, + }); + + const axiosConfig: AxiosRequestConfig = { + method, + url: endpoint, + data, + headers: headersWithToken, + params: query, + timeout, + httpsAgent, + }; + + const response = await axios.request(axiosConfig); + + return { + ...response.data, + statusCode: response.status, + headers: response.headers as Record, + } as T; + } catch (error: any) { + // Handle different types of errors + if (axios.isAxiosError(error)) { + const statusCode = error.response?.status || 500; + const errorData = error.response?.data || { message: error.message }; + + throw new Error( + `Monday.com API request failed with status ${statusCode}: ${ + typeof errorData === 'object' ? JSON.stringify(errorData) : errorData + }`, + ); + } + + throw new Error(`Failed to execute Monday.com API request: ${error.message}`); + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/apps.consts.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/apps.consts.ts new file mode 100644 index 0000000..feb4ec7 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/apps.consts.ts @@ -0,0 +1,52 @@ +export enum AppFeatureType { + AppFeatureBoardView = 'AppFeatureBoardView', + AppFeatureIntegration = 'AppFeatureIntegration', + AppFeatureSolution = 'AppFeatureSolution', + AppFeatureItemView = 'AppFeatureItemView', + AppFeatureDashboardWidget = 'AppFeatureDashboardWidget', + AppFeatureAccountSettingsView = 'AppFeatureAccountSettingsView', + AppFeatureDocActions = 'AppFeatureDocActions', + AppFeatureObject = 'AppFeatureObject', + AppFeatureWorkspaceView = 'AppFeatureWorkspaceView', + AppFeatureAI = 'AppFeatureAI', + AppFeatureAiBoardMainMenuHeader = 'AppFeatureAiBoardMainMenuHeader', + AppFeatureAiItemUpdateActions = 'AppFeatureAiItemUpdateActions', + AppFeatureAiDocSlashCommand = 'AppFeatureAiDocSlashCommand', + AppFeatureAiDocContextualMenu = 'AppFeatureAiDocContextualMenu', + AppFeatureAiDocQuickStart = 'AppFeatureAiDocQuickStart', + AppFeatureAiDocTopBar = 'AppFeatureAiDocTopBar', + AppFeatureColumnTemplate = 'AppFeatureColumnTemplate', + AppFeatureAiIcAssistantHelpCenter = 'AppFeatureAiIcAssistantHelpCenter', + AppFeatureAppWizard = 'AppFeatureAppWizard', + AppFeatureGroupMenuAction = 'AppFeatureGroupMenuAction', + AppFeatureItemMenuAction = 'AppFeatureItemMenuAction', + AppFeatureNotificationKind = 'AppFeatureNotificationKind', + AppFeatureNotificationSettingKind = 'AppFeatureNotificationSettingKind', + AppFeatureBlock = 'AppFeatureBlock', + AppFeatureItemBatchAction = 'AppFeatureItemBatchAction', + AppFeatureAiFormula = 'AppFeatureAiFormula', + AppFeatureAiItemEmailsAndActivitiesActions = 'AppFeatureAiItemEmailsAndActivitiesActions', + AppFeatureAiEmailsAndActivitiesHeaderActions = 'AppFeatureAiEmailsAndActivitiesHeaderActions', + AppFeatureFieldType = 'AppFeatureFieldType', + AppFeatureProduct = 'AppFeatureProduct', + AppFeatureProductView = 'AppFeatureProductView', + AppFeatureBoardColumnAction = 'AppFeatureBoardColumnAction', + AppFeatureBoardColumnExtension = 'AppFeatureBoardColumnExtension', + AppFeaturePackagedBlock = 'AppFeaturePackagedBlock', + AppFeatureTopbar = 'AppFeatureTopbar', + AppFeatureWorkflowTemplate = 'AppFeatureWorkflowTemplate', + AppFeatureColumn = 'AppFeatureColumn', + AppFeatureSubWorkflow = 'AppFeatureSubWorkflow', + AppFeatureBoardHeaderAction = 'AppFeatureBoardHeaderAction', + AppFeatureDialog = 'AppFeatureDialog', + AppFeatureDataEntity = 'AppFeatureDataEntity', + AppFeatureSurfaceView = 'AppFeatureSurfaceView', +} + +export enum MondayAppsToolCategory { + APP = 'app', + APP_VERSION = 'app_version', + APP_FEATURE = 'app_feature', + STORAGE = 'storage', + MONDAY_CODE = 'monday_code', +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/routes.consts.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/routes.consts.ts new file mode 100644 index 0000000..c5efda1 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/consts/routes.consts.ts @@ -0,0 +1,79 @@ +export enum HttpMethod { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +export const MONDAY_APPS_DOMAIN = 'https://monday-apps-ms.monday.com'; +const APPS_MS_PATH = '/apps_ms'; + +const BASE_API = '/api'; +const BASE_APPS = `${BASE_API}/apps`; +const BASE_APP_VERSIONS = `${BASE_API}/app-versions`; +const BASE_CODE = `${BASE_API}/code`; +const BASE_STORAGE = `${BASE_API}/storage`; + +const API_URL = `${MONDAY_APPS_DOMAIN}${BASE_API}`; +const APPS_URL = `${MONDAY_APPS_DOMAIN}${BASE_APPS}`; +const APP_VERSIONS_URL = `${MONDAY_APPS_DOMAIN}${BASE_APP_VERSIONS}`; +const CODE_URL = `${MONDAY_APPS_DOMAIN}${BASE_CODE}`; +const STORAGE_URL = `${MONDAY_APPS_DOMAIN}${BASE_STORAGE}`; +const APPS_MS_URL = `${MONDAY_APPS_DOMAIN}${APPS_MS_PATH}`; + +export const API_ENDPOINTS = { + APPS: { + GET_ALL: APPS_URL, + CREATE: APPS_URL, + CREATE_FROM_MANIFEST: `${APPS_URL}/manifest`, + GET_MANIFEST: (appId: number) => `${APPS_URL}/${appId}/manifest`, + UPDATE_MANIFEST: (appId: number) => `${APPS_URL}/${appId}/manifest`, + PROMOTE: (appId: number) => `${APPS_URL}/${appId}/promote`, + }, + + APP_VERSIONS: { + GET_ALL: (appId: number) => `${APPS_URL}/${appId}/versions`, + GET_BY_ID: (versionId: number) => `${APP_VERSIONS_URL}/${versionId}`, + GET_STATUS: (path: string) => `${API_URL}/${path}`, + }, + + APP_FEATURES: { + GET_ALL: (appVersionId: number) => `${APP_VERSIONS_URL}/${appVersionId}/app-features`, + GET_WITH_TYPES: (appVersionId: number, types?: string[]) => { + const url = `${APP_VERSIONS_URL}/${appVersionId}/app-features`; + const appFeatureTypes = types?.map((type, index) => `type[${index}]=${type}`).join('&'); + return appFeatureTypes ? `${url}?${appFeatureTypes}` : url; + }, + CREATE: (appId: number, appVersionId: number) => `${APPS_URL}/${appId}/app-versions/${appVersionId}/app-features`, + CREATE_RELEASE: (appId: number, appVersionId: number, appFeatureId: number) => + `${APPS_URL}/${appId}/versions/${appVersionId}/app-features/${appFeatureId}/releases`, + }, + + STORAGE: { + GET_BY_TERM: (appId: number, accountId: number, term: string) => + `${STORAGE_URL}/app/${appId}/account/${accountId}/records?term=${encodeURI(term)}`, + EXPORT_DATA: (appId: number, accountId: number) => + `${STORAGE_URL}/app/${appId}/account/${accountId}/records/export`, + REMOVE_APP_DATA: (appId: number, accountId: number) => `${APPS_URL}/${appId}/accounts/${accountId}`, + }, + + CODE: { + APP_VERSION_BASE: (appVersionId: number) => `${CODE_URL}/${appVersionId}`, + GET_DEPLOYMENT_STATUS: (appVersionId: number) => `${CODE_URL}/${appVersionId}/deployments`, + GET_DEPLOYMENT_SIGNED_URL: (appVersionId: number) => `${CODE_URL}/${appVersionId}/deployments/signed-url`, + UPLOAD_DEPLOYMENT: (appVersionId: number) => `${CODE_URL}/${appVersionId}/deployments`, + GET_LOGS: (appVersionId: number, logsType: string, additionalParams?: string) => + `${CODE_URL}/${appVersionId}/logs?type=${logsType}${additionalParams || ''}`, + GET_ENV_KEYS: (appId: number) => `${CODE_URL}/${appId}/env-keys`, + MANAGE_ENV: (appId: number, key: string) => `${CODE_URL}/${appId}/env/${key}`, + GET_SECRET_KEYS: (appId: number) => `${CODE_URL}/${appId}/secret-keys`, + MANAGE_SECRET: (appId: number, key: string) => `${CODE_URL}/${appId}/secrets/${key}`, + TUNNEL_TOKEN: `${CODE_URL}/tunnel-token`, + }, + + RELEASES: { + GET_APP_RELEASES: (appVersionId: number) => `${APPS_MS_URL}/app-versions/${appVersionId}/releases`, + }, +}; + +export const APPS_MS_TIMEOUT_IN_MS = 30000; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/index.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/index.ts index b7232bc..a8f478d 100644 --- a/packages/agent-toolkit/src/core/tools/monday-apps-tools/index.ts +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/index.ts @@ -1,2 +1,29 @@ -import { Tool } from 'src/core/tool'; -export const allMondayAppsTools: (new (...args: any[]) => Tool)[] = []; +import { MondayAppsToolType } from './base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from './consts/apps.consts'; +import { storageTools } from './storage'; +import { appTools } from './app'; +import { appVersionTools } from './app-version'; +import { appFeatureTools } from './app-feature'; +import { codeTools } from './monday-code'; + +export const mondayAppsTools = { + [MondayAppsToolCategory.STORAGE]: storageTools, + [MondayAppsToolCategory.APP]: appTools, + [MondayAppsToolCategory.APP_VERSION]: appVersionTools, + [MondayAppsToolCategory.APP_FEATURE]: appFeatureTools, + [MondayAppsToolCategory.MONDAY_CODE]: codeTools, +}; + +export const allMondayAppsTools: MondayAppsToolType[] = [ + ...storageTools, + ...appTools, + ...appVersionTools, + ...appFeatureTools, + ...codeTools, +]; + +export * from './storage'; +export * from './app'; +export * from './app-version'; +export * from './app-feature'; +export * from './monday-code'; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/delete-environment-variable.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/delete-environment-variable.ts new file mode 100644 index 0000000..c85e5ca --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/delete-environment-variable.ts @@ -0,0 +1,44 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { EnvVarResponse, deleteEnvVarSchema } from './schemas/code-schemas'; + +export class DeleteEnvironmentVariableTool extends BaseMondayAppsTool { + name = 'monday_apps_delete_environment_variable'; + category = MondayAppsToolCategory.MONDAY_CODE; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Delete an environment variable for an app'; + } + + getInputSchema() { + return deleteEnvVarSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const { appId, key } = input; + + const response = await this.executeApiRequest( + HttpMethod.DELETE, + API_ENDPOINTS.CODE.MANAGE_ENV(appId, key), + ); + + return { + content: `Successfully deleted environment variable '${key}' for app ID ${appId}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to delete environment variable: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + } as EnvVarResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-deployment-status.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-deployment-status.ts new file mode 100644 index 0000000..5915aa2 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-deployment-status.ts @@ -0,0 +1,60 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { DeploymentStatusResponse, getDeploymentStatusSchema } from './schemas/code-schemas'; + +export class GetDeploymentStatusTool extends BaseMondayAppsTool< + typeof getDeploymentStatusSchema.shape, + DeploymentStatusResponse +> { + name = 'monday_apps_get_deployment_status'; + category = MondayAppsToolCategory.MONDAY_CODE; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Get the deployment status for a specific app version'; + } + + getInputSchema() { + return getDeploymentStatusSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { appVersionId } = input; + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.CODE.GET_DEPLOYMENT_STATUS(appVersionId), + ); + + // Create a more detailed status message + const statusDetails = [ + `Status: ${response.status || 'Unknown'}`, + response.startTime ? `Started: ${new Date(response.startTime).toLocaleString()}` : null, + response.endTime ? `Completed: ${new Date(response.endTime).toLocaleString()}` : null, + response.error ? `Error: ${response.error}` : null, + response.logs ? `Logs: ${response.logs}` : null, + ] + .filter(Boolean) + .join('\n'); + + return { + content: `Deployment status for app version ID ${appVersionId}:\n${statusDetails}`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to get deployment status: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + } as DeploymentStatusResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-tunnel-token.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-tunnel-token.ts new file mode 100644 index 0000000..77719a1 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/get-tunnel-token.ts @@ -0,0 +1,49 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { TunnelTokenResponse, getTunnelTokenSchema } from './schemas/code-schemas'; + +export class GetTunnelTokenTool extends BaseMondayAppsTool { + name = 'monday_apps_get_tunnel_token'; + category = MondayAppsToolCategory.MONDAY_CODE; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Get a tunnel token for exposing code running on the local machine'; + } + + getInputSchema() { + return getTunnelTokenSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const { appId } = input; + + const query = appId ? { appId } : undefined; + + const response = await this.executeApiRequest( + HttpMethod.PUT, + API_ENDPOINTS.CODE.TUNNEL_TOKEN, + { query }, + ); + + return { + content: `Successfully retrieved tunnel token. Domain: ${response.domain}`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to get tunnel token: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + token: '', + domain: '', + } as TunnelTokenResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/index.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/index.ts new file mode 100644 index 0000000..1717e03 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/index.ts @@ -0,0 +1,19 @@ +import { GetDeploymentStatusTool } from './get-deployment-status'; +import { GetTunnelTokenTool } from './get-tunnel-token'; +import { SetEnvironmentVariableTool } from './set-environment-variable'; +import { DeleteEnvironmentVariableTool } from './delete-environment-variable'; +import { ListEnvironmentVariableKeysTool } from './list-environment-variable-keys'; + +export const codeTools = [ + GetDeploymentStatusTool, + GetTunnelTokenTool, + SetEnvironmentVariableTool, + DeleteEnvironmentVariableTool, + ListEnvironmentVariableKeysTool, +]; + +export * from './get-deployment-status'; +export * from './get-tunnel-token'; +export * from './set-environment-variable'; +export * from './delete-environment-variable'; +export * from './list-environment-variable-keys'; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/list-environment-variable-keys.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/list-environment-variable-keys.ts new file mode 100644 index 0000000..b8f7d07 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/list-environment-variable-keys.ts @@ -0,0 +1,48 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { EnvVarKeysResponse, listEnvVarKeysSchema } from './schemas/code-schemas'; + +export class ListEnvironmentVariableKeysTool extends BaseMondayAppsTool< + typeof listEnvVarKeysSchema.shape, + EnvVarKeysResponse +> { + name = 'monday_apps_list_environment_variable_keys'; + category = MondayAppsToolCategory.MONDAY_CODE; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'List all environment variable keys for an app'; + } + + getInputSchema() { + return listEnvVarKeysSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const { appId } = input; + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.CODE.GET_ENV_KEYS(appId), + ); + + return { + content: `Found ${response.keys.length} environment variable keys for app ID ${appId}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to list environment variable keys: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + keys: [], + } as EnvVarKeysResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/schemas/code-schemas.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/schemas/code-schemas.ts new file mode 100644 index 0000000..d3812bb --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/schemas/code-schemas.ts @@ -0,0 +1,44 @@ +import { z } from 'zod'; +import { MondayApiResponse } from '../../base-tool/monday-apps-tool'; + +export interface DeploymentStatusResponse extends MondayApiResponse { + status?: string; + creationDate?: string; + activeFromVersionId?: number; +} + +export const getDeploymentStatusSchema = z.object({ + appVersionId: z.number().describe('The ID of the app version to get deployment status for'), +}); + +export interface TunnelTokenResponse extends MondayApiResponse { + token: string; + domain: string; +} + +export const getTunnelTokenSchema = z.object({ + appId: z.number().optional().describe('The ID of the app to get a tunnel token for (optional)'), +}); + +export interface EnvVarResponse extends MondayApiResponse { + success?: boolean; +} + +export const baseEnvVarSchema = z.object({ + appId: z.number().describe('The ID of the app to manage environment variables for'), + key: z.string().describe('The environment variable key'), +}); + +export const setEnvVarSchema = baseEnvVarSchema.extend({ + value: z.string().describe('The environment variable value'), +}); + +export const deleteEnvVarSchema = baseEnvVarSchema; + +export interface EnvVarKeysResponse extends MondayApiResponse { + keys: string[]; +} + +export const listEnvVarKeysSchema = z.object({ + appId: z.number().describe('The ID of the app to list environment variable keys for'), +}); diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/set-environment-variable.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/set-environment-variable.ts new file mode 100644 index 0000000..ad133c9 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/monday-code/set-environment-variable.ts @@ -0,0 +1,45 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { EnvVarResponse, setEnvVarSchema } from './schemas/code-schemas'; + +export class SetEnvironmentVariableTool extends BaseMondayAppsTool { + name = 'monday_apps_set_environment_variable'; + category = MondayAppsToolCategory.MONDAY_CODE; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Set an environment variable for an app'; + } + + getInputSchema() { + return setEnvVarSchema.shape; + } + + async execute(input: ToolInputType): Promise> { + try { + const { appId, key, value } = input; + + const response = await this.executeApiRequest( + HttpMethod.PUT, + API_ENDPOINTS.CODE.MANAGE_ENV(appId, key), + { data: { value } }, + ); + + return { + content: `Successfully set environment variable '${key}' for app ID ${appId}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to set environment variable: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + } as EnvVarResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/export-storage-data.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/export-storage-data.ts new file mode 100644 index 0000000..9477367 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/export-storage-data.ts @@ -0,0 +1,57 @@ +import { ToolInputType, ToolOutputType, ToolType } from 'src/core/tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { ExportStorageDataResponse, exportStorageDataSchema } from './schemas/storage-schemas'; + +export class ExportStorageDataTool extends BaseMondayAppsTool< + typeof exportStorageDataSchema.shape, + ExportStorageDataResponse +> { + name = 'monday_apps_export_storage_data'; + category = MondayAppsToolCategory.STORAGE; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Export storage data from a Monday.com app'; + } + + getInputSchema() { + return exportStorageDataSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { appId, accountId, fileFormat } = input; + + const query: Record = {}; + if (fileFormat) { + query.fileFormat = fileFormat; + } + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.STORAGE.EXPORT_DATA(appId, accountId), + { query }, + ); + + return { + content: `Successfully exported storage data for app ID ${appId}, account ID ${accountId}.${ + response.downloadUrl ? ` Download URL: ${response.downloadUrl}` : '' + }`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to export storage data: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + } as ExportStorageDataResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/index.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/index.ts new file mode 100644 index 0000000..9960a0e --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/index.ts @@ -0,0 +1,9 @@ +import { SearchStorageRecordsTool } from './search-storage-records'; +import { ExportStorageDataTool } from './export-storage-data'; +import { RemoveAppStorageDataTool } from './remove-app-storage-data'; + +export const storageTools = [SearchStorageRecordsTool, ExportStorageDataTool, RemoveAppStorageDataTool]; + +export * from './search-storage-records'; +export * from './export-storage-data'; +export * from './remove-app-storage-data'; diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/remove-app-storage-data.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/remove-app-storage-data.ts new file mode 100644 index 0000000..37c9bbe --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/remove-app-storage-data.ts @@ -0,0 +1,50 @@ +import { ToolInputType, ToolOutputType, ToolType } from '../../../tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { RemoveAppStorageDataResponse, removeAppStorageDataSchema } from './schemas/storage-schemas'; + +export class RemoveAppStorageDataTool extends BaseMondayAppsTool< + typeof removeAppStorageDataSchema.shape, + RemoveAppStorageDataResponse +> { + name = 'monday_apps_remove_app_storage_data'; + category = MondayAppsToolCategory.STORAGE; + type: ToolType = ToolType.WRITE; + + getDescription(): string { + return 'Remove all storage data for a specific account on a specific app'; + } + + getInputSchema() { + return removeAppStorageDataSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { appId, accountId } = input; + + const response = await this.executeApiRequest( + HttpMethod.DELETE, + API_ENDPOINTS.STORAGE.REMOVE_APP_DATA(appId, accountId), + ); + + return { + content: `Successfully removed all data for app ID ${appId}, account ID ${accountId}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to remove app data: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + success: false, + } as RemoveAppStorageDataResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/schemas/storage-schemas.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/schemas/storage-schemas.ts new file mode 100644 index 0000000..9be5d59 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/schemas/storage-schemas.ts @@ -0,0 +1,38 @@ +import { z } from 'zod'; +import { MondayApiResponse } from '../../base-tool/monday-apps-tool'; + +export interface StorageRecordsResponse extends MondayApiResponse { + term: string; + records: Array<{ + key: string; + value: string; + backendOnly: boolean; + }>; + cursor?: string; +} + +export const searchStorageRecordsSchema = z.object({ + appId: z.number().describe('The ID of the app to search storage records for'), + accountId: z.number().describe('The ID of the account to search storage records for'), + term: z.string().describe('The term to search for in the storage records'), + cursor: z.string().optional().describe('The cursor for pagination'), +}); + +export interface ExportStorageDataResponse extends MondayApiResponse { + downloadUrl?: string; +} + +export const exportStorageDataSchema = z.object({ + appId: z.number().describe('The ID of the app to export storage data for'), + accountId: z.number().describe('The ID of the account to export storage data for'), + fileFormat: z.enum(['JSON', 'CSV']).optional().describe('The format of the exported file (JSON or CSV)'), +}); + +export interface RemoveAppStorageDataResponse extends MondayApiResponse { + success?: boolean; +} + +export const removeAppStorageDataSchema = z.object({ + appId: z.number().describe('The ID of the app to remove data for'), + accountId: z.number().describe('The ID of the account to remove data for'), +}); diff --git a/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/search-storage-records.ts b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/search-storage-records.ts new file mode 100644 index 0000000..e6ba528 --- /dev/null +++ b/packages/agent-toolkit/src/core/tools/monday-apps-tools/storage/search-storage-records.ts @@ -0,0 +1,57 @@ +import { ToolInputType, ToolOutputType, ToolType } from 'src/core/tool'; +import { BaseMondayAppsTool } from '../base-tool/monday-apps-tool'; +import { MondayAppsToolCategory } from '../consts/apps.consts'; +import { API_ENDPOINTS, HttpMethod } from '../consts/routes.consts'; +import { StorageRecordsResponse, searchStorageRecordsSchema } from './schemas/storage-schemas'; + +export class SearchStorageRecordsTool extends BaseMondayAppsTool< + typeof searchStorageRecordsSchema.shape, + StorageRecordsResponse +> { + name = 'monday_apps_search_storage_records'; + category = MondayAppsToolCategory.STORAGE; + type: ToolType = ToolType.READ; + + getDescription(): string { + return 'Search for storage records in a Monday.com app'; + } + + getInputSchema() { + return searchStorageRecordsSchema.shape; + } + + async execute( + input: ToolInputType, + ): Promise> { + try { + const { appId, accountId, term, cursor } = input; + + const query: Record = { term }; + if (cursor) { + query.cursor = cursor; + } + + const response = await this.executeApiRequest( + HttpMethod.GET, + API_ENDPOINTS.STORAGE.GET_BY_TERM(appId, accountId, term), + { query }, + ); + + return { + content: `Found ${response.records.length} storage records matching term '${term}' for app ID ${appId}, account ID ${accountId}.`, + metadata: response, + }; + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + return { + content: `Failed to search storage records: ${errorMessage}`, + metadata: { + statusCode: 500, + error: errorMessage, + term: input.term, + records: [], + } as StorageRecordsResponse, + }; + } + } +} diff --git a/packages/agent-toolkit/src/utils/tools/initializing.utils.ts b/packages/agent-toolkit/src/utils/tools/initializing.utils.ts index 0c87a2a..bfc57c5 100644 --- a/packages/agent-toolkit/src/utils/tools/initializing.utils.ts +++ b/packages/agent-toolkit/src/utils/tools/initializing.utils.ts @@ -1,6 +1,7 @@ import { ApiClient } from '@mondaydotcomorg/api'; -import { Tool } from 'src/core/tool'; +import { BaseMondayAppsTool } from 'src/core/tools/monday-apps-tools/base-tool/monday-apps-tool'; import { BaseMondayApiTool } from 'src/core/tools/platform-api-tools/base-monday-api-tool'; +import { Tool } from 'src/core/tool'; export const createToolInstance = ( tool: new (...args: any[]) => Tool, @@ -8,6 +9,8 @@ export const createToolInstance = ( ) => { if (tool.prototype instanceof BaseMondayApiTool) { return new tool(instanceOptions.apiClient); + } else if (tool.prototype instanceof BaseMondayAppsTool) { + return new tool(instanceOptions.apiToken); } return new tool(); }; diff --git a/packages/monday-api-mcp/README.md b/packages/monday-api-mcp/README.md index 3121e25..77d42af 100644 --- a/packages/monday-api-mcp/README.md +++ b/packages/monday-api-mcp/README.md @@ -34,6 +34,7 @@ The Monday API token can also be provided via the `monday_token` environment var | API Version | `--version`, `-v` | Monday.com API version | No | `current` | | Read Only Mode | `--read-only`, `-ro` | Enable read-only mode | No | `false` | | Dynamic API Tools | `--enable-dynamic-api-tools`, `-edat` | (Beta) Enable dynamic API tools (Mode that includes the whole API schema, not supported when using read-only mode) | No | `false` | +| Monday apps Tools | `--enable-monday-apps-tools`, `-emat` | (Beta) Enable Monday Apps tools | No | `false` | ## 💻 Claude Desktop Integration diff --git a/packages/monday-api-mcp/package.json b/packages/monday-api-mcp/package.json index 39d9a9d..d50fc42 100644 --- a/packages/monday-api-mcp/package.json +++ b/packages/monday-api-mcp/package.json @@ -1,6 +1,6 @@ { "name": "@mondaydotcomorg/monday-api-mcp", - "version": "1.0.3", + "version": "1.0.4", "description": "MCP server for using the monday.com API", "license": "MIT", "bin": { diff --git a/yarn.lock b/yarn.lock index a23384b..c9a0af9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1639,6 +1639,15 @@ auto-bind@~4.0.0: resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== +axios@^1.8.4: + version "1.8.4" + resolved "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz#78990bb4bc63d2cae072952d374835950a82f447" + integrity sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -2681,6 +2690,11 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + form-data-encoder@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" @@ -4341,6 +4355,11 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"