Connect Store
store_connectAdd, sync, or list Shopify and WooCommerce stores. Connect new stores to sync products, orders, and customers; refresh cached data; or view all connected stores with sync counts.
Instructions
Manage Shopify or WooCommerce store connections. action="connect" adds a new store and performs an initial sync of products, orders, and customers; action="sync" refreshes cached data for an existing store; action="list" returns all connected stores with their sync counts. Returns a JSON payload with store metadata (id, name, platform, url, counts, last_sync) — credentials are never returned.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | connect = add new store, sync = refresh existing store, list = show all stores | |
| name | No | Human-readable store name (required for connect, e.g. "My Shop") | |
| platform | No | "shopify" or "woocommerce" (required for connect) | |
| url | No | Store base URL starting with https:// (required for connect, e.g. "https://myshop.myshopify.com") | |
| api_key | No | Platform API access token (required for connect) | |
| api_secret | No | Platform API secret — REQUIRED for woocommerce, ignored for shopify | |
| store_id | No | Existing store UUID (required for sync) |
Implementation Reference
- src/index.ts:37-106 (registration)Registration of the 'store_connect' tool on the MCP server, including the input schema (z.object with action, name, platform, url, api_key, api_secret, store_id) and the handler that dispatches to connectStore (action='connect'), syncStore (action='sync'), or lists stores (action='list').
// ── Tool: store_connect ─────────────────────────────────────────── server.registerTool( 'store_connect', { title: 'Connect Store', description: 'Manage Shopify or WooCommerce store connections. action="connect" adds a new store and performs an initial sync of products, orders, and customers; action="sync" refreshes cached data for an existing store; action="list" returns all connected stores with their sync counts. Returns a JSON payload with store metadata (id, name, platform, url, counts, last_sync) — credentials are never returned.', inputSchema: z.object({ action: z.enum(['connect', 'sync', 'list']).describe('connect = add new store, sync = refresh existing store, list = show all stores'), name: z.string().min(1).optional().describe('Human-readable store name (required for connect, e.g. "My Shop")'), platform: PlatformSchema.optional().describe('"shopify" or "woocommerce" (required for connect)'), url: z.string().url().optional().describe('Store base URL starting with https:// (required for connect, e.g. "https://myshop.myshopify.com")'), api_key: z.string().min(1).optional().describe('Platform API access token (required for connect)'), api_secret: z.string().min(1).optional().describe('Platform API secret — REQUIRED for woocommerce, ignored for shopify'), store_id: z.string().uuid().optional().describe('Existing store UUID (required for sync)'), }), annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, }, async ({ action, name, platform, url, api_key, api_secret, store_id }) => { try { if (action === 'list') { const stores = await storage.getStores(); if (stores.length === 0) { return { content: [{ type: 'text' as const, text: 'No stores are connected yet. Use action="connect" with name, platform, url, and api_key to add one.' }], }; } return { content: [{ type: 'text' as const, text: JSON.stringify({ total: stores.length, stores: stores.map((s) => ({ id: s.id, name: s.name, platform: s.platform, url: s.url, products: s.product_count, orders: s.order_count, customers: s.customer_count, last_sync: s.last_sync_at, })), }, null, 2) }], }; } if (action === 'sync') { if (!store_id) { return { content: [{ type: 'text' as const, text: 'store_id is required for action="sync". Use action="list" to find connected store IDs.' }], isError: true }; } const result = await syncStore(store_id); return { content: [{ type: 'text' as const, text: `Store synced successfully — ${result.products} products, ${result.orders} orders, ${result.customers} customers refreshed.` }] }; } // connect const missing: string[] = []; if (!name) missing.push('name'); if (!platform) missing.push('platform'); if (!url) missing.push('url'); if (!api_key) missing.push('api_key'); if (missing.length > 0) { return { content: [{ type: 'text' as const, text: `Missing required field(s) for connect: ${missing.join(', ')}. Required: name, platform, url, api_key. WooCommerce also needs api_secret.` }], isError: true }; } if (platform === 'woocommerce' && !api_secret) { return { content: [{ type: 'text' as const, text: 'api_secret is required when platform="woocommerce" (WooCommerce REST API uses consumer_key + consumer_secret).' }], isError: true }; } const result = await connectStore({ name: name!, platform: platform!, url: url!, api_key: api_key!, api_secret }); return { content: [{ type: 'text' as const, text: JSON.stringify({ message: `Store "${result.store.name}" connected successfully.`, store_id: result.store.id, synced: result.synced, next_steps: 'Use inventory_status, customers_segment, or report_daily with this store_id to start analyzing.', }, null, 2) }], }; } catch (e) { return handleToolError(e); } } ); - src/tools/connect.ts:8-70 (handler)The core handler function connectStore() that validates for duplicates, tests the platform connection (Shopify or WooCommerce), fetches initial data (products, orders, customers), stores data, and returns the store metadata (with credentials redacted).
export async function connectStore(input: StoreConnectInput): Promise<{ store: Omit<StoreConfig, 'api_key' | 'api_secret'>; synced: { products: number; orders: number; customers: number } }> { // Check for duplicate const existing = await storage.getStoreByUrl(input.url); if (existing) throw new DuplicateError('store URL', input.url); // Test connection if (input.platform === 'shopify') { await testShopifyConnection(input.url, input.api_key); } else { if (!input.api_secret) throw new PlatformError('WooCommerce', 'api_secret is required for WooCommerce'); await testWooConnection(input.url, input.api_key, input.api_secret); } const storeId = uuidv4(); const now = new Date().toISOString(); // Fetch initial data let products, orders, customers; if (input.platform === 'shopify') { [products, orders, customers] = await Promise.all([ fetchShopifyProducts(storeId, input.url, input.api_key), fetchShopifyOrders(storeId, input.url, input.api_key), fetchShopifyCustomers(storeId, input.url, input.api_key), ]); } else { [products, orders, customers] = await Promise.all([ fetchWooProducts(storeId, input.url, input.api_key, input.api_secret!), fetchWooOrders(storeId, input.url, input.api_key, input.api_secret!), fetchWooCustomers(storeId, input.url, input.api_key, input.api_secret!), ]); } // Store data await Promise.all([ storage.upsertProducts(products), storage.upsertOrders(orders), storage.upsertCustomers(customers), ]); const store: StoreConfig = { id: storeId, name: input.name, platform: input.platform, url: input.url, api_key: input.api_key, api_secret: input.api_secret, connected_at: now, last_sync_at: now, product_count: products.length, order_count: orders.length, customer_count: customers.length, }; await storage.addStore(store); // Redact credentials from response const { api_key: _ak, api_secret: _as, ...safeStore } = store; return { store: safeStore, synced: { products: products.length, orders: orders.length, customers: customers.length }, }; } - src/models/store.ts:22-29 (schema)StoreConnectInputSchema — Zod schema defining the input shape for store_connect: name, platform, url, api_key, and optional api_secret.
export const StoreConnectInputSchema = z.object({ name: z.string().min(1).describe('Store display name'), platform: PlatformSchema.describe('E-commerce platform'), url: z.string().url().describe('Store URL (e.g. https://your-store.myshopify.com)'), api_key: z.string().min(1).describe('API access token or consumer key'), api_secret: z.string().optional().describe('API secret (required for WooCommerce)'), }); export type StoreConnectInput = z.infer<typeof StoreConnectInputSchema>; - src/tools/connect.ts:72-106 (helper)syncStore helper function used by store_connect when action='sync' — refreshes data for an existing store by fetching products, orders, and customers again.
export async function syncStore(storeId: string): Promise<{ products: number; orders: number; customers: number }> { const store = await storage.getStoreById(storeId); if (!store) throw new NotFoundError('Store', storeId); let products, orders, customers; if (store.platform === 'shopify') { [products, orders, customers] = await Promise.all([ fetchShopifyProducts(store.id, store.url, store.api_key), fetchShopifyOrders(store.id, store.url, store.api_key), fetchShopifyCustomers(store.id, store.url, store.api_key), ]); } else { if (!store.api_secret) throw new PlatformError('WooCommerce', 'Missing API secret'); [products, orders, customers] = await Promise.all([ fetchWooProducts(store.id, store.url, store.api_key, store.api_secret), fetchWooOrders(store.id, store.url, store.api_key, store.api_secret), fetchWooCustomers(store.id, store.url, store.api_key, store.api_secret), ]); } await Promise.all([ storage.upsertProducts(products), storage.upsertOrders(orders), storage.upsertCustomers(customers), ]); await storage.updateStore(storeId, { last_sync_at: new Date().toISOString(), product_count: products.length, order_count: orders.length, customer_count: customers.length, }); return { products: products.length, orders: orders.length, customers: customers.length }; }