Skip to main content
Glama

Createve.AI Nexus

by spgoodman
CreateveAI.node.tsβ€’8.23 kB
import { IDataObject, IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription, NodeOperationError, NodeConnectionType, } from 'n8n-workflow'; import { executeApiRequest, pollQueueStatus, } from '../shared/GenericFunctions'; import { fetchOpenApiSchema, generateFields, isQueueEndpoint, parseEndpoints, } from '../shared/OpenApiParser'; import { handleBinaryInputData, processBinaryOutputData, } from '../shared/BinaryDataHandlers'; export class CreateveAI implements INodeType { description: INodeTypeDescription = { displayName: 'Createve.AI', name: 'createveAI', icon: 'file:createveai.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["endpoint"]}}', description: 'Consume Createve.AI Nexus API endpoints dynamically', defaults: { name: 'Createve.AI', color: '#1976d2', }, inputs: [{ type: NodeConnectionType.Main }], outputs: [{ type: NodeConnectionType.Main }], credentials: [ { name: 'createveAIApi', required: true, }, ], properties: [ // Endpoint selection { displayName: 'Endpoint', name: 'endpoint', type: 'options', noDataExpression: true, typeOptions: { loadOptionsMethod: 'getEndpoints', }, default: '', description: 'API endpoint to call', required: true, }, // Common parameter fields that might be used by API endpoints { displayName: 'Text', name: 'text', type: 'string', default: '', displayOptions: { show: { endpoint: ['text_processing/textAnalyzer', 'text_processing/textSummarizer'], }, }, description: 'Text to process', }, { displayName: 'Summary Length', name: 'summary_length', type: 'number', default: 3, displayOptions: { show: { endpoint: ['text_processing/textSummarizer'], }, }, description: 'Number of sentences in the summary', }, { displayName: 'Width', name: 'width', type: 'number', default: 512, displayOptions: { show: { endpoint: ['image_processing/imageResizer', 'image_processing/thumbnailGenerator'], }, }, description: 'Width of the output image', }, { displayName: 'Height', name: 'height', type: 'number', default: 512, displayOptions: { show: { endpoint: ['image_processing/imageResizer', 'image_processing/thumbnailGenerator'], }, }, description: 'Height of the output image', }, // Queue operations { displayName: 'Operation Mode', name: 'operationMode', type: 'options', options: [ { name: 'Submit & Wait', value: 'submitAndWait', description: 'Submit job and wait for results', }, { name: 'Submit Only', value: 'submitOnly', description: 'Submit job and return queue ID', }, { name: 'Check Status', value: 'checkStatus', description: 'Check status of existing queue item', }, ], default: 'submitAndWait', description: 'How to handle queue-based operations', }, { displayName: 'Queue ID', name: 'queueId', type: 'string', default: '', displayOptions: { show: { operationMode: ['checkStatus'], }, }, description: 'ID of the queue item to check', required: true, }, { displayName: 'Max Poll Time (seconds)', name: 'maxPollTime', type: 'number', default: 300, displayOptions: { show: { operationMode: ['submitAndWait'], }, }, description: 'Maximum time to wait for results', }, { displayName: 'Poll Interval (seconds)', name: 'pollInterval', type: 'number', default: 2, displayOptions: { show: { operationMode: ['submitAndWait'], }, }, description: 'Time between status checks', }, ], }; methods = { loadOptions: { async getEndpoints(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> { const credentials = await this.getCredentials('createveAIApi'); if (!credentials) { throw new NodeOperationError(this.getNode(), 'No credentials provided'); } try { const schema = await fetchOpenApiSchema.call(this, credentials); const endpoints = parseEndpoints(schema); return endpoints.map(endpoint => ({ name: endpoint.displayName, value: endpoint.path, description: endpoint.description, })); } catch (error) { throw new NodeOperationError( this.getNode(), `Failed to load API endpoints: ${error.message}`, ); } }, }, }; async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> { // Get credentials const credentials = await this.getCredentials('createveAIApi'); if (!credentials) { throw new NodeOperationError(this.getNode(), 'No credentials provided'); } const apiUrl = credentials.apiUrl as string; const apiKey = credentials.apiKey as string; const items = this.getInputData(); const returnData: INodeExecutionData[] = []; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { try { // Get parameters const endpoint = this.getNodeParameter('endpoint', itemIndex) as string; const operationMode = this.getNodeParameter('operationMode', itemIndex) as string; // Handle queue status operation if (operationMode === 'checkStatus') { const queueId = this.getNodeParameter('queueId', itemIndex) as string; // Poll for result (just once) const result = await pollQueueStatus.call( this, apiUrl, apiKey, endpoint, queueId, 1, 1, ); // Process binary data if present const returnItem = processBinaryOutputData( result, items[itemIndex], this.getExecutionId(), ); returnData.push(returnItem); continue; } // Build parameters from node inputs const parameters: IDataObject = {}; // Get endpoint-specific parameters if (endpoint === 'text_processing/textAnalyzer' || endpoint === 'text_processing/textSummarizer') { parameters.text = this.getNodeParameter('text', itemIndex) as string; if (endpoint === 'text_processing/textSummarizer') { parameters.summary_length = this.getNodeParameter('summary_length', itemIndex) as number; } } else if (endpoint === 'image_processing/imageResizer' || endpoint === 'image_processing/thumbnailGenerator') { parameters.width = this.getNodeParameter('width', itemIndex) as number; parameters.height = this.getNodeParameter('height', itemIndex) as number; // Get binary data for image handleBinaryInputData(parameters, items[itemIndex]); } // Execute the API request const response = await executeApiRequest.call( this, apiUrl, apiKey, endpoint, parameters, ); // Check if response includes queue_id (indicating a queued operation) if (response.queue_id && operationMode === 'submitAndWait') { // Get polling settings const maxPollTime = this.getNodeParameter('maxPollTime', itemIndex, 300) as number; const pollInterval = this.getNodeParameter('pollInterval', itemIndex, 2) as number; // Poll for result const result = await pollQueueStatus.call( this, apiUrl, apiKey, endpoint, response.queue_id as string, maxPollTime, pollInterval, ); // Process binary data if present const returnItem = processBinaryOutputData( result, items[itemIndex], this.getExecutionId(), ); returnData.push(returnItem); } else { // Either direct response or queue ID only const returnItem = processBinaryOutputData( response, items[itemIndex], this.getExecutionId(), ); returnData.push(returnItem); } } catch (error) { if (this.continueOnFail()) { returnData.push({ json: { error: error.message, }, }); continue; } throw error; } } return [returnData]; } }

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/spgoodman/createveai-nexus-server'

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