Company Logo
MCIP

The Registration Mental Model

Think of store registration like setting up a new contact in your phone. You add their name (store identifier), their number (API endpoint), and maybe some notes about how to reach them (authentication details). Once saved, you can call them anytime without looking up the details again.

MCIP works the same way. Register a store once with its connection details, and every AI agent query automatically knows how to reach it. No repeated configuration, no manual routing—just seamless connectivity.

Part 1: The Registration Process

Single Store Registration

The simplest setup: one MCIP instance, one store. Perfect for getting started or dedicated deployments.

Environment Configuration:

# .env

# Store Identity
STORE_PROVIDER=VENDURE
STORE_ID=my-awesome-store
STORE_NAME="My Awesome Store"

# Connection Details
SOURCE_URL=https://api.mystore.com/shop-api
STOREFRONT_URL=https://mystore.com

# Authentication
SOURCE_API_KEY=your-api-key-here

# For GraphQL platforms
GRAPHQL_QUERY={products{items{id name slug description variants{id sku name price priceWithTax currencyCode stockLevel}featuredAsset{preview source}}}}

Verification:

# Start MCIP
docker-compose up -d

# Trigger initial sync
curl -X POST http://localhost:8080/admin/sync \
  -H "x-admin-api-key: your-admin-key"

# Verify products loaded
curl "http://localhost:8080/search?q=test"

Checkpoint: You should see products in the search response. If you see an empty array, check the sync logs.

Multi-Store Registration

For aggregating products across multiple platforms, MCIP supports configuration-based multi-store setup.

stores.yaml Configuration:

# config/stores.yaml

stores:
  - id: electronics-hub
    name: "Electronics Hub"
    provider: SHOPIFY
    enabled: true
    priority: 1
    connection:
      url: https://electronics-hub.myshopify.com/admin/api/2024-01/products.json
      auth:
        type: bearer
        token: ${ELECTRONICS_HUB_TOKEN}
    options:
      timeout: 5000
      retries: 3
      currency: USD

  - id: fashion-outlet
    name: "Fashion Outlet"
    provider: WOOCOMMERCE
    enabled: true
    priority: 2
    connection:
      url: https://fashion-outlet.com/wp-json/wc/v3/products
      auth:
        type: basic
        username: ${FASHION_OUTLET_KEY}
        password: ${FASHION_OUTLET_SECRET}
    options:
      timeout: 8000
      retries: 2
      currency: EUR

  - id: home-goods
    name: "Home & Garden"
    provider: VENDURE
    enabled: true
    priority: 3
    connection:
      url: https://homegoods.com/shop-api
      graphqlQuery: ${VENDURE_QUERY}
    options:
      timeout: 5000
      currency: USD

Environment for Multi-Store:

# .env.production

# Store tokens (referenced in stores.yaml)
ELECTRONICS_HUB_TOKEN=shpat_xxxxxxxxxxxxx
FASHION_OUTLET_KEY=ck_xxxxxxxxxxxxx
FASHION_OUTLET_SECRET=cs_xxxxxxxxxxxxx

# Vendure query (minified)
VENDURE_QUERY={products{items{id name slug description variants{id sku price}featuredAsset{preview}}}}

# Config path
STORES_CONFIG_PATH=./config/stores.yaml

Part 2: Configuration Management

Configuration Hierarchy

MCIP loads configuration in layers, each overriding the previous:

  1. Default values (built into code) ↓
  2. stores.yaml (file-based config) ↓
  3. Environment variables (.env) ↓
  4. Runtime overrides (API calls)

This means you can set defaults in stores.yaml, override sensitive values via environment variables, and make temporary changes through the API—all without redeploying.

Store Configuration Schema

Here's the complete configuration schema with all available options:

interface StoreConfig {
  // Identity
  id: string;                    // Unique identifier (lowercase, no spaces)
  name: string;                  // Human-readable display name
  provider: string;              // Adapter to use: VENDURE, SHOPIFY, etc.
  enabled: boolean;              // Whether to include in searches
  
  // Priority & Behavior
  priority: number;              // Lower = higher priority (1 is highest)
  weight: number;                // Search result weighting (0.0 - 1.0)
  
  // Connection
  connection: {
    url: string;                 // API endpoint URL
    auth?: AuthConfig;           // Authentication details
    graphqlQuery?: string;       // For GraphQL endpoints
    headers?: Record<string, string>;  // Custom headers
  };
  
  // Operational Settings
  options: {
    timeout: number;             // Request timeout in ms (default: 5000)
    retries: number;             // Retry attempts on failure (default: 3)
    retryDelay: number;          // Delay between retries in ms (default: 1000)
    currency: string;            // Default currency code
    rateLimit?: {
      requests: number;          // Max requests per window
      window: number;            // Window size in ms
    };
  };
  
  // Health Check
  healthCheck?: {
    enabled: boolean;            // Enable health monitoring
    interval: number;            // Check interval in ms (default: 60000)
    endpoint?: string;           // Custom health endpoint
    timeout: number;             // Health check timeout (default: 3000)
  };
  
  // Sync Settings
  sync?: {
    schedule?: string;           // Cron expression for auto-sync
    batchSize: number;           // Products per batch (default: 100)
    fullSyncInterval?: number;   // Hours between full syncs
  };
}

Configuration Validation

MCIP validates all store configurations on startup:

# Check configuration without starting
npm run config:validate

# Output:
# ✓ Store 'electronics-hub' - Valid
# ✓ Store 'fashion-outlet' - Valid
# ✗ Store 'home-goods' - Invalid: missing required field 'connection.url'

Part 3: Credential Handling

Security Best Practices

Never commit credentials to version control. This seems obvious, but let's make it foolproof:

# .gitignore

# Environment files
.env
.env.*
!.env.example

# Config with secrets
config/stores.yaml
!config/stores.example.yaml

Authentication Types

MCIP supports multiple authentication methods:

Bearer Token (Shopify, custom APIs):

auth:
  type: bearer
  token: ${STORE_API_TOKEN}

Basic Auth (WooCommerce, legacy systems):

auth:
  type: basic
  username: ${STORE_KEY}
  password: ${STORE_SECRET}

API Key Header (various platforms):

auth:
  type: header
  headerName: X-API-Key
  value: ${STORE_API_KEY}

OAuth2 (enterprise systems):

auth:
  type: oauth2
  clientId: ${OAUTH_CLIENT_ID}
  clientSecret: ${OAUTH_CLIENT_SECRET}
  tokenUrl: https://auth.platform.com/oauth/token
  scopes:
    - read_products
    - read_inventory

Credential Rotation

When API keys need updating, MCIP supports zero-downtime rotation:

# Update credential in environment
export NEW_STORE_TOKEN=shpat_new_token_here

# Trigger config reload via API
curl -X POST http://localhost:8080/admin/reload-config \
  -H "x-admin-api-key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{"storeId": "electronics-hub", "credential": "NEW_STORE_TOKEN"}'

# Response:
# {"status": "success", "message": "Credentials updated for electronics-hub"}

Part 4: Health Checks

Why Health Checks Matter

Imagine an AI agent trying to search a store that's been down for hours. Without health checks, every query fails slowly. With health checks, MCIP knows which stores are healthy and routes around problems automatically.

Configuring Health Checks

# In stores.yaml

healthCheck:
  enabled: true
  interval: 60000          # Check every minute
  timeout: 3000            # 3 second timeout
  endpoint: /health        # Custom endpoint (optional)
  failureThreshold: 3      # Mark unhealthy after 3 failures
  successThreshold: 2      # Mark healthy after 2 successes

Health Check Endpoints

Check all stores:

curl http://localhost:8080/health/stores

Response:

{
  "status": "degraded",
  "stores": [
    {
      "id": "electronics-hub",
      "name": "Electronics Hub",
      "status": "healthy",
      "lastCheck": "2025-01-15T10:30:00Z",
      "latency": 245,
      "uptime": "99.8%"
    },
    {
      "id": "fashion-outlet",
      "name": "Fashion Outlet",
      "status": "unhealthy",
      "lastCheck": "2025-01-15T10:30:00Z",
      "error": "Connection timeout",
      "failedChecks": 3
    },
    {
      "id": "home-goods",
      "name": "Home & Garden",
      "status": "healthy",
      "lastCheck": "2025-01-15T10:30:00Z",
      "latency": 189,
      "uptime": "100%"
    }
  ]
}

Automatic Failover

When a store becomes unhealthy, MCIP automatically:

  1. Excludes it from search queries - No slow timeouts
  2. Continues health checks - Detects recovery
  3. Re-includes on recovery - Automatic healing
  4. Logs the event - For monitoring and alerts
// This happens automatically - no code needed!
// Unhealthy stores are filtered from the search pool
const healthyStores = stores.filter(s => s.status === 'healthy');
const results = await searchAcrossStores(healthyStores, query);

Part 5: Dynamic Updates

Hot Reload Configuration

Change store settings without restarting MCIP:

# Reload all store configurations
curl -X POST http://localhost:8080/admin/reload-config \
  -H "x-admin-api-key: your-admin-key"

# Reload specific store
curl -X POST http://localhost:8080/admin/reload-config \
  -H "x-admin-api-key: your-admin-key" \
  -d '{"storeId": "electronics-hub"}'

Enable/Disable Stores

Temporarily remove a store from searches (useful during maintenance):

# Disable store
curl -X PATCH http://localhost:8080/admin/stores/fashion-outlet \
  -H "x-admin-api-key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

# Re-enable store
curl -X PATCH http://localhost:8080/admin/stores/fashion-outlet \
  -H "x-admin-api-key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true}'

Runtime Priority Adjustment

Need to prioritize a store during a promotion? Adjust on the fly:

curl -X PATCH [http://localhost:8080/admin/stores/fashion-outlet](http://localhost:8080/admin/stores/fashion-outlet) \
  -H "x-admin-api-key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{"priority": 1, "weight": 1.5}'

Quick Reference

TaskCommand
List all storesGET /admin/stores
Check store healthGET /health/stores
Sync all productsPOST /admin/sync
Sync one storePOST /admin/sync with {"storeId": "..."}
Disable storePATCH /admin/stores/{id} with {"enabled": false}
Reload configPOST /admin/reload-config
Update credentialsPOST /admin/reload-config with credential reference

What's Next

Your stores are registered and ready! Here's where to go from here: