Skip to main content
Glama

mcp-google-sheets

make-api-call.ts6.13 kB
import { Property, createAction } from '@activepieces/pieces-framework'; import { vtigerAuth } from '../..'; import { instanceLogin } from '../common'; import { AuthenticationType, HttpHeaders, HttpMessageBody, HttpMethod, HttpRequest, httpClient, } from '@activepieces/pieces-common'; //Docs: https://code.vtiger.com/vtiger/vtigercrm-manual/-/wikis/Webservice-Docs //Extra: https://help.vtiger.com/article/147111249-Rest-API-Manual export const makeAPICall = createAction({ name: 'make_api_call', auth: vtigerAuth, displayName: 'Custom API Call (Deprecated)', description: 'Performs an arbitrary authorized API call. (Deprecated)', props: { method: Property.StaticDropdown<HttpMethod>({ displayName: 'Http Method', description: 'Select the HTTP method you want to use', required: true, options: { options: [ { label: 'GET', value: HttpMethod.GET }, { label: 'POST', value: HttpMethod.POST }, { label: 'PUT', value: HttpMethod.PUT }, { label: 'PATCH', value: HttpMethod.PATCH }, { label: 'DELETE', value: HttpMethod.DELETE }, ], }, }), url: Property.ShortText({ displayName: 'URL', description: 'Absolute URL or path. If a relative path is provided (e.g., /me, /listtypes, /describe), it will be called against the REST base.', required: false, }), urlPath: Property.ShortText({ displayName: 'URL Path (deprecated)', description: "Deprecated. Use 'URL' instead. API endpoint's URL path (example: /me, /listtypes, /describe)", required: false, }), headers: Property.Json({ displayName: 'Headers', description: `Enter the desired request headers. Skip the authorization headers`, required: false, defaultValue: {}, }), data: Property.Json({ displayName: 'Data', description: `Enter the data to pass. if its POST, it will be sent as body data, and if GET, as query string`, required: false, defaultValue: {}, }), }, async run({ propsValue, auth }) { const method = propsValue.method ?? HttpMethod.GET; const urlPath = propsValue.urlPath; const url = propsValue.url; if (urlPath && !urlPath.startsWith('/')) { return { error: 'URL path must start with a slash, example: /me, /listtypes, /describe', }; } let finalUrl = `${auth.instance_url}/webservice.php`; let useRestAuth = false; if (url) { if (url.startsWith('http://') || url.startsWith('https://')) { finalUrl = url; } else if (url.startsWith('/')) { finalUrl = `${auth.instance_url}/restapi/v1/vtiger/default${url}`; useRestAuth = true; } else { finalUrl = `${auth.instance_url}/restapi/v1/vtiger/default/${url}`; useRestAuth = true; } } else if (urlPath) { finalUrl = `${auth.instance_url}/restapi/v1/vtiger/default${urlPath}`; useRestAuth = true; } const normalizeHeaders = (h: unknown): HttpHeaders => { const out: HttpHeaders = {}; if (h && typeof h === 'object' && !Array.isArray(h)) { for (const [k, v] of Object.entries(h as Record<string, unknown>)) { if (v === undefined || v === null) { out[k] = undefined; } else if (Array.isArray(v)) { out[k] = (v as unknown[]).map((x) => String(x)); } else if (typeof v === 'string') { out[k] = v; } else { out[k] = String(v); } } } return out; }; const headers: HttpHeaders = normalizeHeaders(propsValue.headers); if (useRestAuth) { // Default JSON for REST when not GET and no explicit content-type provided if ( method !== HttpMethod.GET && !Object.keys(headers).some( (k) => k.toLowerCase() === 'content-type' ) ) { headers['Content-Type'] = 'application/json'; } } else { // webservice.php defaults to urlencoded for POST operations if ( method !== HttpMethod.GET && !Object.keys(headers).some( (k) => k.toLowerCase() === 'content-type' ) ) { headers['Content-Type'] = 'application/x-www-form-urlencoded'; } } const httpRequest: HttpRequest<HttpMessageBody> = { url: finalUrl, method, headers, }; let data: Record<string, unknown> = propsValue.data ?? {}; const toQueryParams = (obj: Record<string, unknown>): Record<string, string> => { const qp: Record<string, string> = {}; for (const [k, v] of Object.entries(obj ?? {})) { if (v === undefined || v === null) continue; qp[k] = typeof v === 'string' ? v : JSON.stringify(v); } return qp; }; if (useRestAuth) { httpRequest.authentication = { type: AuthenticationType.BASIC, username: auth.username, password: auth.password, }; } else { const vtigerInstance = await instanceLogin( auth.instance_url, auth.username, auth.password ); if (vtigerInstance === null) return; data = { sessionName: vtigerInstance.sessionId ?? vtigerInstance.sessionName, ...(propsValue.data ?? {}), }; } if (method === HttpMethod.GET) { httpRequest['queryParams'] = toQueryParams(data); } else { // For REST with JSON default, send raw object; else url-encode const contentType = Object.entries(headers).find(([k]) => k.toLowerCase() === 'content-type')?.[1]; const ct = Array.isArray(contentType) ? contentType[0] : contentType; if (useRestAuth && ct === 'application/json') { httpRequest['body'] = data; } else { httpRequest['body'] = toQueryParams(data); } } const response = await httpClient.sendRequest<Record<string, unknown>[]>( httpRequest ); if ([200, 201].includes(response.status)) { return response.body; } return { error: 'Unexpected outcome!', }; }, });

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