MCPInstall

commercevault-edd-commerce-orchestrator

MCP server for Easy Digital Downloads API integration enabling sales analytics, product management, and order orchestration

Installs
649
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/reason-machines/data-skills --skill commercevault-edd-commerce-orchestrator
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads commercevault-edd-commerce-orchestrator automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

CommerceVault EDD Commerce Orchestrator

Skill by ara.so — Data Skills collection.

CommerceVault (mcp-edd-analytics-vantage) is an MCP (Model Context Protocol) server that provides a unified interface for interacting with Easy Digital Downloads (EDD) WordPress e-commerce installations. It transforms raw EDD REST API responses into structured, queryable data for sales analytics, product catalog management, customer segmentation, and order lifecycle tracking.

The server implements hexagonal architecture with pluggable adapters, cryptographic payload verification, adaptive rate limiting, and built-in caching for high-throughput commerce operations.

Installation

Prerequisites

  • Node.js 18+ or Python 3.9+
  • Access to an Easy Digital Downloads WordPress installation
  • EDD REST API credentials (Consumer Key and Consumer Secret)

Install via npm

npm install -g mcp-edd-analytics-vantage

Install via Python

pip install mcp-edd-analytics-vantage

Clone from Source

git clone https://github.com/dhapat3927/mcp-edd-analytics-vantage.git
cd mcp-edd-analytics-vantage
npm install
# or
pip install -r requirements.txt

Configuration

Environment Variables

Create a .env file in your project root:

# Required - EDD API Credentials
EDD_SITE_URL=https://your-store.com
EDD_CONSUMER_KEY=ck_your_consumer_key_here
EDD_CONSUMER_SECRET=cs_your_consumer_secret_here

# Optional - Server Configuration
COMMERCEVAULT_PORT=3000
COMMERCEVAULT_CACHE_ENABLED=true
COMMERCEVAULT_CACHE_TTL=300
COMMERCEVAULT_RATE_LIMIT=100

# Optional - Security
COMMERCEVAULT_HMAC_SECRET=your_secret_key_for_payload_signing
COMMERCEVAULT_TLS_CERT_PATH=/path/to/cert.pem
COMMERCEVAULT_TLS_KEY_PATH=/path/to/key.pem

# Optional - Analytics
COMMERCEVAULT_METRICS_ENABLED=true
COMMERCEVAULT_RETENTION_DAYS=90

MCP Settings Configuration

Add to your MCP client configuration (e.g., Claude Desktop config):

{
  "mcpServers": {
    "commercevault": {
      "command": "npx",
      "args": ["mcp-edd-analytics-vantage"],
      "env": {
        "EDD_SITE_URL": "https://your-store.com",
        "EDD_CONSUMER_KEY": "${EDD_CONSUMER_KEY}",
        "EDD_CONSUMER_SECRET": "${EDD_CONSUMER_SECRET}"
      }
    }
  }
}

Core API Operations

Product Management

List All Products

// Node.js / JavaScript
import { CommerceVault } from 'mcp-edd-analytics-vantage';

const vault = new CommerceVault({
  siteUrl: process.env.EDD_SITE_URL,
  consumerKey: process.env.EDD_CONSUMER_KEY,
  consumerSecret: process.env.EDD_CONSUMER_SECRET
});

// Retrieve products with filtering
const products = await vault.products.list({
  status: 'publish',
  per_page: 50,
  orderby: 'date',
  order: 'desc'
});

console.log(`Found ${products.length} products`);
products.forEach(product => {
  console.log(`${product.id}: ${product.name} - $${product.price}`);
});
# Python
from commercevault import CommerceVault
import os

vault = CommerceVault(
    site_url=os.getenv('EDD_SITE_URL'),
    consumer_key=os.getenv('EDD_CONSUMER_KEY'),
    consumer_secret=os.getenv('EDD_CONSUMER_SECRET')
)

# Retrieve products with filtering
products = vault.products.list(
    status='publish',
    per_page=50,
    orderby='date',
    order='desc'
)

print(f"Found {len(products)} products")
for product in products:
    print(f"{product.id}: {product.name} - ${product.price}")

Get Single Product Details

const productId = 123;
const product = await vault.products.get(productId);

console.log({
  id: product.id,
  name: product.name,
  price: product.price,
  downloads: product.sales_count,
  earnings: product.earnings,
  files: product.files.map(f => f.name)
});

Create or Update Product

const newProduct = await vault.products.create({
  name: 'Premium WordPress Plugin',
  status: 'publish',
  type: 'download',
  price: 49.99,
  categories: ['wordpress', 'plugins'],
  files: [
    {
      name: 'Plugin ZIP',
      file: 'https://cdn.example.com/plugin.zip'
    }
  ]
});

console.log(`Created product ID: ${newProduct.id}`);

Order Management

Retrieve Orders with Filters

// Get orders from the last 30 days
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

const recentOrders = await vault.orders.list({
  status: 'complete',
  date_created_after: thirtyDaysAgo.toISOString(),
  per_page: 100
});

// Calculate revenue
const totalRevenue = recentOrders.reduce((sum, order) => {
  return sum + parseFloat(order.total);
}, 0);

console.log(`Total revenue (30 days): $${totalRevenue.toFixed(2)}`);

Get Order Details

const orderId = 456;
const order = await vault.orders.get(orderId);

console.log({
  order_id: order.id,
  customer_email: order.billing.email,
  total: order.total,
  status: order.status,
  items: order.line_items.map(item => ({
    product: item.name,
    quantity: item.quantity,
    price: item.price
  }))
});

Update Order Status

await vault.orders.update(orderId, {
  status: 'refunded',
  customer_note: 'Refund processed per customer request'
});

Customer Management

List Customers with Segmentation

const customers = await vault.customers.list({
  orderby: 'registered_date',
  order: 'desc',
  per_page: 50
});

// Segment by purchase count
const segments = {
  new: customers.filter(c => c.orders_count === 1),
  repeat: customers.filter(c => c.orders_count > 1 && c.orders_count <= 5),
  vip: customers.filter(c => c.orders_count > 5)
};

console.log('Customer Segments:');
console.log(`New: ${segments.new.length}`);
console.log(`Repeat: ${segments.repeat.length}`);
console.log(`VIP: ${segments.vip.length}`);

Calculate Customer Lifetime Value

customers = vault.customers.list(per_page=100)

for customer in customers:
    ltv = sum(float(order.total) for order in customer.orders)
    avg_order_value = ltv / len(customer.orders) if customer.orders else 0
    
    print(f"{customer.email}:")
    print(f"  LTV: ${ltv:.2f}")
    print(f"  AOV: ${avg_order_value:.2f}")
    print(f"  Orders: {len(customer.orders)}")

Analytics & Reporting

Revenue Analytics

const analytics = await vault.analytics.revenue({
  start_date: '2026-01-01',
  end_date: '2026-06-30',
  interval: 'month'
});

analytics.periods.forEach(period => {
  console.log(`${period.month}: $${period.gross_revenue} (${period.order_count} orders)`);
});

console.log('\nSummary:');
console.log(`Total Revenue: $${analytics.total_revenue}`);
console.log(`Average Order Value: $${analytics.average_order_value}`);
console.log(`Total Orders: ${analytics.total_orders}`);

Product Performance Report

const productAnalytics = await vault.analytics.products({
  start_date: '2026-01-01',
  end_date: '2026-06-30',
  orderby: 'revenue',
  order: 'desc',
  limit: 10
});

console.log('Top 10 Products by Revenue:');
productAnalytics.forEach((product, index) => {
  console.log(`${index + 1}. ${product.name}`);
  console.log(`   Revenue: $${product.revenue}`);
  console.log(`   Sales: ${product.sales_count}`);
  console.log(`   Avg Price: $${product.average_price}`);
});

Customer Cohort Analysis

cohort_data = vault.analytics.cohorts({
    'cohort_type': 'month',
    'start_date': '2026-01-01',
    'metrics': ['retention', 'revenue']
})

for cohort in cohort_data:
    print(f"Cohort: {cohort.period}")
    print(f"  Initial Customers: {cohort.initial_size}")
    print(f"  Month 1 Retention: {cohort.retention_month_1}%")
    print(f"  Month 3 Retention: {cohort.retention_month_3}%")
    print(f"  Total Revenue: ${cohort.total_revenue:.2f}")

License Management

Generate License Keys

const license = await vault.licenses.create({
  product_id: 123,
  customer_id: 456,
  license_length: 'lifetime',
  activation_limit: 3
});

console.log(`License Key: ${license.key}`);
console.log(`Activations Remaining: ${license.activation_limit}`);

Validate and Activate License

const validation = await vault.licenses.validate({
  license_key: 'XXXX-XXXX-XXXX-XXXX',
  product_id: 123,
  url: 'https://customer-site.com'
});

if (validation.valid) {
  const activation = await vault.licenses.activate({
    license_key: validation.key,
    url: 'https://customer-site.com'
  });
  
  console.log(`License activated. ${activation.activations_left} activations remaining.`);
} else {
  console.log(`Invalid license: ${validation.error}`);
}

Common Patterns

Delta Synchronization

Efficiently sync only changed records:

// Store last sync timestamp
let lastSync = await vault.cache.get('last_product_sync');
if (!lastSync) {
  lastSync = new Date('2026-01-01').toISOString();
}

// Fetch only products modified since last sync
const updatedProducts = await vault.products.list({
  modified_after: lastSync,
  per_page: 100
});

console.log(`${updatedProducts.length} products updated since ${lastSync}`);

// Update local database/cache
for (const product of updatedProducts) {
  await localDb.products.upsert(product);
}

// Update sync timestamp
await vault.cache.set('last_product_sync', new Date().toISOString());

Webhook Relay Setup

Configure webhook endpoints to receive real-time events:

// Register webhook handler
vault.webhooks.register({
  topic: 'order.completed',
  delivery_url: 'https://your-app.com/webhooks/edd/order-completed',
  secret: process.env.WEBHOOK_SECRET
});

// Webhook handler endpoint
app.post('/webhooks/edd/order-completed', async (req, res) => {
  // Verify webhook signature
  const isValid = vault.webhooks.verify(
    req.body,
    req.headers['x-edd-signature'],
    process.env.WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }
  
  const order = req.body.data;
  
  // Process order (send confirmation email, update inventory, etc.)
  await processNewOrder(order);
  
  res.status(200).send('OK');
});

Batch Operations with Rate Limiting

const productIds = [101, 102, 103, 104, 105, /* ... 500 more ... */];

// Process in batches to respect rate limits
const batchSize = 10;
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

for (let i = 0; i < productIds.length; i += batchSize) {
  const batch = productIds.slice(i, i + batchSize);
  
  const products = await Promise.all(
    batch.map(id => vault.products.get(id))
  );
  
  // Process batch
  await processBatch(products);
  
  // Respect rate limits
  if (i + batchSize < productIds.length) {
    await delay(1000); // 1 second between batches
  }
}

Error Handling and Retry Logic

from commercevault.exceptions import RateLimitError, APIError
import time

def fetch_with_retry(func, max_retries=3, backoff=2):
    for attempt in range(max_retries):
        try:
            return func()
        except RateLimitError as e:
            wait_time = backoff ** attempt
            print(f"Rate limited. Waiting {wait_time}s before retry {attempt + 1}/{max_retries}")
            time.sleep(wait_time)
        except APIError as e:
            if e.status_code >= 500:  # Server error, retry
                print(f"Server error. Retrying {attempt + 1}/{max_retries}")
                time.sleep(backoff ** attempt)
            else:  # Client error, don't retry
                raise
    
    raise Exception(f"Failed after {max_retries} retries")

# Usage
orders = fetch_with_retry(lambda: vault.orders.list(per_page=100))

CLI Commands

If installed globally, CommerceVault provides CLI tools:

# Start MCP server
commercevault serve --port 3000

# Test connection
commercevault test-connection

# Export analytics report
commercevault export-analytics \
  --start-date 2026-01-01 \
  --end-date 2026-06-30 \
  --format csv \
  --output revenue-report.csv

# Sync products to local database
commercevault sync products \
  --incremental \
  --db-connection postgres://localhost/commerce

# Generate license keys in bulk
commercevault licenses generate \
  --product-id 123 \
  --count 100 \
  --output licenses.json

Troubleshooting

Authentication Errors

Problem: 401 Unauthorized errors when calling API

Solution: Verify credentials and URL format:

// Ensure URL does NOT have trailing slash
const vault = new CommerceVault({
  siteUrl: 'https://store.com',  // ✓ Correct
  // siteUrl: 'https://store.com/',  // ✗ Wrong
  consumerKey: process.env.EDD_CONSUMER_KEY,
  consumerSecret: process.env.EDD_CONSUMER_SECRET
});

// Test authentication
try {
  await vault.auth.verify();
  console.log('Authentication successful');
} catch (error) {
  console.error('Auth failed:', error.message);
}

Rate Limit Exceeded

Problem: 429 Too Many Requests errors

Solution: Enable adaptive rate limiting:

const vault = new CommerceVault({
  siteUrl: process.env.EDD_SITE_URL,
  consumerKey: process.env.EDD_CONSUMER_KEY,
  consumerSecret: process.env.EDD_CONSUMER_SECRET,
  rateLimiting: {
    enabled: true,
    maxRequestsPerSecond: 2,
    retryOnLimit: true,
    maxRetries: 3
  }
});

Cache Invalidation Issues

Problem: Stale data returned from API

Solution: Force cache refresh or disable caching:

// Force fresh data
const products = await vault.products.list({
  per_page: 50,
  _bypass_cache: true
});

// Or clear cache manually
await vault.cache.clear('products:*');

SSL Certificate Errors

Problem: UNABLE_TO_VERIFY_LEAF_SIGNATURE on self-signed certs

Solution: Configure TLS options (development only):

const vault = new CommerceVault({
  siteUrl: process.env.EDD_SITE_URL,
  consumerKey: process.env.EDD_CONSUMER_KEY,
  consumerSecret: process.env.EDD_CONSUMER_SECRET,
  tls: {
    rejectUnauthorized: false  // Only for development!
  }
});

Data Formatting Issues

Problem: Dates or currencies displaying incorrectly

Solution: Configure locale settings:

const vault = new CommerceVault({
  siteUrl: process.env.EDD_SITE_URL,
  consumerKey: process.env.EDD_CONSUMER_KEY,
  consumerSecret: process.env.EDD_CONSUMER_SECRET,
  locale: {
    language: 'en-US',
    currency: 'USD',
    dateFormat: 'YYYY-MM-DD',
    timezone: 'America/New_York'
  }
});

Best Practices

  1. Always use environment variables for credentials — never hardcode API keys
  2. Enable caching for read-heavy operations (product catalogs, customer lists)
  3. Implement webhook handlers for real-time order processing instead of polling
  4. Use delta sync when synchronizing large datasets to minimize API quota usage
  5. Log all transactions with cryptographic fingerprints for audit compliance
  6. Set up monitoring for API latency and error rates using the built-in metrics endpoint

FAQ

What does the commercevault-edd-commerce-orchestrator skill do?

MCP server for Easy Digital Downloads API integration enabling sales analytics, product management, and order orchestration

How do I install commercevault-edd-commerce-orchestrator?

Run npx skills add https://github.com/reason-machines/data-skills --skill commercevault-edd-commerce-orchestrator in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/commercevault-edd-commerce-orchestrator/ (personal) or .claude/skills/commercevault-edd-commerce-orchestrator/ (project).

Which AI agents can use commercevault-edd-commerce-orchestrator?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is commercevault-edd-commerce-orchestrator safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains commercevault-edd-commerce-orchestrator?

It is published by reason-machines in reason-machines/data-skills. It has 649 recorded installs.

More from reason-machines/data-skills

View all →

apache-airflow-orchestration

reason-machines/data-skills

Expert knowledge of Apache Airflow for building, scheduling, and monitoring data pipelines and workflows

DevOps & Cloud2.4K installs

datatalks-data-engineering-zoomcamp

reason-machines/data-skills

Free 9-week data engineering course covering Docker, Terraform, Kestra, BigQuery, dbt, Spark, and Kafka with hands-on projects

Data & Databases2.4K installs

llm-public-opinion-analytics-assistant

reason-machines/data-skills

Multi-platform hot search crawler and LLM-powered public opinion analysis system with clustering, sentiment analysis, and multi-channel push notifications

AI & Agents2.4K installs

roblox-mm2-analytics-toolkit

reason-machines/data-skills

Analytics and inventory management toolkit for Roblox Murder Mystery 2 gameplay optimization

Data & Databases2.4K installs

mm2-analytics-roblox-tracker

reason-machines/data-skills

Analyze Murder Mystery 2 gameplay data, track inventory, and optimize strategy using this Roblox analytics toolkit

Data & Databases2.4K installs

mm2-roblox-analytics-toolkit

reason-machines/data-skills

Murder Mystery 2 gameplay analytics, inventory tracking, and strategy optimization toolkit for Roblox

Data & Databases2.4K installs

Popular backend & apis skills

View category →

find-skills

vercel-labs/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

OfficialBackend & APIs4.1M installs

entra-app-registration

microsoft/azure-skills

Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.

OfficialBackend & APIs566.7K installs

This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).

Backend & APIs514.8K installs

embedded-captions

heygen-com/hyperframes

Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.

Backend & APIs453.3K installs

entra-agent-id

microsoft/azure-skills

Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).

OfficialBackend & APIs336.6K installs

neon

neondatabase/agent-skills

Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.

Backend & APIs237.1K installs