Skip to main content
Glama

mcp-google-sheets

props.ts20.3 kB
import { Property } from '@activepieces/pieces-framework'; import { HttpMethod } from '@activepieces/pieces-common'; import { podioApiCall } from './client'; import { getAccessToken } from './auth'; export const appIdProperty = Property.Number({ displayName: 'App ID', description: 'The ID of the Podio app', required: true, }); export const dynamicAppProperty = Property.Dropdown({ displayName: 'App', description: 'Select a Podio app', required: true, refreshers: ['spaceId'], options: async ({ auth, spaceId }) => { if (!auth) { return { disabled: true, placeholder: 'Connect your Podio account first', options: [], }; } try { const accessToken = getAccessToken(auth as any); let resourceUri = '/app/'; if (spaceId) { resourceUri = `/app/space/${spaceId}/`; } const apps = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri, }); if (!apps || apps.length === 0) { return { options: [], placeholder: spaceId ? 'No apps found in this space' : 'No apps found', }; } return { options: apps.map((app: any) => ({ label: `${app.config?.name || app.name}${app.space ? ` (${app.space.name})` : ''}`, value: app.app_id, })), }; } catch (error) { return { disabled: true, options: [], placeholder: 'Failed to load apps. Check your connection.', }; } }, }); export const dynamicSpaceProperty = Property.Dropdown({ displayName: 'Space', description: 'Select a Podio workspace', required: true, refreshers: ['orgId'], options: async ({ auth, orgId }) => { if (!auth) { return { disabled: true, placeholder: 'Connect your Podio account first', options: [], }; } if (!orgId) { return { disabled: true, placeholder: 'Select an organization first', options: [], }; } try { const accessToken = getAccessToken(auth as any); const resourceUri = `/org/${orgId}/space/`; const spaces = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri, }); if (!spaces || spaces.length === 0) { return { options: [], placeholder: 'No spaces found in this organization', }; } return { options: spaces.map((space: any) => ({ label: `${space.name}${space.org ? ` (${space.org.name})` : ''}`, value: space.space_id, })), }; } catch (error) { return { disabled: true, options: [], placeholder: 'Failed to load spaces. Check your connection.', }; } }, }); export const dynamicOrgProperty = Property.Dropdown({ displayName: 'Organization', description: 'Select a Podio organization', required: true, refreshers: [], options: async ({ auth }) => { if (!auth) { return { disabled: true, placeholder: 'Connect your Podio account first', options: [], }; } try { const accessToken = getAccessToken(auth as any); const orgs = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri: '/org/', }); if (!orgs || orgs.length === 0) { return { options: [], placeholder: 'No organizations found', }; } return { options: orgs.map((org: any) => ({ label: org.name, value: org.org_id, })), }; } catch (error) { return { disabled: true, options: [], placeholder: 'Failed to load organizations. Check your connection.', }; } }, }); export const dynamicItemProperty = Property.Dropdown({ displayName: 'Item', description: 'Select a Podio item', required: true, refreshers: ['appId'], options: async ({ auth, appId }) => { if (!auth || !appId) { return { disabled: true, placeholder: !auth ? 'Connect your Podio account first' : 'Select an app first', options: [], }; } try { const accessToken = getAccessToken(auth as any); const response = await podioApiCall<{ items: any[] }>({ method: HttpMethod.POST, accessToken, resourceUri: `/item/app/${appId}/filter/`, body: { limit: 50 }, }); if (!response.items || response.items.length === 0) { return { options: [], placeholder: 'No items found in this app', }; } return { options: response.items.map((item: any) => ({ label: `${item.title || `Item ${item.item_id}`}`, value: item.item_id, })), }; } catch (error) { return { disabled: true, options: [], placeholder: 'Failed to load items. Check your permissions.', }; } }, }); export const dynamicRefTypeProperty = Property.Dropdown({ displayName: 'Reference Type', description: 'The type of object to reference', required: false, refreshers: [], options: async () => { return { options: [ { label: 'Item', value: 'item' }, { label: 'Task', value: 'task' }, { label: 'Status', value: 'status' }, { label: 'App', value: 'app' }, { label: 'Space', value: 'space' }, ], }; }, }); export const dynamicRefIdProperty = Property.Dropdown({ displayName: 'Reference Object', description: 'Select the specific object to reference', required: false, refreshers: ['refType', 'appId', 'spaceId', 'orgId'], options: async ({ auth, refType, appId, spaceId, orgId }) => { if (!auth || !refType) { return { disabled: true, placeholder: !auth ? 'Connect your Podio account first' : 'Select a reference type first', options: [], }; } try { const accessToken = getAccessToken(auth as any); let endpoint = ''; switch (refType) { case 'item': { if (!appId) { return { disabled: true, placeholder: 'Select an app first to load items', options: [], }; } const itemResponse = await podioApiCall<{ items: any[] }>({ method: HttpMethod.POST, accessToken, resourceUri: `/item/app/${appId}/filter/`, body: { limit: 30 }, }); return { options: itemResponse.items?.map((item: any) => ({ label: item.title || `Item ${item.item_id}`, value: item.item_id, })) || [], }; } case 'task': { if (spaceId) { endpoint = `/task/space/${spaceId}/`; } else { endpoint = '/task/'; } const taskResponse = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri: endpoint, queryParams: { limit: 30 }, }); return { options: taskResponse?.map((task: any) => ({ label: task.text || `Task ${task.task_id}`, value: task.task_id, })) || [], }; } case 'status': if (!spaceId) { return { disabled: true, placeholder: 'Select a space first to load status updates', options: [], }; } try { const statusResponse = await podioApiCall<any>({ method: HttpMethod.GET, accessToken, resourceUri: `/stream/space/${spaceId}/`, queryParams: { limit: 50, type: 'status' }, }); if (statusResponse?.items) { return { options: statusResponse.items .filter((item: any) => item.type === 'status' && item.data) .map((item: any) => ({ label: (item.data.value || item.data.text || '').substring(0, 60) + (item.data.value?.length > 60 ? '...' : '') || `Status ${item.data.status_id}`, value: item.data.status_id, })) .slice(0, 30), }; } return { options: [], placeholder: 'No status updates found in this space', }; } catch (error) { return { options: [], placeholder: 'Enter status ID manually (could not load status updates)', }; } case 'app': if (spaceId) { endpoint = `/app/space/${spaceId}/`; } else { endpoint = '/app/'; } try { const appResponse = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri: endpoint, }); return { options: appResponse?.map((app: any) => ({ label: `${app.config?.name || app.name}${app.space ? ` (${app.space.name})` : ''}`, value: app.app_id, })) || [], }; } catch (error) { return { options: [], placeholder: spaceId ? 'No apps found in this space' : 'Failed to load apps', }; } case 'space': { if (!orgId) { return { disabled: true, placeholder: 'Select an organization first to load spaces', options: [], }; } const spaceResponse = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri: `/org/${orgId}/space/`, }); return { options: spaceResponse?.map((space: any) => ({ label: space.name, value: space.space_id, })) || [], }; } default: return { options: [], placeholder: 'Unknown reference type', }; } } catch (error) { return { disabled: true, options: [], placeholder: `Failed to load ${refType}s. Check your permissions.`, }; } }, }); export const spaceIdProperty = Property.Number({ displayName: 'Space ID', description: 'The ID of the Podio workspace/space', required: true, }); export const itemIdProperty = Property.Number({ displayName: 'Item ID', description: 'The ID of the Podio item', required: true, }); export const taskIdProperty = Property.Number({ displayName: 'Task ID', description: 'The ID of the Podio task', required: true, }); export const dynamicFileProperty = Property.Dropdown({ displayName: 'File', description: 'Select a file from the space', required: true, refreshers: ['spaceId'], options: async ({ auth, spaceId }) => { if (!auth) { return { disabled: true, placeholder: 'Connect your Podio account first', options: [], }; } if (!spaceId) { return { disabled: true, placeholder: 'Select a space first to load files', options: [], }; } try { const accessToken = getAccessToken(auth as any); const files = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri: `/file/space/${spaceId}/`, queryParams: { limit: 50, sort_by: 'created_on', sort_desc: 'true' } }); if (!files || files.length === 0) { return { options: [], placeholder: 'No files found in this space', }; } return { options: files.map((file: any) => { let label = file.name || `File ${file.file_id}`; if (file.size) { const sizeInKB = Math.round(file.size / 1024); const sizeText = sizeInKB > 1024 ? `${Math.round(sizeInKB / 1024)}MB` : `${sizeInKB}KB`; label += ` (${sizeText})`; } if (file.mimetype) { const fileType = file.mimetype.split('/')[0]; const iconMap: Record<string, string> = { 'image': '🖼️', 'video': '🎥', 'audio': '🎵', 'text': '📄', 'application': '📁' }; const icon = iconMap[fileType] || '📄'; label = `${icon} ${label}`; } if (file.context?.title) { label += ` → ${file.context.title}`; } return { label, value: file.file_id, }; }), }; } catch (error) { return { disabled: true, options: [], placeholder: 'Failed to load files. Check your connection.', }; } }, }); export const dynamicTaskProperty = Property.Dropdown({ displayName: 'Task', description: 'Select a Podio task', required: true, refreshers: [], options: async ({ auth }) => { if (!auth) { return { disabled: true, placeholder: 'Connect your Podio account first', options: [], }; } try { const accessToken = getAccessToken(auth as any); const userInfo = await podioApiCall<any>({ method: HttpMethod.GET, accessToken, resourceUri: '/user/status', }); const userId = userInfo?.user?.user_id; if (!userId) { return { disabled: true, options: [], placeholder: 'Could not determine user ID for task filtering', }; } const tasks = await podioApiCall<any[]>({ method: HttpMethod.GET, accessToken, resourceUri: '/task/', queryParams: { responsible: userId, limit: 100, view: 'full', sort_by: 'created_on', sort_desc: 'true' } }); if (!tasks || tasks.length === 0) { return { options: [], placeholder: 'No tasks found assigned to you', }; } return { options: tasks.map((task: any) => { let label = task.text || `Task ${task.task_id}`; if (task.status === 'completed') { label = `✓ ${label}`; } else if (task.due_date) { const dueDate = new Date(task.due_date); const today = new Date(); if (dueDate < today) { label = `⚠️ ${label} (Overdue)`; } else { label = `📅 ${label}`; } } if (task.ref?.title) { label += ` → ${task.ref.title}`; } return { label, value: task.task_id, }; }), }; } catch (error) { return { disabled: true, options: [], placeholder: 'Failed to load tasks. Check your connection.', }; } }, }); export const orgIdProperty = Property.Number({ displayName: 'Organization ID', description: 'The ID of the Podio organization', required: true, }); export const refTypeProperty = Property.Dropdown({ displayName: 'Reference Type', description: 'The type of object', required: true, refreshers: [], options: async () => { return { options: [ { label: 'Item', value: 'item' }, { label: 'Task', value: 'task' }, { label: 'Status', value: 'status' }, { label: 'App', value: 'app' }, { label: 'Space', value: 'space' }, ], }; }, }); export const statusProperty = Property.Dropdown({ displayName: 'Status', description: 'The status filter', required: false, refreshers: [], options: async () => { return { options: [ { label: 'Active', value: 'active' }, { label: 'Completed', value: 'completed' }, { label: 'All', value: 'all' }, ], }; }, }); export const silentProperty = Property.Checkbox({ displayName: 'Silent Mode', description: 'If true, notifications will not be triggered and the object will not appear in activity streams', required: false, defaultValue: false, }); export const hookProperty = Property.Checkbox({ displayName: 'Execute Hooks', description: 'If false, webhooks and integrations will not be triggered for this operation', required: false, defaultValue: true, }); export const limitProperty = Property.Number({ displayName: 'Limit', description: 'Maximum number of results to return (1-500, default: 20)', required: false, defaultValue: 20, }); export const offsetProperty = Property.Number({ displayName: 'Offset', description: 'Number of results to skip for pagination (default: 0)', required: false, defaultValue: 0, }); export function formatFieldValues(appFields: any[], formData: Record<string, any>): Record<string, any> { const fields: Record<string, any> = {}; for (const field of appFields) { const fieldKey = `field_${field.field_id}`; const fieldValue = formData[fieldKey]; if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') { const fieldType = field.type; switch (fieldType) { case 'text': fields[field.field_id] = { value: fieldValue.toString(), }; break; case 'number': fields[field.field_id] = { value: fieldValue.toString(), }; break; case 'money': if (typeof fieldValue === 'object' && fieldValue.value) { fields[field.field_id] = { value: fieldValue.value.toString(), currency: fieldValue.currency || 'USD', }; } break; case 'date': if (typeof fieldValue === 'object') { const dateObj: any = {}; if (fieldValue.start_date) dateObj.start_date = fieldValue.start_date; if (fieldValue.start_time) dateObj.start_time = fieldValue.start_time; if (fieldValue.end_date) dateObj.end_date = fieldValue.end_date; if (fieldValue.end_time) dateObj.end_time = fieldValue.end_time; if (Object.keys(dateObj).length > 0) { fields[field.field_id] = dateObj; } } break; case 'contact': case 'member': case 'app': case 'category': case 'status': case 'image': case 'file': case 'duration': case 'video': fields[field.field_id] = { value: Number(fieldValue), }; break; case 'progress': { const progressValue = Number(fieldValue); if (progressValue >= 0 && progressValue <= 100) { fields[field.field_id] = { value: progressValue, }; } break; } case 'email': case 'phone': if (typeof fieldValue === 'object' && fieldValue.value) { fields[field.field_id] = { value: fieldValue.value, type: fieldValue.type || (fieldType === 'email' ? 'work' : 'mobile'), }; } break; case 'location': fields[field.field_id] = { value: fieldValue.toString(), }; break; case 'embed': if (typeof fieldValue === 'object' && fieldValue.embed) { fields[field.field_id] = { embed: fieldValue.embed, file: fieldValue.file || null, }; } break; default: fields[field.field_id] = { value: fieldValue.toString(), }; } } } return fields; }

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