Skip to main content
Glama

mcp-google-sheets

props.ts26.8 kB
import { OAuth2PropertyValue, Property } from '@activepieces/pieces-framework'; import { AuthenticationType, HttpMethod, HttpRequest, httpClient, } from '@activepieces/pieces-common'; export const props = { tenant_id: Property.Dropdown({ displayName: 'Organization', refreshers: [], required: true, options: async ({ auth }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/connections', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, }; const result = await httpClient.sendRequest< { id: string; authEventId: string; tenantId: string; tenantType: string; tenantName: string; createdDateUtc: string; updatedDateUtc: string; }[] >(request); if (result.status === 200) { return { disabled: false, options: [ { label: result.body?.[0].tenantName, value: result.body?.[0].tenantId, }, ], }; } return { disabled: true, options: [], placeholder: 'Error processing tenant_id', }; }, }), invoice_id: (required = false) => Property.Dropdown({ displayName: 'Invoice', description: 'Select an invoice', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/Invoices?summaryOnly=true&page=1', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const invoices: any[] = result.body?.Invoices ?? []; const options = invoices.slice(0, 50).map((inv) => { const labelParts = [inv.InvoiceNumber || inv.InvoiceID]; if (inv.Contact?.Name) labelParts.push(inv.Contact.Name); if (inv.Status) labelParts.push(inv.Status); return { label: labelParts.filter(Boolean).join(' • '), value: inv.InvoiceID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load invoices', }; }, }), payable_invoice_id: (required = false) => Property.Dropdown({ displayName: 'Invoice (Authorised)', description: 'Select an authorised invoice (sales or bill) to apply payment to.', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const url = 'https://api.xero.com/api.xro/2.0/Invoices?summaryOnly=true&page=1&Statuses=AUTHORISED'; const request: HttpRequest = { method: HttpMethod.GET, url, authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const invoices: any[] = result.body?.Invoices ?? []; const options = invoices.slice(0, 50).map((inv) => { const labelParts = [ inv.Type, inv.InvoiceNumber || inv.InvoiceID, inv.Contact?.Name, inv.AmountDue ? `Due ${inv.AmountDue}` : undefined, ]; return { label: labelParts.filter(Boolean).join(' • '), value: inv.InvoiceID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load invoices', }; }, }), sales_invoice_id: (required = false) => Property.Dropdown({ displayName: 'Sales Invoice (Sendable)', description: 'Select a sales invoice with a valid status for sending email (SUBMITTED, AUTHORISED, or PAID).', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const url = 'https://api.xero.com/api.xro/2.0/Invoices?summaryOnly=true&page=1&Statuses=SUBMITTED,AUTHORISED,PAID&where=Type%3d%3d%22ACCREC%22'; const request: HttpRequest = { method: HttpMethod.GET, url, authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const invoices: any[] = result.body?.Invoices ?? []; const options = invoices.slice(0, 50).map((inv) => { const labelParts = [inv.InvoiceNumber || inv.InvoiceID]; if (inv.Contact?.Name) labelParts.push(inv.Contact.Name); if (inv.Status) labelParts.push(inv.Status); return { label: labelParts.filter(Boolean).join(' • '), value: inv.InvoiceID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load sales invoices', }; }, }), editable_sales_invoice_id: (required = false) => Property.Dropdown({ displayName: 'Sales Invoice (Editable)', description: 'Select a sales invoice (ACCREC) with DRAFT or SUBMITTED status.', required, refreshers: ['tenant_id', 'allow_authorised'], options: async ({ auth, propsValue, tenant_id, allow_authorised }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const allowAuthorised = Boolean( typeof allow_authorised !== 'undefined' ? allow_authorised : (propsValue as Record<string, unknown>)?.['allow_authorised'] ); const statuses = allowAuthorised ? 'DRAFT,SUBMITTED,AUTHORISED' : 'DRAFT,SUBMITTED'; const url = `https://api.xero.com/api.xro/2.0/Invoices?summaryOnly=true&page=1&Statuses=${encodeURIComponent(statuses)}&where=Type%3d%3d%22ACCREC%22`; const request: HttpRequest = { method: HttpMethod.GET, url, authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const invoices: any[] = result.body?.Invoices ?? []; const options = invoices.slice(0, 50).map((inv) => { const labelParts = [inv.InvoiceNumber || inv.InvoiceID]; if (inv.Contact?.Name) labelParts.push(inv.Contact.Name); if (inv.Status) labelParts.push(inv.Status); return { label: labelParts.filter(Boolean).join(' • '), value: inv.InvoiceID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load sales invoices', }; }, }), credit_note_id: (required = false) => Property.Dropdown({ displayName: 'Credit Note', description: 'Select a credit note to allocate from', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/CreditNotes', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const creditNotes: any[] = result.body?.CreditNotes ?? []; const options = creditNotes.slice(0, 50).map((cn) => { const labelParts = [cn.CreditNoteNumber || cn.CreditNoteID]; if (cn.Contact?.Name) labelParts.push(cn.Contact.Name); if (cn.Type) labelParts.push(cn.Type); if (cn.Status) labelParts.push(cn.Status); return { label: labelParts.filter(Boolean).join(' • '), value: cn.CreditNoteID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load credit notes', }; }, }), contact_id: (required = false) => Property.ShortText({ displayName: 'Contact ID', description: 'ID of the contact to create invoice for.', required: required, }), contact_dropdown: (required = false) => Property.Dropdown({ displayName: 'Contact', description: 'Select a contact', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/Contacts?summaryOnly=true&page=1', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const contacts: any[] = result.body?.Contacts ?? []; const options = contacts.slice(0, 100).map((c) => { const labelParts = [c.Name]; if (c.EmailAddress) labelParts.push(c.EmailAddress); return { label: labelParts.filter(Boolean).join(' • '), value: c.ContactID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load contacts', }; }, }), contact_name: (required = false) => Property.ShortText({ displayName: 'Contact Name', description: 'Contact name, in full.', required: required, }), contact_email: (required = false) => Property.ShortText({ displayName: 'Contact Email', description: 'Email address of the contact.', required: required, }), bank_account_id: (required = false) => Property.Dropdown({ displayName: 'Bank Account', description: 'Select a bank account', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/Accounts', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const accounts: any[] = result.body?.Accounts ?? []; const options = accounts .filter( (acc) => acc?.Type === 'BANK' || acc?.EnablePaymentsToAccount === true ) .slice(0, 100) .map((acc) => { const labelParts = [acc.Name || acc.Code || acc.AccountID]; if (acc.Code) labelParts.push(acc.Code); return { label: labelParts.filter(Boolean).join(' • '), value: acc.AccountID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load bank accounts', }; }, }), branding_theme_id: (required = false) => Property.Dropdown({ displayName: 'Branding Theme', description: 'Select a branding theme', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/BrandingThemes', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const themes: any[] = result.body?.BrandingThemes ?? []; const options = themes.slice(0, 50).map((t) => ({ label: t.Name || t.BrandingThemeID, value: t.BrandingThemeID, })); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load branding themes', }; }, }), purchase_order_id: (required = false) => Property.Dropdown({ displayName: 'Purchase Order', description: 'Select a purchase order to update', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/PurchaseOrders?page=1', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const pos: any[] = result.body?.PurchaseOrders ?? []; const options = pos.slice(0, 100).map((po) => { const labelParts = [ po.PurchaseOrderNumber || po.PurchaseOrderID, po.Contact?.Name, po.Status, ]; return { label: labelParts.filter(Boolean).join(' • '), value: po.PurchaseOrderID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load purchase orders', }; }, }), account_code: (allowedTypes: string[], required = false) => Property.Dropdown({ displayName: 'Account', description: 'Select an account', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/Accounts', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const accounts: any[] = result.body?.Accounts ?? []; const options = accounts .filter((acc) => Array.isArray(allowedTypes) ? allowedTypes.includes(acc?.Type) : true ) .slice(0, 200) .map((acc) => { const labelParts = [acc.Name || acc.Code || acc.AccountID]; if (acc.Code) labelParts.push(acc.Code); if (acc.Type) labelParts.push(acc.Type); return { label: labelParts.filter(Boolean).join(' • '), value: acc.AccountID, }; }); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load accounts', }; }, }), project_id: (required = false) => Property.Dropdown({ displayName: 'Project', description: 'Select a project', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/projects.xro/2.0/Projects?page=1', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const projects: any[] = result.body?.items ?? result.body?.Projects ?? []; const options = projects.slice(0, 200).map((p) => ({ label: p.name || p.projectId, value: p.projectId, })); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load projects', }; }, }), currency_code: (required = false) => Property.Dropdown({ displayName: 'Currency', description: 'Select a currency code', required, refreshers: ['tenant_id'], options: async ({ auth, propsValue, tenant_id }) => { if (!auth) return { disabled: true, options: [], placeholder: 'Please authenticate first', }; const rawTenant = tenant_id ?? (propsValue as Record<string, any>)?.['tenant_id']; const tenantId: string | undefined = typeof rawTenant === 'string' ? rawTenant : rawTenant?.value || rawTenant?.tenantId || rawTenant?.id; if (!tenantId) return { disabled: true, options: [], placeholder: 'Select an Organization first', }; const request: HttpRequest = { method: HttpMethod.GET, url: 'https://api.xero.com/api.xro/2.0/Currencies', authentication: { type: AuthenticationType.BEARER_TOKEN, token: (auth as OAuth2PropertyValue).access_token, }, headers: { 'Xero-Tenant-Id': tenantId, }, }; const result = await httpClient.sendRequest<Record<string, any>>(request); if (result.status === 200) { const currencies: any[] = result.body?.Currencies ?? []; const options = currencies.slice(0, 300).map((c) => ({ label: `${c.Code} • ${c.Description ?? ''}`.trim(), value: c.Code, })); return { disabled: false, options }; } return { disabled: true, options: [], placeholder: 'Unable to load currencies', }; }, }), };

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