commercevault-edd-mcp-server

v2026.09.25

Easy Digital Downloads MCP server for sales analytics, order management, and product data via natural language

GitHub
Install command
npx skhub add reason-machines/commercevault-edd-mcp-server
Markdown
SKILL.md

CommerceVault EDD MCP Server

Skill by ara.so — MCP Skills collection.

CommerceVault (mcp-edd-analytics-vantage) is an MCP (Model Context Protocol) server that provides natural language access to Easy Digital Downloads (EDD) WordPress e-commerce data. It enables AI assistants to query sales analytics, manage products, retrieve customer orders, and perform revenue analysis through a structured API interface.

What It Does

This MCP server acts as a middleware layer between AI coding agents and Easy Digital Downloads REST API, providing:

  • Sales Analytics: Revenue reports, GMV, AOV, cohort analysis
  • Product Management: Catalog synchronization, pricing, digital downloads
  • Order Operations: Lifecycle management, fulfillment tracking, refunds
  • Customer Data: Profiles, purchase history, LTV calculations
  • License Management: Key generation, activation tracking, entitlements
  • Webhook Relay: Event forwarding with transformation and enrichment

Installation

Prerequisites

  • Node.js 18+ or Python 3.9+
  • Easy Digital Downloads installed on WordPress site
  • EDD REST API credentials (API key and token)
  • MCP-compatible client (Claude Desktop, Cursor, etc.)

Install as MCP Server

  1. Clone or download the repository:
git clone https://github.com/dhapat3927/mcp-edd-analytics-vantage.git
cd mcp-edd-analytics-vantage
  1. Install dependencies:
npm install
# or
pip install -r requirements.txt
  1. Configure MCP client settings (e.g., Claude Desktop claude_desktop_config.json):
{
  "mcpServers": {
    "commercevault-edd": {
      "command": "node",
      "args": ["/path/to/mcp-edd-analytics-vantage/server.js"],
      "env": {
        "EDD_API_URL": "https://yoursite.com/wp-json/edd/v2",
        "EDD_API_KEY": "${EDD_API_KEY}",
        "EDD_API_TOKEN": "${EDD_API_TOKEN}",
        "CACHE_ENABLED": "true",
        "CACHE_TTL": "300"
      }
    }
  }
}

For Python implementation:

{
  "mcpServers": {
    "commercevault-edd": {
      "command": "python",
      "args": ["/path/to/mcp-edd-analytics-vantage/server.py"],
      "env": {
        "EDD_API_URL": "https://yoursite.com/wp-json/edd/v2",
        "EDD_API_KEY": "${EDD_API_KEY}",
        "EDD_API_TOKEN": "${EDD_API_TOKEN}"
      }
    }
  }
}

Configuration

Environment Variables

VariableRequiredDescriptionDefault
EDD_API_URLYesFull URL to EDD REST API endpoint-
EDD_API_KEYYesEDD API key from WordPress admin-
EDD_API_TOKENYesEDD API token for authentication-
CACHE_ENABLEDNoEnable Redis-backed response cachingfalse
CACHE_TTLNoCache time-to-live in seconds300
REDIS_URLNoRedis connection stringredis://localhost:6379
RATE_LIMIT_MAXNoMax requests per minute60
LOG_LEVELNoLogging verbosity (debug/info/warn/error)info
HMAC_SECRETNoShared secret for payload signatures-

Getting EDD API Credentials

  1. Log into WordPress admin
  2. Navigate to Downloads → Settings → API
  3. Click Generate API Keys
  4. Copy the Public Key (API_KEY) and Token (API_TOKEN)
  5. Set appropriate permissions for the key (read/write)

Key API Tools

The MCP server exposes these tools for AI agents:

Products

edd_get_products - Retrieve product catalog

// Parameters
{
  "category": "software",      // Filter by category slug
  "tag": "featured",          // Filter by tag
  "search": "premium",        // Search product titles
  "per_page": 20,            // Results per page (default: 10)
  "page": 1                  // Page number
}

edd_get_product - Get single product details

{
  "product_id": 123          // Product ID
}

Orders

edd_get_orders - Retrieve order history

{
  "status": "complete",      // Order status filter
  "customer": 456,          // Customer ID
  "start_date": "2026-01-01",
  "end_date": "2026-06-30",
  "per_page": 50
}

edd_get_order - Get single order details

{
  "order_id": 789
}

edd_create_order - Create new order

{
  "customer_id": 456,
  "products": [
    {
      "product_id": 123,
      "price": 49.99,
      "quantity": 1
    }
  ],
  "status": "pending",
  "gateway": "stripe"
}

Customers

edd_get_customers - Retrieve customer list

{
  "email": "user@example.com",
  "order_by": "purchase_count",
  "order": "desc"
}

edd_get_customer_stats - Get customer analytics

{
  "customer_id": 456
}
// Returns: total_spent, purchase_count, avg_order_value, lifetime_value

Analytics

edd_get_sales_stats - Revenue and sales metrics

{
  "start_date": "2026-01-01",
  "end_date": "2026-06-30",
  "interval": "day",         // day, week, month
  "product_id": 123         // Optional: filter by product
}
// Returns: revenue, orders, avg_order_value, gross_merchandise_value

edd_get_top_products - Best-selling products report

{
  "period": "30days",        // 7days, 30days, 90days, year
  "limit": 10
}

Licenses

edd_get_licenses - Retrieve license keys

{
  "product_id": 123,
  "status": "active",        // active, inactive, expired
  "customer_id": 456
}

edd_activate_license - Activate license key

{
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "site_url": "https://customer-site.com",
  "item_id": 123
}

Code Examples

Example 1: Fetch Monthly Revenue Report

// server.js implementation snippet
async function getSalesStats(params) {
  const { start_date, end_date, interval = 'day' } = params;
  
  const response = await fetch(
    `${process.env.EDD_API_URL}/reports/sales?` +
    `start_date=${start_date}&end_date=${end_date}&interval=${interval}`,
    {
      headers: {
        'Authorization': `Basic ${Buffer.from(
          `${process.env.EDD_API_KEY}:${process.env.EDD_API_TOKEN}`
        ).toString('base64')}`,
        'Content-Type': 'application/json'
      }
    }
  );
  
  if (!response.ok) {
    throw new Error(`EDD API error: ${response.statusText}`);
  }
  
  const data = await response.json();
  
  return {
    revenue: data.totals.revenue,
    orders: data.totals.orders,
    avg_order_value: data.totals.revenue / data.totals.orders,
    interval_data: data.data
  };
}

Example 2: Create Order with License

# server.py implementation snippet
import requests
import os
from base64 import b64encode

def create_order_with_license(customer_id, product_id, price):
    auth_string = f"{os.getenv('EDD_API_KEY')}:{os.getenv('EDD_API_TOKEN')}"
    auth_header = b64encode(auth_string.encode()).decode()
    
    headers = {
        'Authorization': f'Basic {auth_header}',
        'Content-Type': 'application/json'
    }
    
    payload = {
        'customer': customer_id,
        'products': [{
            'product_id': product_id,
            'price': price,
            'quantity': 1,
            'options': {
                'generate_license': True
            }
        }],
        'status': 'complete',
        'gateway': 'manual'
    }
    
    response = requests.post(
        f"{os.getenv('EDD_API_URL')}/orders",
        json=payload,
        headers=headers
    )
    
    response.raise_for_status()
    order_data = response.json()
    
    return {
        'order_id': order_data['id'],
        'license_key': order_data['licenses'][0]['key'],
        'total': order_data['total']
    }

Example 3: Customer Lifetime Value Analysis

async function analyzeCustomerLTV(customer_id) {
  const orders = await eddRequest('GET', '/orders', {
    customer: customer_id,
    status: 'complete'
  });
  
  const stats = orders.reduce((acc, order) => {
    acc.total_spent += parseFloat(order.total);
    acc.order_count += 1;
    acc.products_purchased += order.items.length;
    
    const orderDate = new Date(order.date_created);
    if (!acc.first_purchase || orderDate < acc.first_purchase) {
      acc.first_purchase = orderDate;
    }
    if (!acc.last_purchase || orderDate > acc.last_purchase) {
      acc.last_purchase = orderDate;
    }
    
    return acc;
  }, {
    total_spent: 0,
    order_count: 0,
    products_purchased: 0,
    first_purchase: null,
    last_purchase: null
  });
  
  const daysSinceFirst = Math.floor(
    (new Date() - stats.first_purchase) / (1000 * 60 * 60 * 24)
  );
  
  return {
    lifetime_value: stats.total_spent,
    avg_order_value: stats.total_spent / stats.order_count,
    purchase_frequency: stats.order_count / (daysSinceFirst / 30),
    customer_age_days: daysSinceFirst,
    predicted_12mo_value: (stats.total_spent / daysSinceFirst) * 365
  };
}

Common Patterns

Pattern 1: Product Catalog Sync with Caching

const CACHE = new Map();
const CACHE_TTL = parseInt(process.env.CACHE_TTL || '300') * 1000;

async function getCachedProducts(params) {
  const cacheKey = JSON.stringify(params);
  const cached = CACHE.get(cacheKey);
  
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
  
  const products = await eddRequest('GET', '/products', params);
  
  CACHE.set(cacheKey, {
    data: products,
    timestamp: Date.now()
  });
  
  return products;
}

Pattern 2: Webhook Event Processing

function processWebhook(event) {
  const enriched = {
    ...event,
    processed_at: new Date().toISOString(),
    source: 'edd-webhook'
  };
  
  switch (event.event_type) {
    case 'edd_complete_purchase':
      return handleOrderComplete(enriched);
    case 'edd_customer_created':
      return handleCustomerCreated(enriched);
    case 'edd_subscription_status_changed':
      return handleSubscriptionChange(enriched);
    default:
      return { status: 'ignored', event_type: event.event_type };
  }
}

Pattern 3: Rate-Limited Batch Operations

async function batchUpdateProducts(updates) {
  const RATE_LIMIT = parseInt(process.env.RATE_LIMIT_MAX || '60');
  const DELAY = (60 / RATE_LIMIT) * 1000;
  
  const results = [];
  
  for (const update of updates) {
    try {
      const result = await eddRequest('PUT', `/products/${update.id}`, update);
      results.push({ success: true, id: update.id, result });
    } catch (error) {
      results.push({ success: false, id: update.id, error: error.message });
    }
    
    await new Promise(resolve => setTimeout(resolve, DELAY));
  }
  
  return results;
}

Troubleshooting

Authentication Failures

Symptom: 401 Unauthorized errors

Solution:

  • Verify EDD_API_KEY and EDD_API_TOKEN are correct
  • Check API key permissions in WordPress admin
  • Ensure key hasn't been revoked or expired
  • Test credentials with curl:
curl -u "PUBLIC_KEY:TOKEN" https://yoursite.com/wp-json/edd/v2/products

Rate Limiting Issues

Symptom: 429 Too Many Requests errors

Solution:

  • Reduce RATE_LIMIT_MAX in configuration
  • Implement request queuing with delays
  • Enable caching to reduce API calls
  • Use batch endpoints where available

Missing Data in Responses

Symptom: Expected fields are null or missing

Solution:

  • Verify EDD version supports the endpoint
  • Check if required EDD extensions are installed (e.g., Software Licensing)
  • Update API version in EDD_API_URL (try /v2 or /v3)
  • Review EDD plugin settings for disabled features

Connection Timeouts

Symptom: Requests hang or timeout

Solution:

  • Increase timeout in fetch/requests configuration
  • Check WordPress site performance and hosting
  • Verify firewall rules allow MCP server IP
  • Enable WordPress caching (Redis/Memcached)

Cache Staleness

Symptom: Outdated data returned after updates

Solution:

  • Reduce CACHE_TTL value
  • Implement cache invalidation on write operations
  • Use Redis with TTL instead of in-memory cache
  • Add cache-busting query parameters

HMAC Verification Errors

Symptom: Signature mismatch warnings

Solution:

  • Ensure HMAC_SECRET matches across client and server
  • Verify payload hasn't been modified in transit
  • Check for character encoding issues
  • Use webhook signature verification from EDD settings

Advanced Usage

Custom Middleware Chain

const middleware = [
  validateRequest,
  enrichWithGeoData,
  applyTaxCalculation,
  logAuditTrail
];

async function processRequest(tool, params) {
  let context = { tool, params, timestamp: Date.now() };
  
  for (const fn of middleware) {
    context = await fn(context);
  }
  
  return executeEDDTool(context.tool, context.params);
}

Multi-Store Support

const stores = {
  'store1': {
    url: process.env.EDD_STORE1_URL,
    key: process.env.EDD_STORE1_KEY,
    token: process.env.EDD_STORE1_TOKEN
  },
  'store2': {
    url: process.env.EDD_STORE2_URL,
    key: process.env.EDD_STORE2_KEY,
    token: process.env.EDD_STORE2_TOKEN
  }
};

function getStoreConfig(store_id) {
  return stores[store_id] || stores['store1'];
}

This skill enables AI coding agents to interact with Easy Digital Downloads through natural language, performing complex e-commerce operations, analytics, and automation tasks seamlessly.

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.25

Published

Sep 25, 2026

Category

Uncategorized

License

NOASSERTION

Source path

skills/commercevault-edd-mcp-server

Default branch

main

Latest commit

329e67c

Tree SHA

01fd22f