Skip to main content
Glama

mcp-google-sheets

add-attachment.ts5.64 kB
import { Property, createAction, OAuth2PropertyValue } from '@activepieces/pieces-framework'; import { getTaskListsDropdown, getTasksInListDropdown } from '../common'; import { TaskFileAttachment } from '@microsoft/microsoft-graph-types'; import { microsoftToDoAuth } from '../../index'; import { Client } from '@microsoft/microsoft-graph-client'; export const addAttachmentAction = createAction({ auth: microsoftToDoAuth, name: 'add_attachment', displayName: 'Add an Attachment', description: 'Adds an attachment to a task.', props: { task_list_id: Property.Dropdown({ displayName: 'Task List', description: 'The task list that contains the task.', required: true, refreshers: [], options: async ({ auth }) => { if (!(auth as OAuth2PropertyValue)?.access_token) { return { disabled: true, placeholder: 'Connect your account first', options: [], }; } return await getTaskListsDropdown(auth as OAuth2PropertyValue); }, }), task_id: Property.Dropdown({ displayName: 'Task', description: 'The task to which you are adding the attachment.', required: true, refreshers: ['task_list_id'], options: async ({ auth, task_list_id }) => { const authValue = auth as OAuth2PropertyValue; if (!authValue?.access_token || !task_list_id) { return { disabled: true, placeholder: !authValue?.access_token ? 'Connect your account first' : 'Select a task list first', options: [], }; } return await getTasksInListDropdown(authValue, task_list_id as string); }, }), file: Property.File({ displayName: 'File', description: 'The file to attach (up to 25 MB supported).', required: true, }), filename: Property.ShortText({ displayName: 'Attachment Name (Optional)', description: 'The name to display for the attachment. If left blank, the original filename will be used.', required: false, }), }, async run(context) { const { auth, propsValue } = context; const { task_list_id, task_id, file, filename } = propsValue; if (!task_list_id || !task_id) { throw new Error('Task List ID and Task ID are required'); } if (!file || !file.data) { throw new Error('File or file data is missing. Please provide a valid file.'); } const fileSizeInBytes = file.data.length; const fileSizeInMB = fileSizeInBytes / (1024 * 1024); const attachmentName = filename || file.filename; if (fileSizeInMB > 25) { throw new Error(`File size (${fileSizeInMB.toFixed(2)} MB) exceeds the 25 MB limit.`); } const client = Client.initWithMiddleware({ authProvider: { getAccessToken: () => Promise.resolve(auth.access_token), }, }); try { if (fileSizeInMB < 3) { const attachmentBody = { '@odata.type': '#microsoft.graph.taskFileAttachment', name: attachmentName, contentBytes: file.data.toString('base64'), contentType: file.extension ? `application/${file.extension}` : 'application/octet-stream', }; const response = await client .api(`/me/todo/lists/${task_list_id}/tasks/${task_id}/attachments`) .post(attachmentBody); return response as TaskFileAttachment; } const uploadSession = await client .api(`/me/todo/lists/${task_list_id}/tasks/${task_id}/attachments/createUploadSession`) .post({ attachmentInfo: { attachmentType: 'file', name: attachmentName, size: fileSizeInBytes, }, }); const uploadUrl = uploadSession.uploadUrl; const chunkSize = 4 * 1024 * 1024; let uploadedBytes = 0; while (uploadedBytes < fileSizeInBytes) { const chunkEnd = Math.min(uploadedBytes + chunkSize, fileSizeInBytes); const chunk = file.data.slice(uploadedBytes, chunkEnd); const contentRange = `bytes ${uploadedBytes}-${chunkEnd - 1}/${fileSizeInBytes}`; const uploadResponse = await client .api(uploadUrl) .headers({ 'Content-Length': chunk.length.toString(), 'Content-Range': contentRange, 'Content-Type': 'application/octet-stream', }) .put(chunk); uploadedBytes = chunkEnd; if (uploadedBytes >= fileSizeInBytes) { return uploadResponse as TaskFileAttachment; } } throw new Error('Upload completed but no response received'); } catch (error: any) { throw new Error(`Failed to add attachment: ${error?.message || 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