Skip to main content
Glama

mcp-google-sheets

create-event.ts15.3 kB
import { createAction, Property } from '@activepieces/pieces-framework'; import { httpClient, HttpMethod } from '@activepieces/pieces-common'; import { fetchContacts, fetchUsers, fetchUserGroups, fetchEventCategories, fetchCustomFields, WEALTHBOX_API_BASE, handleApiError, DOCUMENT_TYPES, EVENT_STATES } from '../common'; export const createEvent = createAction({ name: 'create_event', displayName: 'Create Event', description: 'Creates a calendar event linked to contact. Schedule advisory meetings on behalf of clients.', props: { title: Property.ShortText({ displayName: 'Event Title', description: 'The name of the event (e.g., "Client Meeting", "Portfolio Review")', required: true }), starts_at: Property.DateTime({ displayName: 'Start Date & Time', description: 'When the event starts (yyyy-mm-dd hh:mm format)', required: true }), ends_at: Property.DateTime({ displayName: 'End Date & Time', description: 'When the event ends (yyyy-mm-dd hh:mm format)', required: true }), location: Property.ShortText({ displayName: 'Location', description: 'Where the event takes place (e.g., "Conference Room", "Client Office", "Zoom Meeting")', required: false }), description: Property.LongText({ displayName: 'Description', description: 'A detailed explanation of the event purpose and agenda', required: false }), all_day: Property.Checkbox({ displayName: 'All Day Event', description: 'Check if this is an all-day event', required: false, defaultValue: false }), repeats: Property.Checkbox({ displayName: 'Repeating Event', description: 'Check if this event repeats', required: false, defaultValue: false }), state: Property.StaticDropdown({ displayName: 'Event Status', description: 'The current state of the event', required: false, defaultValue: EVENT_STATES.UNCONFIRMED, options: { options: [ { label: 'Unconfirmed', value: EVENT_STATES.UNCONFIRMED }, { label: 'Confirmed', value: EVENT_STATES.CONFIRMED }, { label: 'Tentative', value: EVENT_STATES.TENTATIVE }, { label: 'Completed', value: EVENT_STATES.COMPLETED }, { label: 'Cancelled', value: EVENT_STATES.CANCELLED } ] } }), contact_id: Property.Dropdown({ displayName: 'Linked Contact', description: 'Select the contact to link this event to', required: false, refreshers: [], options: async ({ auth }) => { if (!auth) return { options: [] }; try { const contacts = await fetchContacts(auth as unknown as string, { active: true, order: 'recent' }); return { options: contacts.map((contact: any) => ({ label: contact.name || `${contact.first_name} ${contact.last_name}`.trim() || `Contact ${contact.id}`, value: contact.id })) }; } catch (error) { return { options: [], error: 'Failed to load contacts. Please check your authentication.' }; } } }), invitees: Property.DynamicProperties({ displayName: 'Invitees', description: 'Add people to invite to this event', required: false, refreshers: [], props: async ({ auth }) => { if (!auth) { return { invitees_array: Property.Array({ displayName: 'Invitees', description: 'Add invitees to this event', required: false, properties: { invitee: Property.ShortText({ displayName: 'Invitee', description: 'Invitee name', required: true }), type: Property.StaticDropdown({ displayName: 'Type', description: 'Type of invitee', required: true, options: { options: [ { label: 'Contact', value: 'Contact' }, { label: 'User', value: 'User' } ] } }) } }) }; } try { const [contacts, users] = await Promise.all([ fetchContacts(auth as unknown as string, { active: true }), fetchUsers(auth as unknown as string) ]); const contactOptions = contacts.map((contact: any) => ({ label: `${contact.name || `${contact.first_name} ${contact.last_name}`.trim()} (Contact)`, value: `contact_${contact.id}` })); const userOptions = users.map((user: any) => ({ label: `${user.name} (User)`, value: `user_${user.id}` })); const allInviteeOptions = [...contactOptions, ...userOptions]; return { invitees_array: Property.Array({ displayName: 'Invitees', description: 'Add invitees to this event', required: false, properties: { invitee: Property.StaticDropdown({ displayName: 'Invitee', description: 'Select a contact or user to invite', required: true, options: { options: allInviteeOptions } }) } }) }; } catch (error) { return { invitees_array: Property.Array({ displayName: 'Invitees', description: 'Add invitees to this event (API unavailable)', required: false, properties: { invitee: Property.ShortText({ displayName: 'Invitee Name', description: 'Enter the invitee name', required: true }), type: Property.StaticDropdown({ displayName: 'Type', description: 'Type of invitee', required: true, options: { options: [ { label: 'Contact', value: 'Contact' }, { label: 'User', value: 'User' } ] } }) } }) }; } } }), event_category: Property.Dropdown({ displayName: 'Event Category', description: 'Select the category for this event', required: false, refreshers: [], options: async ({ auth }) => { if (!auth) return { options: [] }; try { const categories = await fetchEventCategories(auth as unknown as string); return { options: categories.map((category: any) => ({ label: category.name, value: category.id })) }; } catch (error) { return { options: [], error: 'Failed to load event categories. Please check your authentication.' }; } } }), email_invitees: Property.Checkbox({ displayName: 'Email Invitees', description: 'Send email invitations to invitees', required: false, defaultValue: true }), visible_to: Property.Dropdown({ displayName: 'Visible To', description: 'Select who can view this event', required: false, refreshers: [], options: async ({ auth }) => { if (!auth) return { options: [] }; try { const userGroups = await fetchUserGroups(auth as unknown as string); return { options: userGroups.map((group: any) => ({ label: group.name, value: group.name })) }; } catch (error) { return { options: [], error: 'Failed to load user groups. Please check your authentication.' }; } } }), custom_fields: Property.DynamicProperties({ displayName: 'Custom Fields', description: 'Add custom fields to this event', required: false, refreshers: [], props: async ({ auth }) => { if (!auth) { return { custom_fields_array: Property.Array({ displayName: 'Custom Fields', description: 'Add custom fields to this event', required: false, properties: { custom_field: Property.ShortText({ displayName: 'Custom Field', description: 'Custom field name', required: true }), value: Property.ShortText({ displayName: 'Value', description: 'The value for this custom field', required: true }) } }) }; } try { const customFields = await fetchCustomFields(auth as unknown as string, DOCUMENT_TYPES.EVENT); const customFieldOptions = customFields.map((field: any) => ({ label: field.name, value: field.name })); return { custom_fields_array: Property.Array({ displayName: 'Custom Fields', description: 'Add custom fields to this event', required: false, properties: { custom_field: Property.StaticDropdown({ displayName: 'Custom Field', description: 'Select a custom field for this event', required: true, options: { options: customFieldOptions } }), value: Property.ShortText({ displayName: 'Value', description: 'The value for this custom field', required: true }) } }) }; } catch (error) { return { custom_fields_array: Property.Array({ displayName: 'Custom Fields', description: 'Add custom fields to this event (API unavailable)', required: false, properties: { custom_field: Property.ShortText({ displayName: 'Custom Field Name', description: 'Enter the custom field name exactly', required: true }), value: Property.ShortText({ displayName: 'Value', description: 'The value for this custom field', required: true }) } }) }; } } }) }, async run(context) { const { auth, propsValue } = context; if (!auth) { throw new Error('Authentication is required'); } const requestBody: any = { title: propsValue.title, starts_at: propsValue.starts_at, ends_at: propsValue.ends_at }; if (propsValue.location) requestBody.location = propsValue.location; if (propsValue.description) requestBody.description = propsValue.description; if (propsValue.all_day !== undefined) requestBody.all_day = propsValue.all_day; if (propsValue.repeats !== undefined) requestBody.repeats = propsValue.repeats; if (propsValue.state) requestBody.state = propsValue.state; if (propsValue.event_category) requestBody.event_category = propsValue.event_category; if (propsValue.visible_to) requestBody.visible_to = propsValue.visible_to; if (propsValue.email_invitees !== undefined) requestBody.email_invitees = propsValue.email_invitees; if (propsValue.contact_id) { try { const contacts = await fetchContacts(auth as unknown as string, { active: true }); const selectedContact = contacts.find((contact: any) => contact.id === propsValue.contact_id); requestBody.linked_to = [{ id: propsValue.contact_id, type: 'Contact', name: selectedContact ? (selectedContact.name || `${selectedContact.first_name} ${selectedContact.last_name}`.trim()) : `Contact ${propsValue.contact_id}` }]; } catch (error) { requestBody.linked_to = [{ id: propsValue.contact_id, type: 'Contact', name: `Contact ${propsValue.contact_id}` }]; } } const inviteesArray = (propsValue as any).invitees_array; if (inviteesArray && Array.isArray(inviteesArray) && inviteesArray.length > 0) { const invitees: any[] = []; for (const inviteeItem of inviteesArray) { const inviteeValue = inviteeItem.invitee; if (inviteeValue && typeof inviteeValue === 'string') { if (inviteeValue.startsWith('contact_')) { const contactId = inviteeValue.replace('contact_', ''); invitees.push({ id: parseInt(contactId), type: 'Contact' }); } else if (inviteeValue.startsWith('user_')) { const userId = inviteeValue.replace('user_', ''); invitees.push({ id: parseInt(userId), type: 'User' }); } } } if (invitees.length > 0) { requestBody.invitees = invitees; } } const customFieldsArray = (propsValue as any).custom_fields_array; if (customFieldsArray && Array.isArray(customFieldsArray) && customFieldsArray.length > 0) { try { const customFields = await fetchCustomFields(auth as unknown as string, DOCUMENT_TYPES.EVENT); const customFieldMap = new Map(customFields.map((field: any) => [field.name, field.id])); requestBody.custom_fields = customFieldsArray.map((field: any) => { const fieldId = customFieldMap.get(field.custom_field); if (!fieldId) { throw new Error(`Custom field "${field.custom_field}" not found. Please check the field name.`); } return { id: fieldId, value: field.value }; }); } catch (error) { if (error instanceof Error && error.message.includes('Custom field')) { throw error; } console.warn('Could not fetch custom fields for validation:', error); requestBody.custom_fields = customFieldsArray.map((field: any) => ({ id: field.custom_field, value: field.value })); } } try { const response = await httpClient.sendRequest({ method: HttpMethod.POST, url: `${WEALTHBOX_API_BASE}/events`, headers: { 'ACCESS_TOKEN': auth as unknown as string, 'Content-Type': 'application/json' }, body: requestBody }); if (response.status >= 400) { handleApiError('create event', response.status, response.body); } return response.body; } catch (error) { throw new Error(`Failed to create event: ${error instanceof Error ? error.message : 'Unknown error'}`); } } });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server