Skip to content

feat(connectors/shopify): first-class Shopify→USD primitives + MCP/HTTP-SSE + Temporal#15

Merged
ninan-versioning merged 1 commit into
mainfrom
jared-shoploop/shopify-connector-mcp
Jun 26, 2026
Merged

feat(connectors/shopify): first-class Shopify→USD primitives + MCP/HTTP-SSE + Temporal#15
ninan-versioning merged 1 commit into
mainfrom
jared-shoploop/shopify-connector-mcp

Conversation

@ninan-versioning

Copy link
Copy Markdown
Owner

First-class Shopify → product_twin.usda → Scene Composer connector at
connectors/shopify/ (@shoploop/connector-shopify). MCP-shaped, modeled on
daslabhq/openusd-mcp + Griptape Nodes' agent-callable USD pattern — not a thin REST
wrapper. CPU-only; render stays in open-imagine.

The 4 primitives (one internal core, no duplication)

All four are importable from @shoploop/connector-shopify, callable from MCP, and triggerable
from webhooks — over the same core (client.ts Admin GraphQL 2025-07 + usd/* emit/inspect/manipulate).

  1. Catalog ingest (ingestCatalog / shoploop-shopify ingest) — paginated Admin GraphQL →
    one <handle>.usda per product + _manifest.json (shopify_id ↔ usda_path). Shopify options →
    USD variant sets; real GLB/USDZ from Model3d media when present, else placeholder def Mesh;
    commerce/brand schema attrs (commerce:price|sku|inventory|vendor, brand:tags, brand:rules_ref).
  2. MCP server (shoploop-shopify mcp) — Express + HTTP/SSE on :8787 (/sse, /messages),
    bearer auth (SHOPLOOP_MCP_TOKEN), CORS allowlist. 7 tools: list_products, get_product,
    get_variants, get_metafields, update_metafield, inspect_product_twin (prim tree + variant
    sets + LLM text summary), manipulate_variant_set (agent-driven stage edits).
  3. Scene composition (composeScene) — enforces Kinfolk brand rules at the USD layer; emits a
    composed stage sublayering [brand_rules, product_twin, scene_preset]. Does not render.
  4. Webhook → Temporal (POST /webhooks/shopify + shoploop-shopify worker) — HMAC-verified
    (SHOPIFY_WEBHOOK_SECRET); 4 workflows: ReingestProductWorkflow, RecomposeCreativePackWorkflow,
    PurgeProductTwinWorkflow, UpdateCommerceAttrWorkflow. Idempotent workflow id
    shopify:<shop>:<topic>:<productId>:<updated_at> (REJECT_DUPLICATE).

Contracts (referenced, not vendored)

// CONTRACT: pointers to open-imagine/contracts/product_twin.v1.json (emitted .usda validates
against it) and open-imagine/contracts/render_job.v1.json (render-job body POSTed to
OPEN_IMAGINE_ROUTER_URL).

Cost footprint (decision gate #5)

CPU-only. ~$13/mo at Varitea dogfood scale (~30 SKUs, ~100 webhook events/day):
1× t4g.small co-locating MCP + worker ≈ $12, Temporal Cloud dev tier $0, S3 for .usda (~50 MB) <$1.
At 100 brands ≈ $60/mo (Fargate + Temporal starter). No GPU here — that cost lives in open-imagine.

Varitea dogfood acceptance checklist

  • One .usda per product with variant sets matching Shopify options (variantSet "size"
    _50g/_100g/_250g) — golden in test/fixtures/varitea_product_twin.usda.
  • Emitted stage shaped to validate against the open-imagine product_twin.v1 contract.
  • MCP inspect_product_twin returns a prim tree + text summary readable by Claude/Cursor.
  • products/update webhook → ReingestProductWorkflow (+ RecomposeCreativePackWorkflow),
    idempotent id; HMAC-verified.
  • Ingest produces byte-identical USDA via CLI and via Temporal activity (modulo
    commerce:generated_at) — asserted in tests.

Testing

pnpm test20 passing across 3 files:

  • primitives.test.ts — ingest matches golden modulo timestamp; options→variant sets; placeholder
    vs real mesh; add/rename/remove variant; composeScene sublayers + Kinfolk rules.
  • mcp.test.ts — in-process MCP server (linked transport), all 7 tools, shape assertions.
  • webhook.test.ts — HMAC verify (valid/tampered/wrong-secret/empty), idempotent id, signed POST
    fans out to the mapped workflows, invalid signature → 401 starts nothing.

pnpm typecheck and pnpm build clean.

Decision gate

  1. Varitea dogfood critical path? Yes — this is the catalog→USD left half of the loop.
  2. Deepens moat? Yes — USD scene graph + brand-constraint enforcement before pixels exist.
  3. Cheaper than API? N/A (no model calls).
  4. Ships ≤2 weeks solo? Yes.
  5. Monthly cost? ~$13/mo dogfood (above).

Spec excerpts (/home/user/workspace/shopify-connector-spec.md)

Positioning: Grip-from-below. First-class Shopify → product_twin.usda → Scene Composer
primitives. Not a thin REST wrapper.

Idempotency: workflow id = shopify:<shop>:<topic>:<productId>:<updated_at>. Temporal de-dupes.

Moat anchor: brand constraint enforcement happens here, at the scene graph — before any pixels exist.

Tools mirror daslabhq/openusd-mcp shape, commerce-typed: list_products · get_product · get_variants ·
get_metafields · update_metafield · inspect_product_twin · manipulate_variant_set.

Cost — Total: ~$13/mo at dogfood scale. At 100 brands: ~$60/mo (Fargate + Temporal starter).

Boundaries respected

No render/image code (→ open-imagine), no Polaris/Remix embed app (→ shoploop-shopify), no
ad-buying (→ shoploop-growth). shoploop-core/shoploop-shopify untouched. AWS-only path; no Vercel.

🤖 Generated with Claude Code

…TP-SSE + Temporal

Add @shoploop/connector-shopify: Shopify catalog → product_twin.usda primitives
modeled on daslabhq/openusd-mcp. Four primitives over a single internal core
(client.ts + usd/*): catalog ingest, MCP read/inspect/manipulate (7 tools over
HTTP/SSE), brand-constrained scene composition, and webhook→Temporal (4 workflows,
idempotent ids). CPU-only; render stays in open-imagine (contracts referenced, not
vendored). 20 tests green (golden USDA, in-proc MCP, webhook HMAC).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ninan-versioning
ninan-versioning force-pushed the jared-shoploop/shopify-connector-mcp branch from 758d4a6 to 34ab98b Compare June 26, 2026 05:58
@ninan-versioning
ninan-versioning merged commit 7384102 into main Jun 26, 2026
1 check passed
@ninan-versioning
ninan-versioning deleted the jared-shoploop/shopify-connector-mcp branch June 26, 2026 05:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant