Skip to main content
Glama
form-sharing-tool.ts13.4 kB
import { z } from 'zod'; import { FormPublicationService } from '../services/form-publication-service'; import { TallyApiClient } from '../services/TallyApiClient'; import { FormVisibility, EmbedTheme, ShareLinkType, FormPublicationSettingsSchema, ShareLinkGenerationOptions } from '../models/form-sharing-models'; // Input schemas for MCP tools const PublishFormInputSchema = z.object({ formId: z.string().describe('The ID of the form to publish'), visibility: z.nativeEnum(FormVisibility).optional().describe('Form visibility setting'), password: z.string().optional().describe('Password for password-protected forms'), publishDate: z.string().datetime().optional().describe('Scheduled publish date'), unpublishDate: z.string().datetime().optional().describe('Scheduled unpublish date'), notificationEmails: z.array(z.string().email()).optional().describe('Email addresses to notify on submission') }); const UpdatePublicationSettingsInputSchema = z.object({ formId: z.string().describe('The ID of the form to update'), settings: FormPublicationSettingsSchema.partial().describe('Publication settings to update') }); const GenerateEmbedCodeInputSchema = z.object({ formId: z.string().describe('The ID of the form to generate embed code for'), theme: z.nativeEnum(EmbedTheme).optional().describe('Theme for the embedded form'), autoHeight: z.boolean().optional().describe('Whether to auto-adjust height'), width: z.string().optional().describe('Width of the embedded form'), height: z.string().optional().describe('Height of the embedded form'), hideHeader: z.boolean().optional().describe('Whether to hide the form header'), hideFooter: z.boolean().optional().describe('Whether to hide the form footer'), backgroundColor: z.string().optional().describe('Background color for the embed'), borderRadius: z.number().optional().describe('Border radius in pixels'), customCss: z.string().optional().describe('Custom CSS to apply') }); const GenerateShareLinkInputSchema = z.object({ formId: z.string().describe('The ID of the form to create a share link for'), type: z.nativeEnum(ShareLinkType).describe('Type of share link to generate'), customSlug: z.string().optional().describe('Custom slug for the share link'), password: z.string().optional().describe('Password protection for the link'), expirationHours: z.number().positive().optional().describe('Hours until the link expires'), maxUses: z.number().positive().optional().describe('Maximum number of uses for the link'), trackingEnabled: z.boolean().optional().describe('Whether to enable tracking for this link') }); const GetFormAnalyticsInputSchema = z.object({ formId: z.string().describe('The ID of the form to get analytics for'), period: z.enum(['day', 'week', 'month', 'year']).optional().describe('Time period for analytics data') }); const BulkOperationInputSchema = z.object({ operationType: z.enum(['publish', 'unpublish', 'update_settings', 'generate_links']).describe('Type of bulk operation'), formIds: z.array(z.string()).min(1).describe('Array of form IDs to operate on'), settings: z.record(z.any()).optional().describe('Settings to apply (for update_settings operation)') }); export class FormSharingTool { private publicationService: FormPublicationService; constructor(apiClient: TallyApiClient) { this.publicationService = new FormPublicationService(apiClient); } /** * Publish a form with specified settings */ async publishForm(input: z.infer<typeof PublishFormInputSchema>) { try { const { formId, visibility, password, publishDate, unpublishDate, notificationEmails } = PublishFormInputSchema.parse(input); const options: { password?: string; publishDate?: string; unpublishDate?: string; notificationEmails?: string[]; } = {}; if (password !== undefined) options.password = password; if (publishDate !== undefined) options.publishDate = publishDate; if (unpublishDate !== undefined) options.unpublishDate = unpublishDate; if (notificationEmails !== undefined) options.notificationEmails = notificationEmails; const result = await this.publicationService.publishForm(formId, visibility, options); return { success: true, data: result, message: `Form ${formId} published successfully with ${result.visibility} visibility` }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to publish form' }; } } /** * Unpublish a form */ async unpublishForm(input: { formId: string }) { try { const result = await this.publicationService.unpublishForm(input.formId); return { success: true, data: result, message: `Form ${input.formId} unpublished successfully` }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to unpublish form' }; } } /** * Get publication settings for a form */ async getPublicationSettings(input: { formId: string }) { try { const result = await this.publicationService.getPublicationSettings(input.formId); return { success: true, data: result, message: `Retrieved publication settings for form ${input.formId}` }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to get publication settings' }; } } /** * Update publication settings for a form */ async updatePublicationSettings(input: z.infer<typeof UpdatePublicationSettingsInputSchema>) { try { const { formId, settings } = UpdatePublicationSettingsInputSchema.parse(input); // Filter out undefined values from settings const filteredSettings = Object.fromEntries( Object.entries(settings).filter(([_, value]) => value !== undefined) ); const result = await this.publicationService.updatePublicationSettings(formId, filteredSettings); return { success: true, data: result, message: `Updated publication settings for form ${formId}` }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to update publication settings' }; } } /** * Generate embed code for a form */ async generateEmbedCode(input: z.infer<typeof GenerateEmbedCodeInputSchema>) { try { const { formId, ...embedSettings } = GenerateEmbedCodeInputSchema.parse(input); // Filter out undefined values from embedSettings const filteredEmbedSettings = Object.fromEntries( Object.entries(embedSettings).filter(([_, value]) => value !== undefined) ); const result = await this.publicationService.generateEmbedCode(formId, filteredEmbedSettings); return { success: true, data: result, message: `Generated embed code for form ${formId}`, embedCode: { html: result.html, javascript: result.javascript, iframe: result.iframe } }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to generate embed code' }; } } /** * Generate a shareable link for a form */ async generateShareLink(input: z.infer<typeof GenerateShareLinkInputSchema>) { try { const { formId, type, ...otherOptions } = GenerateShareLinkInputSchema.parse(input); // Filter out undefined values from otherOptions const filteredOptions = Object.fromEntries( Object.entries(otherOptions).filter(([_, value]) => value !== undefined) ); const options: ShareLinkGenerationOptions = { type, ...filteredOptions }; const result = await this.publicationService.generateShareLink(formId, options); return { success: true, data: result, message: `Generated ${result.type.toUpperCase()} share link for form ${formId}`, shareUrl: result.url }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to generate share link' }; } } /** * Get all share links for a form */ async getShareLinks(input: { formId: string }) { try { const result = await this.publicationService.getShareLinks(input.formId); return { success: true, data: result, message: `Retrieved ${result.length} share links for form ${input.formId}`, count: result.length }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to get share links' }; } } /** * Deactivate a share link */ async deactivateShareLink(input: { linkId: string }) { try { const result = await this.publicationService.deactivateShareLink(input.linkId); return { success: true, data: result, message: `Deactivated share link ${input.linkId}` }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to deactivate share link' }; } } /** * Get sharing statistics for a form */ async getFormSharingStats(input: { formId: string }) { try { const result = await this.publicationService.getFormSharingStats(input.formId); return { success: true, data: result, message: `Retrieved sharing statistics for form ${input.formId}`, summary: { totalViews: result.totalViews, totalSubmissions: result.totalSubmissions, conversionRate: result.conversionRate } }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to get sharing statistics' }; } } /** * Get detailed analytics for a form */ async getFormAnalytics(input: z.infer<typeof GetFormAnalyticsInputSchema>) { try { const { formId, period = 'week' } = GetFormAnalyticsInputSchema.parse(input); const result = await this.publicationService.getFormAnalytics(formId, period); return { success: true, data: result, message: `Retrieved ${period} analytics for form ${formId}`, period, dataPoints: result.metrics.dates.length }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to get form analytics' }; } } /** * Perform bulk operations on multiple forms */ async performBulkOperation(input: z.infer<typeof BulkOperationInputSchema>) { try { const { operationType, formIds, settings } = BulkOperationInputSchema.parse(input); const operation = { operationType, formIds, settings, status: 'pending' as const, completedCount: 0, failedCount: 0, errors: [], createdAt: new Date().toISOString() }; const result = await this.publicationService.performBulkOperation(operation); return { success: true, data: result, message: `Bulk ${operationType} operation completed`, summary: { total: formIds.length, completed: result.completedCount, failed: result.failedCount, status: result.status } }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to perform bulk operation' }; } } /** * Validate if a form can be published */ async validateFormForPublication(input: { formId: string }) { try { const result = await this.publicationService.validateFormForPublication(input.formId); return { success: true, data: result, message: result.canPublish ? `Form ${input.formId} is ready for publication` : `Form ${input.formId} has validation issues`, canPublish: result.canPublish, issuesCount: result.errors.length + result.warnings.length }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', message: 'Failed to validate form for publication' }; } } } // Export the input schemas for use in MCP server registration export { PublishFormInputSchema, UpdatePublicationSettingsInputSchema, GenerateEmbedCodeInputSchema, GenerateShareLinkInputSchema, GetFormAnalyticsInputSchema, BulkOperationInputSchema };

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/learnwithcc/tally-mcp'

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