Usage Examples
Step-by-step scenarios for working with @reformer/mcp.
Scenario 1: Create a Form from Scratchβ
Task: Create a user registration form.
Request to AI:
Create a registration form with fields:
- Email
- Password (minimum 8 characters)
- Confirm password
- Terms agreement checkbox
What happens:
- AI calls
get_recommended_structureto determine the structure - Generates TypeScript interface:
interface RegistrationForm {
email: string;
password: string;
confirmPassword: string;
agreeToTerms: boolean;
}
- Creates form schema with components
- Adds validation:
import { validate, cross, defineValidationSchema } from '@reformer/core/validation';
import { required, email, minLength } from '@reformer/core/validators';
import type { ValidationError } from '@reformer/core';
// Password match reads a sibling field β a cross-field rule over the model snapshot.
const passwordsMatch = (f: RegistrationForm): ValidationError | null =>
f.confirmPassword && f.password && f.confirmPassword !== f.password
? { code: 'passwords-mismatch', message: 'Passwords do not match' }
: null;
const validationSchema = defineValidationSchema<RegistrationForm>(({ model }) => {
validate(model.$.email, [required(), email()]);
validate(model.$.password, [required(), minLength(8)]);
validate(model.$.confirmPassword, [required()]);
cross(model.$.confirmPassword, passwordsMatch);
// Inline rule β a plain (value) => ValidationError | null function.
validate(model.$.agreeToTerms, [
(value) => (value ? null : { code: 'terms-required', message: 'Agreement is required' }),
]);
});
The schema lives outside the layout tree. The app runs it on demand (e.g. on submit) with the
external runner β await validateModel(model, validationSchema). It returns a boolean and
routes errors onto the form nodes itself, so the UI highlights the fields.
- Checks code via
check_code
Scenario 2: Add Validationβ
Task: Add validation to an existing form.
Request to AI:
Add validation to the order form:
- Phone field: required, format +7 (XXX) XXX-XX-XX
- Delivery date: not earlier than tomorrow
- If deliveryType === "express", then deliveryTime is required
What happens:
- AI analyzes current code
- Uses
generate_validationto get rules - Generates validation:
import { validate, validateWhen, defineValidationSchema } from '@reformer/core/validation';
import { required, pattern } from '@reformer/core/validators';
import type { ValidationError } from '@reformer/core';
// Inline rule: delivery date not earlier than tomorrow.
const notBeforeTomorrow = (value: string): ValidationError | null => {
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(0, 0, 0, 0);
return new Date(value) >= tomorrow
? null
: { code: 'deliveryTooSoon', message: 'Select a date no earlier than tomorrow' };
};
const validationSchema = defineValidationSchema<OrderForm>(({ model }) => {
validate(model.$.phone, [
required(),
pattern(/^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/, { message: 'Format: +7 (XXX) XXX-XX-XX' }),
]);
validate(model.$.deliveryDate, [required(), notBeforeTomorrow]);
// Conditional branch: the deliveryTime rule is active only for express delivery,
// otherwise it is silenced (its error clears automatically).
validateWhen(
() => model.deliveryType === 'express',
() =>
validate(model.$.deliveryTime, [required({ message: 'Specify time for express delivery' })])
);
});
Scenario 3: Set Up Computed Fieldsβ
Task: Add automatic calculation to an order form.
Request to AI:
In the order form add:
- Automatic subtotal calculation (quantity * price) for each item
- Total sum across all items
- 10% discount if total is over 10000
What happens:
- AI uses
generate_behaviorto get patterns - Generates behaviors:
import { computeFrom } from '@reformer/core/behaviors';
const behavior: BehaviorSchemaFn<OrderForm> = (b) => ({
items: b.array({
// Subtotal for each item
subtotal: b.field(
computeFrom(['quantity', 'price'], (quantity, price) => (quantity ?? 0) * (price ?? 0))
),
}),
// Total sum
total: b.field(
computeFrom(
['items'],
(items) => items?.reduce((sum, item) => sum + (item.subtotal ?? 0), 0) ?? 0
)
),
// Discount
discount: b.field(computeFrom(['total'], (total) => (total > 10000 ? total * 0.1 : 0))),
// Final total with discount
finalTotal: b.field(computeFrom(['total', 'discount'], (total, discount) => total - discount)),
});
Scenario 4: Debug an Issueβ
Task: Understand why validation isn't working.
Request to AI:
My form doesn't show validation errors. What's wrong?
const MyForm = () => {
const form = createForm<UserForm>({
form: formSchema,
validation: validationSchema,
});
const email = useFormControl(form.email);
return (
<input
value={email.value}
onChange={(e) => email.setValue(e.target.value)}
/>
);
};
What happens:
-
AI uses
check_codefor analysis -
Finds issues:
- No
useMemoforcreateForm - No call to
markAsTouchedon blur - No error display
- No
-
Suggests fix:
const MyForm = () => {
const form = useMemo(() => createForm<UserForm>({
form: formSchema,
validation: validationSchema,
}), []);
const email = useFormControl(form.email);
return (
<div>
<input
value={email.value}
onChange={(e) => email.setValue(e.target.value)}
onBlur={() => email.markAsTouched()}
/>
{email.touched && email.errors.length > 0 && (
<span className="error">{email.errors[0]}</span>
)}
</div>
);
};
Scenario 5: Create Form from Specificationβ
Task: Create a complex multi-step form based on a requirements document.
Request to AI:
Create a form based on the specification spec/insurance-application-form.md
Use the reformer MCP server for:
1. Getting project structure (get_recommended_structure)
2. Generating types (generate_types)
3. Generating schema (generate_schema)
4. Generating validation (generate_validation)
5. Generating behaviors (generate_behavior)
6. Checking code (check_code)
7. Verifying code compilation (npm run build)
The form should:
- Be multi-step (6 steps)
- Have separate validation files for each step
- Use useStepForm for navigation
- Support computed fields (endDate, age, experience)
- Have conditional field visibility
- Compile without errors
What happens:
- AI reads the specification and analyzes requirements
- Calls
get_recommended_structureto determine file structure (MCP provides several schemes, selection depends on form complexity):
forms/
βββ insurance-application/
βββ types.ts
βββ schema.ts
βββ validation/
β βββ index.ts
β βββ step1-personal.ts
β βββ step2-contact.ts
β βββ step3-vehicle.ts
β βββ step4-insurance.ts
β βββ step5-payment.ts
β βββ step6-documents.ts
βββ behaviors.ts
βββ InsuranceApplicationForm.tsx
-
Generates types via
generate_types: -
Creates form schema via
generate_schema: -
Generates validation schema for each step via
generate_validation: -
Generates behavior schema (computed fields, conditions) via
generate_behavior: -
Checks code via
check_codeand fixes errors -
Runs
npm run buildto verify compilation
Result:
- Fully typed multi-step form
- Separate validation per step
- Automatic calculations (age, end date)
- Conditional field visibility
- Step navigation with validation
Tips for Working with AIβ
Be Specificβ
β Bad:
Make a form
β Good:
Create an order form with fields: Full name, phone, email, delivery address.
Phone in +7 format. Email required. Address minimum 10 characters.
Provide Contextβ
When debugging, always include the code:
Error "Cannot read property 'value' of undefined" on line 15.
[your code]
Use Iterationsβ
Start with a basic form, then add functionality:
- "Create a basic registration form"
- "Add email validation"
- "Add password matching check"
- "Add conditional company field"