Skip to main content
Glama
index.js10.5 kB
/** * Field Operations Module - Main exports * Provides intelligent field management for Gravity MCP */ // Import core components for internal use import { FieldManager } from './field-manager.js'; import { DependencyTracker } from './field-dependencies.js'; import { PositionEngine } from './field-positioner.js'; import { testConfig, TestFormManager } from '../config/test-config.js'; // Re-export components export { FieldManager, DependencyTracker, PositionEngine, testConfig, TestFormManager }; /** * Create and configure field operations infrastructure * @param {object} apiClient - Gravity Forms API client * @param {object} fieldRegistry - Field type registry * @param {object} validator - Field validator * @returns {object} Configured field operations components */ export function createFieldOperations(apiClient, fieldRegistry, validator) { // Create core components const dependencyTracker = new DependencyTracker(); const positionEngine = new PositionEngine(); const fieldManager = new FieldManager(apiClient, fieldRegistry, validator); // Inject dependencies fieldManager.dependencyTracker = dependencyTracker; fieldManager.positionEngine = positionEngine; // Create test form manager if in test mode const testFormManager = testConfig.isTestMode() ? new TestFormManager(apiClient, testConfig) : null; return { fieldManager, dependencyTracker, positionEngine, testFormManager, config: testConfig }; } /** * Field operation tool handlers for MCP integration */ export const fieldOperationHandlers = { /** * Add field to form */ async gf_add_field(params, { fieldManager }) { const { form_id, field_type, properties = {}, position = {}, test_mode = false } = params; try { const result = await fieldManager.addField( form_id, field_type, properties, position ); return { success: true, ...result }; } catch (error) { return { success: false, error: error.message, form_id, field_type }; } }, /** * Update field properties */ async gf_update_field(params, { fieldManager }) { const { form_id, field_id, properties, force = false, test_mode = false } = params; try { const result = await fieldManager.updateField( form_id, field_id, properties ); // Check for breaking changes if not forced if (!force && result.warnings?.dependencies?.length > 0) { return { success: false, error: 'Field has dependencies that may be affected', ...result, suggestion: 'Use force=true to update anyway' }; } return { success: true, ...result }; } catch (error) { return { success: false, error: error.message, form_id, field_id }; } }, /** * Delete field with dependency checking */ async gf_delete_field(params, { fieldManager }) { const { form_id, field_id, cascade = false, force = false, test_mode = false } = params; try { const result = await fieldManager.deleteField( form_id, field_id, { cascade, force } ); return result; } catch (error) { return { success: false, error: error.message, form_id, field_id }; } }, /** * List available field types */ async gf_list_field_types(params, { fieldRegistry }) { const { category, feature, search, include_variants = false } = params; try { const allTypes = Object.entries(fieldRegistry).map(([type, def]) => ({ type, label: def.label, category: def.category, description: def.description, icon: def.icon, supports: { required: def.supportsRequired || false, conditional: def.supportsConditional || false, duplicate: def.supportsDuplicate || false, prepopulate: def.supportsPrepopulate || false, visibility: def.supportsVisibility || false, description: def.supportsDescription || false, validation: def.supportsValidation || false, css_class: def.supportsCssClass || false }, variants: include_variants && def.variants ? Object.entries(def.variants).map(([name, variant]) => ({ name, label: variant.label, description: variant.description, settings: variant.settings })) : undefined, storage: def.storage, validation: def.validation })); // Apply filters let filteredTypes = allTypes; if (category) { filteredTypes = filteredTypes.filter(t => t.category === category); } if (feature) { filteredTypes = filteredTypes.filter(t => t.supports[feature] === true); } if (search) { const searchLower = search.toLowerCase(); filteredTypes = filteredTypes.filter(t => t.type.toLowerCase().includes(searchLower) || t.label.toLowerCase().includes(searchLower) || (t.description && t.description.toLowerCase().includes(searchLower)) ); } // Get unique categories const categories = [...new Set(allTypes.map(t => t.category))].filter(Boolean); return { success: true, field_types: filteredTypes, total: filteredTypes.length, categories }; } catch (error) { return { success: false, error: error.message, field_types: [], total: 0, categories: [] }; } } }; /** * MCP Tool Definitions for field operations */ export const fieldOperationTools = [ { name: 'gf_add_field', description: 'Add a new field to a Gravity Form with intelligent defaults and positioning', inputSchema: { type: 'object', properties: { form_id: { type: 'number', description: 'The ID of the form to add the field to' }, field_type: { type: 'string', description: 'The type of field to add (e.g., text, email, address)' }, properties: { type: 'object', description: 'Field properties and settings', properties: { label: { type: 'string', description: 'Field label' }, description: { type: 'string', description: 'Field description' }, isRequired: { type: 'boolean', description: 'Whether field is required' }, placeholder: { type: 'string', description: 'Placeholder text' }, defaultValue: { type: 'string', description: 'Default value' }, cssClass: { type: 'string', description: 'CSS class names' }, size: { type: 'string', enum: ['small', 'medium', 'large'], description: 'Field size' }, visibility: { type: 'string', enum: ['visible', 'hidden', 'administrative'], description: 'Field visibility' } } }, position: { type: 'object', description: 'Field positioning configuration', properties: { mode: { type: 'string', enum: ['append', 'prepend', 'after', 'before', 'index'], description: 'Positioning mode' }, reference: { type: 'number', description: 'Reference field ID (for after/before) or index' }, page: { type: 'number', description: 'Page number for multi-page forms' } } }, test_mode: { type: 'boolean', description: 'Use test configuration', default: false } }, required: ['form_id', 'field_type'] } }, { name: 'gf_update_field', description: 'Update an existing field in a Gravity Form', inputSchema: { type: 'object', properties: { form_id: { type: 'number', description: 'The ID of the form containing the field' }, field_id: { type: 'number', description: 'The ID of the field to update' }, properties: { type: 'object', description: 'Field properties to update' }, force: { type: 'boolean', description: 'Force update even if there are dependencies', default: false }, test_mode: { type: 'boolean', description: 'Use test configuration', default: false } }, required: ['form_id', 'field_id', 'properties'] } }, { name: 'gf_delete_field', description: 'Delete a field from a Gravity Form with dependency checking', inputSchema: { type: 'object', properties: { form_id: { type: 'number', description: 'The ID of the form containing the field' }, field_id: { type: 'number', description: 'The ID of the field to delete' }, cascade: { type: 'boolean', description: 'Automatically clean up dependencies', default: false }, force: { type: 'boolean', description: 'Force deletion despite dependencies', default: false }, test_mode: { type: 'boolean', description: 'Use test configuration', default: false } }, required: ['form_id', 'field_id'] } }, { name: 'gf_list_field_types', description: 'List all available Gravity Forms field types with their capabilities', inputSchema: { type: 'object', properties: { category: { type: 'string', description: 'Filter by category (standard, advanced, pricing, post)' }, feature: { type: 'string', description: 'Filter by feature support (required, conditional, duplicate)' }, search: { type: 'string', description: 'Search in field type names and labels' }, include_variants: { type: 'boolean', description: 'Include field variants in response', default: false } } } } ];

Latest Blog Posts

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/GravityKit/gravity-mcp'

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