Skip to main content
Glama

mcp-google-sheets

mcp-tool-testing-dialog.tsx6.59 kB
import { t } from 'i18next'; import { useForm, useFormContext } from 'react-hook-form'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogDescription, } from '@/components/ui/dialog'; import { Form } from '@/components/ui/form'; import { ScrollArea } from '@/components/ui/scroll-area'; import { PropertyType, PiecePropertyMap, PieceProperty, } from '@activepieces/pieces-framework'; import { FlowTrigger, McpPropertyType, mcpToolNaming, } from '@activepieces/shared'; import { AutoPropertiesFormComponent } from '../../piece-properties/auto-properties-form'; import { testStepHooks } from '../test-step-hooks'; type McpToolTestingDialogProps = { open: boolean; onOpenChange: (open: boolean) => void; onTestingSuccess: () => void; }; interface McpFormField { name: string; description?: string; required: boolean; type: McpPropertyType; defaultValue?: any; } function mapMcpTypeToPropertyType(mcpType: McpPropertyType): PropertyType { switch (mcpType) { case McpPropertyType.NUMBER: return PropertyType.NUMBER; case McpPropertyType.BOOLEAN: return PropertyType.CHECKBOX; case McpPropertyType.OBJECT: return PropertyType.OBJECT; case McpPropertyType.DATE: return PropertyType.DATE_TIME; case McpPropertyType.ARRAY: return PropertyType.ARRAY; case McpPropertyType.TEXT: default: return PropertyType.SHORT_TEXT; } } function McpToolTestingDialog({ open, onOpenChange, onTestingSuccess, }: McpToolTestingDialogProps) { const form = useFormContext<FlowTrigger>(); const formValues = form.getValues(); const formProps = formValues.settings.input.inputSchema as McpFormField[]; const { mutate: saveMockAsSampleData, isPending: isSavingMockdata } = testStepHooks.useSaveMockData({ onSuccess: () => { onTestingSuccess(); onOpenChange(false); }, }); const testingForm = useForm<Record<string, any>>({ shouldFocusError: true, defaultValues: formProps .filter((field: McpFormField) => field.name.trim() !== '') .reduce((acc, field: McpFormField) => { acc[field.name] = field.type === McpPropertyType.BOOLEAN ? false : ''; return acc; }, {} as Record<string, any>), resolver: (values) => { const errors = formProps.reduce((acc, field: McpFormField) => { if ( field.required && field.type !== McpPropertyType.BOOLEAN && !values[field.name] ) { acc[field.name] = { type: 'required', message: t('{field} is required', { field: field.name }), }; } return acc; }, {} as Record<string, { type: string; message: string }>); return { values: Object.keys(errors).length === 0 ? values : {}, errors, }; }, mode: 'onChange', }); const pieceProps = formProps.reduce((acc, field: McpFormField) => { const pieceProperty = { displayName: field.name, description: field.description || '', required: field.required, type: mapMcpTypeToPropertyType(field.type), defaultValue: field.defaultValue, } as PieceProperty; acc[field.name] = pieceProperty; return acc; }, {} as PiecePropertyMap); return ( <Dialog open={open} onOpenChange={onOpenChange}> <DialogContent className="w-full max-w-xl flex flex-col max-h-[90vh]"> <DialogHeader> <DialogTitle className="px-0.5">{t('Tool Sample Data')}</DialogTitle> <DialogDescription className="px-0.5"> {t( 'Fill in the following fields to use them as sample data for the trigger.', )} </DialogDescription> </DialogHeader> <Form {...testingForm}> <form className="grid space-y-4" onSubmit={testingForm.handleSubmit((data) => { const cleanedData = Object.fromEntries( Object.entries(data) .filter(([key, _]) => key.trim() !== '') .map(([key, value]) => [ mcpToolNaming.fixProperty(key), value, ]), ); saveMockAsSampleData(cleanedData); })} > <ScrollArea className="flex-1 max-h-[50vh]"> <div className="py-4"> {Object.keys(pieceProps).length > 0 ? ( <div className="space-y-4"> {Object.entries(pieceProps).map( ([fieldName, fieldProps]) => { const fieldError = testingForm.formState.errors[fieldName]; return ( <div key={fieldName} className="grid space-y-2 px-0.5" > <AutoPropertiesFormComponent props={{ [fieldName]: fieldProps }} allowDynamicValues={false} prefixValue="" useMentionTextInput={false} disabled={false} /> {fieldError && ( <p className="text-xs text-destructive font-medium"> {fieldError.message?.toString()} </p> )} </div> ); }, )} </div> ) : ( <div className="p-4 rounded-lg text-center"> <p className="text-sm text-muted-foreground"> {t('No input fields defined in the schema')} </p> </div> )} </div> </ScrollArea> <DialogFooter> <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={isSavingMockdata} > {t('Cancel')} </Button> <Button type="submit" loading={isSavingMockdata}> {t('Save')} </Button> </DialogFooter> </form> </Form> </DialogContent> </Dialog> ); } export { McpToolTestingDialog };

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