Documentation Index Fetch the complete documentation index at: https://docs.synapsebuilder.org/llms.txt
Use this file to discover all available pages before exploring further.
What is MCP?
The Model Context Protocol (MCP) is Shopify’s official validation system that checks extensions and functions against their API schemas and best practices.
Why Validation Matters
Without proper validation:
❌ Extensions fail at deploy time
❌ Runtime errors in production
❌ Poor customer experience
❌ Wasted development time
With MCP validation:
✅ Catch errors before deployment
✅ Guarantee API compatibility
✅ Follow Shopify best practices
✅ Faster development cycles
Validation Process
1. Component Validation
Checks that all UI components exist and are used correctly:
// ✅ VALID - Correct import and usage
import { Banner , useCart } from '@shopify/ui-extensions-react/checkout' ;
export default function MyExtension () {
const cart = useCart ();
return < Banner title = "Hello" > Message </ Banner > ;
}
// ❌ INVALID - Wrong import path
import { Banner } from '@shopify/ui-extensions-react' ;
// ❌ INVALID - Component doesn't exist
import { CustomBanner } from '@shopify/ui-extensions-react/checkout' ;
// ❌ INVALID - Wrong props
< Banner invalidProp = "value" > Content </ Banner >
What MCP Checks:
Component exists in the specified package
Import path is correct (/checkout, /admin, etc.)
Props match the component’s TypeScript definition
Required props are provided
Prop types are correct
2. Hook Validation
Ensures React hooks follow all rules:
// ✅ VALID - Hook at top level
function Component () {
const cart = useCart ();
const settings = useSettings ();
if ( ! cart ) return null ;
return < Banner />;
}
// ❌ INVALID - Conditional hook
function Component () {
const cart = useCart ();
if ( cart . lines . length > 0 ) {
const settings = useSettings (); // Error!
}
}
// ❌ INVALID - Hook in callback
function Component () {
const handleClick = () => {
const cart = useCart (); // Error!
};
}
// ❌ INVALID - Hook in loop
function Component () {
return items . map ( item => {
const data = useItemData ( item . id ); // Error!
});
}
What MCP Checks:
Hooks are called at top level only
Hooks are called in the same order every render
Hooks are not called conditionally
Hook names start with “use”
Custom hooks follow hook rules
3. GraphQL Validation
Validates queries against Shopify’s official schema:
# ✅ VALID - Correct schema
query {
cart {
id
cost {
totalAmount {
amount
currencyCode
}
}
lines {
id
quantity
merchandise {
... on ProductVariant {
id
title
price {
amount
}
}
}
}
}
}
# ❌ INVALID - Field doesn't exist
query {
cart {
totalPrice # Wrong field name
}
}
# ❌ INVALID - Missing required selections
query {
cart {
cost {
totalAmount # Missing amount and currencyCode
}
}
}
# ❌ INVALID - Wrong type
query {
cart {
lines {
merchandise {
title # Missing fragment for interface
}
}
}
}
What MCP Checks:
All fields exist in the schema
Required field selections are present
Fragments are used correctly for interfaces/unions
Variables have correct types
Directives are valid
4. Extension Target Validation
Verifies extension targets are valid:
# ✅ VALID - Checkout targets
[[ extensions . targeting ]]
target = "purchase.checkout.block.render"
target = "purchase.checkout.actions.render-before"
target = "purchase.checkout.cart-line-item.render-after"
target = "purchase.checkout.shipping-option-list.render-after"
# ✅ VALID - Admin targets
target = "admin.product-details.block.render"
target = "admin.product-details.action.render"
target = "admin.order-details.block.render"
# ✅ VALID - POS targets
target = "pos.purchase.post.block.render"
# ❌ INVALID - Target doesn't exist
target = "checkout.custom.block"
target = "admin.custom-page.render"
What MCP Checks:
Target exists in Shopify’s extension API
Target is appropriate for extension type
Module path matches target expectations
API version supports the target
For Shopify Functions, validates input queries:
# ✅ VALID - Discount function input
query {
cart {
lines {
quantity
merchandise {
__typename
... on ProductVariant {
id
product {
id
}
}
}
}
}
discountNode {
metafield ( namespace : "$app:function-config" , key : "config" ) {
value
}
}
}
# ❌ INVALID - Missing discountNode for discount function
query {
cart {
lines {
quantity
}
}
}
# ❌ INVALID - Wrong metafield namespace
query {
discountNode {
metafield ( namespace : "custom" , key : "config" ) {
value
}
}
}
Validation Scores
Synapse provides a score from 0-100:
Score Breakdown
Score Rating Meaning Action
95-100 Excellent Production-ready, no issues Deploy immediately 90-94 Very Good Minor style issues Deploy, consider fixes 80-89 Good Some warnings Review warnings 70-79 Fair Multiple issues Fix before deploy 60-69 Poor Significant problems Requires self-correction 0-59 Failed Critical errors Must fix
What Affects Your Score
Deductions:
Critical error (missing import, invalid GraphQL): -15 points
Major warning (unused variable, incorrect prop type): -5 points
Minor warning (missing comment, style issue): -2 points
Best practice violation: -3 points
Bonuses:
Comprehensive error handling: +5 points
TypeScript types used correctly: +3 points
Accessibility attributes present: +2 points
Performance optimizations: +2 points
Common Validation Errors
Error: Module '@shopify/ui-extensions-react' has no exported member 'Banner'Cause: Missing /checkout or /admin in import pathFix: // Wrong
import { Banner } from '@shopify/ui-extensions-react' ;
// Right
import { Banner } from '@shopify/ui-extensions-react/checkout' ;
Error: Cannot query field 'totalPrice' on type 'Cart'Cause: Field name doesn’t exist in schemaFix: # Wrong
query {
cart {
totalPrice
}
}
# Right
query {
cart {
cost {
totalAmount {
amount
}
}
}
}
Error: React Hook "useCart" is called conditionallyCause: Hook inside if statement or callbackFix: // Wrong
function Component () {
if ( condition ) {
const cart = useCart ();
}
}
// Right
function Component () {
const cart = useCart ();
if ( ! condition ) return null ;
// use cart
}
Error: Extension target 'checkout.custom.block' is not validCause: Target doesn’t exist in Shopify’s APIFix: # Wrong
target = "checkout.custom.block"
# Right
target = "purchase.checkout.block.render"
Validation Report Example
When you generate code, you’ll see a report like this:
{
"score" : 92 ,
"status" : "passed" ,
"issues" : [
{
"severity" : "warning" ,
"category" : "best-practice" ,
"message" : "Consider adding error boundary" ,
"line" : 15 ,
"suggestion" : "Wrap component in ErrorBoundary for better error handling"
}
],
"checks" : {
"syntax" : "passed" ,
"components" : "passed" ,
"hooks" : "passed" ,
"graphql" : "passed" ,
"target" : "passed" ,
"typescript" : "passed"
},
"details" : {
"components_validated" : 3 ,
"hooks_validated" : 2 ,
"graphql_queries" : 1 ,
"execution_time_ms" : 245
}
}
How to Improve Your Score
1. Use TypeScript Types
// Good - explicit types
interface Props {
title : string ;
amount : number ;
}
export default function Component ({ title , amount } : Props ) {
return < Banner title ={ title }>{ amount } </ Banner > ;
}
// Better - use Shopify's types
import type { Cart } from '@shopify/ui-extensions-react/checkout' ;
function processCart ( cart : Cart ) {
// Type-safe operations
}
2. Add Error Handling
// Good
function Component () {
const cart = useCart ();
if ( ! cart ) {
return < Text > Loading ...</ Text > ;
}
if ( cart . lines . length === 0 ) {
return < Text > Cart is empty </ Text > ;
}
return < Banner > Items : {cart.lines. length } </ Banner > ;
}
3. Follow React Best Practices
// Good - memoization for performance
const expensiveValue = useMemo (() => {
return cart . lines . reduce (( sum , line ) => sum + line . quantity , 0 );
}, [ cart . lines ]);
// Good - cleanup in useEffect
useEffect (() => {
const timer = setInterval (() => {
// do something
}, 1000 );
return () => clearInterval ( timer );
}, []);
4. Add Accessibility
< Button
onPress = { handleClick }
accessibilityLabel = "Add to cart"
accessibilityRole = "button"
>
Add to Cart
</ Button >
Advanced Validation
Custom Validation Rules
You can add project-specific rules:
// In your synapse config
{
"validation" : {
"rules" : {
"require-error-boundaries" : "warn" ,
"max-component-lines" : [ "error" , 200 ],
"no-inline-styles" : "warn"
}
}
}
Pre-deployment Checks
Before deploying, Synapse runs additional checks:
Bundle size analysis
Performance profiling
Security scanning
Dependency audit
Next Steps
Self-Correction How automatic fixes work
Best Practices Write code that passes validation
Debugging Fix validation errors manually
Extension Standards Shopify’s quality guidelines