onX Documentation

Juniper Commerce Docs

Everything you need to understand the onX standard, build your adapter, integrate with UCP, and validate conformance.

Getting Started

The onX (Order Network eXchange) standard defines a common MCP (Model Context Protocol) interface for commerce fulfillment operations. Any AI platform can connect to any onX-compliant adapter using a single, consistent protocol.

Juniper Commerce is the reference app maintained by the Commerce Operations Foundation . Source: juniper-commerce on GitHub .

Path A — Docker (recommended)

From the repository root, run the interactive setup wizard. It writes a .env file, chooses Demo vs Full Install, data store (PostgreSQL or SQLite when not in Demo), optional AI keys, and optional MCP server profile. When it finishes, use the docker compose command it prints (it may add --profile flags for Postgres and/or the MCP server).

bash
npm run setup
docker compose up --build
# → http://localhost:3000 (adjust if PORT in .env differs)

Path B — Local development

Run the Next.js app directly for fast iteration. Copy the example env file, adjust APP_MODE, DATA_MODE, and keys as needed (defaults favor Demo + in-memory).

bash
npm install
cp .env.example .env.local
npm run dev
# → http://localhost:3000

Conformance

With the app running, open the built-in runner to execute the full suite against your instance.

💡 TipDemo mode uses an in-memory DataProvider with per-session isolation and TTL so visitors don't share data. Install (Full) mode turns on persistent storage: configure DATA_MODE=postgres or sqlite and the matching DATABASE_URL. In Install mode, when you include the MCP reference server in setup, it runs alongside Juniper via Docker Compose; Juniper calls it using ONX_MCP_SERVER_URL.

Architecture

Juniper v2 is a Next.js application that exposes REST and UCP endpoints, maps them to the same twelve onX operations, and powers the Playground with pluggable AI and data backends. The onX contract itself is implemented by adapters behind the MCP reference server; Juniper can call that server over HTTP in full install setups or fulfill operations through its own DataProvider abstraction.

  • DataProvider — Swappable persistence: memory (session-scoped stores), postgres, or sqlite, selected via DATA_MODE and environment.
  • LLM provider — Unified interface with concrete drivers for Anthropic, OpenAI, Google Gemini, and Ollama. The app picks a provider from which API keys or Ollama URL are set.
  • Two-mode architectureDemo (APP_MODE=demo): in-memory data, rate limits, no admin settings UI. Install / Full (APP_MODE=full): persistent data, full Playground, settings, and optional MCP server integration.

The 12 Operations

Adapters implement IFulfillmentAdapter and expose these MCP tools.

get-productsList product catalog
get-product-variantsList SKUs & options
get-inventoryStock levels by SKU/location
get-customersCustomer lookup
get-ordersOrder history & filtering
create-sales-orderPlace a new order
update-orderModify an existing order
cancel-orderCancel with reason
fulfill-orderShip with tracking
get-fulfillmentsFulfillment status
create-returnInitiate return/RMA
get-returnsReturn history

Stack overview

text
┌──────────────────────────────────────────────────────────────────────┐
│  Juniper Commerce (Next.js)                                          │
│  • Routes: storefront, REST APIs, UCP bridge, Playground, conformance│
│  • Demo mode: in-memory DataProvider, isolated per browser session   │
│  • Full / Install: Postgres or SQLite + settings + optional MCP URL  │
├──────────────────────────────────────────────────────────────────────┤
│  LLM layer (one active provider from env)                            │
│    Anthropic (Claude) │ OpenAI │ Google Gemini │ Ollama (local)      │
├──────────────────────────────────────────────────────────────────────┤
│  Commerce logic → 12 onX operations (tools / API handlers)           │
│  DataProvider: Memory │ PostgreSQL │ SQLite                          │
└──────────────────────────────────────────────────────────────────────┘
        │  ONX_MCP_SERVER_URL (optional, typical in Docker Compose)
        ▼
┌──────────────────────────────────────────────────────────────────────┐
│  MCP reference server (HTTP) — mock or custom IFulfillmentAdapter    │
│  Protocol: MCP tools map to the same 12 operations                   │
└──────────────────────────────────────────────────────────────────────┘
ℹ️ InfoApplication entry points for onX-shaped data and tools live under src/lib (data providers, LLM factory, onx-client.ts). In Demo mode, requests stay inside the app process; in Full Install with MCP enabled, Juniper delegates to the reference server defined by ONX_MCP_SERVER_URL.

Build Your Adapter

An adapter wraps your fulfillment system (Shopify, NetSuite, custom WMS, etc.) and implements the onX interface. Use the template from adapter-template/ in the Commerce Operations Foundation repositories as your starting point.

Step 1: Scaffold

bash
cp -r adapter-template my-adapter
cd my-adapter
npm install
# Edit src/adapter.ts

Step 2: Implement the interface

typescript
import type { IFulfillmentAdapter } from '@cof-org/mcp';

export class MyAdapter implements IFulfillmentAdapter {
  async getOrders(params) {
    // Fetch from your system
    const orders = await myAPI.listOrders(params);
    // Return in onX format
    return { items: orders.map(toOnXOrder), total: orders.length };
  }

  async createSalesOrder(input) {
    const order = await myAPI.createOrder(input);
    return toOnXOrder(order);
  }

  // ... implement all 12 operations
}

Step 3: Configure and test

bash
# Point the MCP server at your built adapter (see server docs for env vars)
ADAPTER_TYPE=local ADAPTER_PATH=./dist/adapter.js node server/dist/index.js

# With Juniper running, validate the HTTP surface from the web UI:
# http://localhost:3000/conformance

Step 4: Publish to npm

bash
npm publish --access public
# Consumers can then use:
# ADAPTER_TYPE=npm ADAPTER_PACKAGE=@myco/onx-adapter
💡 TipAll 12 operations have JSON Schema definitions in schemas/. The conformance runner in Juniper validates your deployment against these expectations from the UI.

UCP Integration

The Universal Commerce Protocol (UCP) lets AI platforms discover and consume your commerce capabilities via a standardized manifest. This app implements the full UCP bridge.

Discovery Manifest

Expose your capabilities at /.well-known/ucp:

json
{
  "version": "1.0",
  "name": "My Store",
  "baseUrl": "https://store.example.com",
  "capabilities": [
    {
      "id": "dev.ucp.shopping.catalog",
      "type": "catalog",
      "endpoint": "/api/ucp/catalog",
      "methods": ["GET", "POST"]
    },
    {
      "id": "dev.ucp.shopping.checkout",
      "type": "checkout",
      "endpoint": "/api/ucp/checkout",
      "methods": ["POST"]
    }
  ],
  "auth": {
    "type": "apiKey",
    "apiKeyHeader": "Authorization"
  }
}

Request/Response Flow

text
AI Platform → POST /.well-known/ucp discovery
AI Platform → GET /api/ucp/catalog?query=jacket
AI Platform → POST /api/ucp/checkout { items, customer, address }
              → translates to onX create-sales-order
              → returns { orderId, status, total }
AI Platform → GET /api/ucp/fulfillment?orderId=X
              → translates to onX get-fulfillments
              → returns { orderId, status, trackingNumbers }
ℹ️ InfoThis app uses API key auth for the demo. For production, implement OAuth 2.0 client credentials flow. The manifest documents the token URL and scopes.

Conformance Testing

The conformance runner validates that your Juniper (or proxied onX) HTTP surface meets the reference expectations. Run it from the web UI—no separate CLI package required.

Web UI

Open /conformance while the app is running. Start a run to execute all suites against the configured base URL (typically this app on localhost).

What's Tested

UCP Discovery (3 tests)Manifest exists, has required fields, capabilities array
Catalog API (4 tests)Endpoint reachable, response shape, items structure, search works
Checkout API (3 tests)Creates order, response has orderId, rejects invalid input
Fulfillment API (4 tests)Status lookup, response shape, 400 on missing, 404 on unknown
onX Bridge (3 tests)Products, orders, inventory endpoints all return 200