MCP server for Open Loyalty API - enables AI agents to manage loyalty programs, members, points, rewards, and transactions
npm install @open-loyalty/mcp-serverMCP (Model Context Protocol) server for interacting with Open Loyalty API. This server enables AI agents like Claude and ChatGPT to manage loyalty programs, members, points, rewards, and transactions.
- Node.js 18 or later
- An Open Loyalty account with API access
``bash`
npm install -g @open-loyalty/mcp-server
Or use directly with npx (no installation required):
`bash`
npx @open-loyalty/mcp-server
`bash`
git clone https://github.com/OpenLoyalty/openloyalty-mcp.git
cd openloyalty-mcp/openloyalty-mcp
npm install
npm run build
The server requires the following environment variables:
| Variable | Description |
|----------|-------------|
| OPENLOYALTY_API_URL | Your Open Loyalty API URL (e.g., https://api.openloyalty.io) |OPENLOYALTY_API_TOKEN
| | Your API authentication token |OPENLOYALTY_DEFAULT_STORE_CODE
| | Default store code (e.g., default) |
For local development, create a .env file based on .env.example:
`bash`
cp .env.example .env
The server supports two transport modes for different use cases:
| Mode | Binary | Use Case |
|------|--------|----------|
| stdio | openloyalty-mcp | Local usage with Claude Desktop, Claude Code, Cursor |openloyalty-mcp-http
| HTTP | | Remote hosting, ChatGPT Actions, web integrations |
Both modes provide identical functionality - only the transport layer differs.
---
Use stdio mode when running the server locally with MCP clients like Claude Desktop.
Add this to your Claude Desktop configuration file:
- macOS: ~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json
- Windows:
#### Using npx (Recommended)
`json`
{
"mcpServers": {
"openloyalty": {
"command": "npx",
"args": ["-y", "@open-loyalty/mcp-server"],
"env": {
"OPENLOYALTY_API_URL": "https://your-instance.openloyalty.io",
"OPENLOYALTY_API_TOKEN": "your-api-token",
"OPENLOYALTY_DEFAULT_STORE_CODE": "default"
}
}
}
}
#### Using Global Installation
`json`
{
"mcpServers": {
"openloyalty": {
"command": "openloyalty-mcp",
"env": {
"OPENLOYALTY_API_URL": "https://your-instance.openloyalty.io",
"OPENLOYALTY_API_TOKEN": "your-api-token",
"OPENLOYALTY_DEFAULT_STORE_CODE": "default"
}
}
}
}
#### Using Local Build
`json`
{
"mcpServers": {
"openloyalty": {
"command": "node",
"args": ["/path/to/openloyalty-mcp/dist/index.js"],
"env": {
"OPENLOYALTY_API_URL": "https://your-instance.openloyalty.io",
"OPENLOYALTY_API_TOKEN": "your-api-token",
"OPENLOYALTY_DEFAULT_STORE_CODE": "default"
}
}
}
}
---
Use HTTP mode when hosting the server remotely for web-based MCP clients or ChatGPT Actions.
`bashUsing the binary
openloyalty-mcp-http
$3
| Variable | Required | Description |
|----------|----------|-------------|
|
OPENLOYALTY_API_URL | Yes* | Open Loyalty API URL |
| OPENLOYALTY_API_TOKEN | Yes* | API authentication token |
| OPENLOYALTY_DEFAULT_STORE_CODE | Yes* | Default store code |
| PORT or MCP_HTTP_PORT | No | Server port (default: 3000) |
| OAUTH_ENABLED | No | Enable multi-tenant OAuth mode |
| BASE_URL | OAuth | Public URL for OAuth callbacks |
| REDIS_URL | OAuth | Redis URL for token storage |*Required when
OAUTH_ENABLED is not set or false$3
| Endpoint | Method | Description |
|----------|--------|-------------|
|
/ | GET | Server info |
| /health | GET | Health check |
| /mcp | POST | MCP message endpoint |
| /mcp | GET | SSE stream (with session) |
| /mcp | DELETE | Close session |$3
For dedicated deployments with fixed credentials:
`bash
export OPENLOYALTY_API_URL="https://api.openloyalty.io"
export OPENLOYALTY_API_TOKEN="your-token"
export OPENLOYALTY_DEFAULT_STORE_CODE="default"
openloyalty-mcp-http
`$3
For shared deployments where each user provides their own credentials:
`bash
export OAUTH_ENABLED=true
export BASE_URL="https://your-server.com"
export REDIS_URL="redis://localhost:6379"
openloyalty-mcp-http
`With OAuth enabled, additional endpoints are available:
| Endpoint | Description |
|----------|-------------|
|
/authorize | OAuth authorization form |
| /token | Token exchange |
| /register | Dynamic client registration |
| /.well-known/oauth-authorization-server | OAuth metadata |$3
To use with ChatGPT:
1. Host the HTTP server with OAuth enabled
2. In GPT Editor → Configure → Actions:
- Authentication: OAuth
- Authorization URL:
https://your-server.com/authorize
- Token URL: https://your-server.com/token
- Scope: mcp
3. Add your MCP endpoint: https://your-server.com/mcpUsers will be prompted to enter their Open Loyalty credentials during the OAuth flow.
---
Development
`bash
Run stdio server in development mode
npm run devRun HTTP server in development mode
npm run dev:httpBuild for production
npm run buildRun tests
npm testType checking
npm run typecheck
`---
Available Tools (112 total)
$3
- ol_wallet_type_list - List all wallet types (point currencies)
- ol_wallet_type_get - Get details for a specific wallet type$3
- ol_tierset_list - List all tier sets
- ol_tierset_create - Create a new tier set
- ol_tierset_get - Get tier set details with condition IDs
- ol_tierset_update - Update tier set metadata
- ol_tierset_update_tiers - Define tier thresholds
- ol_tierset_get_tiers - Get all tiers in a tier set$3
- ol_member_create - Register a new loyalty program member
- ol_member_get - Get member details including profile, points balance, and tier status
- ol_member_list - Search and list members with optional filters
- ol_member_update - Update member profile fields
- ol_member_activate - Activate a deactivated member
- ol_member_deactivate - Deactivate an active member
- ol_member_delete - Permanently remove member (GDPR compliance)
- ol_member_get_tier_progress - Get tier progression status
- ol_member_assign_tier - Manually assign tier to member
- ol_member_remove_manual_tier - Remove manual tier assignment$3
- ol_points_add - Add points to member wallet (with optional expiration/lock)
- ol_points_spend - Deduct points from member wallet
- ol_points_transfer - Transfer points between members (P2P)
- ol_points_get_balance - Get member points balance breakdown
- ol_points_get_history - Get points transaction history
- ol_points_get_histogram - Get points histogram for visualization$3
- ol_reward_list - List available rewards
- ol_reward_create - Create a new reward
- ol_reward_get - Get reward details
- ol_reward_update - Update reward configuration
- ol_reward_activate - Activate a reward
- ol_reward_deactivate - Deactivate a reward
- ol_reward_buy - Purchase reward for member (deducts points)
- ol_reward_redeem - Mark coupon as used
- ol_reward_category_list - List reward categories$3
- ol_transaction_create - Record a purchase transaction
- ol_transaction_get - Get transaction details
- ol_transaction_list - List transactions with filters
- ol_transaction_assign_member - Assign unmatched transaction to member$3
- ol_campaign_list - List all campaigns with optional filters
- ol_campaign_create - Create campaign to automate engagement
- ol_campaign_get - Get full campaign configuration
- ol_campaign_update - Update campaign (full replacement)
- ol_campaign_patch - Patch campaign (active/displayOrder only)
- ol_campaign_delete - Permanently delete a campaign
- ol_campaign_simulate - Preview campaign effects without executing
- ol_campaign_generate_codes - Generate redemption codes
- ol_campaign_list_codes - List redemption codes
- ol_campaign_get_available - Get campaigns available for member
- ol_campaign_get_visible - Get campaigns visible to member
- ol_campaign_get_leaderboard - Get campaign leaderboard$3
- ol_segment_list - List customer segments
- ol_segment_create - Create segment to group members
- ol_segment_get - Get segment details with criteria
- ol_segment_update - Update segment configuration
- ol_segment_delete - Permanently delete a segment
- ol_segment_get_members - Get members matching segment
- ol_segment_activate - Activate a segment
- ol_segment_deactivate - Deactivate a segment
- ol_segment_get_resources - Get resources associated with segment$3
- ol_achievement_list - List achievements
- ol_achievement_create - Create achievement for gamification
- ol_achievement_get - Get achievement details
- ol_achievement_update - Update achievement (full replacement)
- ol_achievement_patch - Patch achievement (active/displayOrder)
- ol_achievement_get_member_progress - Get member's progress on achievement
- ol_achievement_list_member_achievements - List member's achievements$3
- ol_badge_list - List badge types
- ol_badge_get - Get badge type details
- ol_badge_update - Update badge type configuration
- ol_badge_get_member_badges - Get badges earned by member$3
- ol_analytics_tiers - Get tier distribution with member counts
- ol_analytics_members - Get member statistics (new, active, inactive)
- ol_analytics_points - Get points statistics (issued, spent, expired)
- ol_analytics_transactions - Get transaction statistics
- ol_analytics_referrals - Get referral program statistics
- ol_analytics_campaigns - Get campaign performance metrics
- ol_analytics_dashboard - Get dashboard overview metrics
- ol_analytics_units - Get wallet-specific metrics
- ol_analytics_campaign_detail - Get detailed campaign analytics$3
- ol_admin_list - List admin users
- ol_admin_create - Create admin user
- ol_admin_get - Get admin user details
- ol_admin_update - Update admin user profile
- ol_admin_change_password - Change admin password
- ol_admin_get_permissions - Get admin permissions$3
- ol_role_list - List roles
- ol_role_create - Create role with permissions
- ol_role_get - Get role details
- ol_role_update - Update role
- ol_role_delete - Delete role
- ol_acl_get_resources - Get available ACL resources and actions$3
- ol_apikey_create - Create API key (token shown once!)
- ol_apikey_list - List API keys for admin
- ol_apikey_delete - Delete API key$3
- ol_audit_list - List audit log entries
- ol_audit_export - Export audit logs$3
- ol_store_list - List stores
- ol_store_create - Create store for multi-tenancy
- ol_store_get - Get store details
- ol_store_update - Update store configuration$3
- ol_webhook_list - List webhook subscriptions
- ol_webhook_create - Create webhook subscription for event notifications
- ol_webhook_get - Get webhook subscription details
- ol_webhook_update - Update webhook subscription
- ol_webhook_delete - Delete webhook subscription
- ol_webhook_events - List available webhook event types$3
- ol_import_create - Create bulk import from CSV
- ol_import_list - List imports with status
- ol_import_get - Get import details and item statuses$3
- ol_export_create - Create data export (async)
- ol_export_list - List exports with status
- ol_export_get - Get export status and details
- ol_export_download - Download export CSV (when status='done')---
Example Workflows
$3
`
ol_wallet_type_list
// Note: conditions use attribute (not type) and walletType expects the wallet CODE (e.g., "default"), not the UUID.
ol_tierset_create({ name: "VIP Program", conditions: [{ attribute: "activeUnits", walletType: "points" }] })
ol_tierset_get({ tierSetId: "..." })
ol_tierset_update_tiers({
tierSetId: "...",
tiers: [
{ name: "Bronze", conditions: [{ conditionId: "xxx", value: 400 }] },
{ name: "Silver", conditions: [{ conditionId: "xxx", value: 800 }] },
{ name: "Gold", conditions: [{ conditionId: "xxx", value: 1200 }] }
]
})
`$3
`
// Register member
ol_member_create({ email: "john@example.com", firstName: "John", lastName: "Doe" })// Add welcome bonus
ol_points_add({ memberId: "...", points: 100, comment: "Welcome bonus" })
// Record purchase (auto-earns points via campaigns)
ol_transaction_create({
header: { documentNumber: "INV-001", purchasedAt: "2024-01-15T10:00:00Z" },
items: [{ sku: "PROD-1", name: "Widget", grossValue: 99.99, category: "Electronics" }],
customerData: { email: "john@example.com" }
})
// Check tier progress
ol_member_get_tier_progress({ memberId: "..." })
`$3
`
// List available rewards
ol_reward_list({ active: true })// Check member balance
ol_points_get_balance({ memberId: "..." })
// Purchase reward (deducts points, returns coupon code)
ol_reward_buy({ rewardId: "...", memberId: "..." })
// Later: mark coupon as used
ol_reward_redeem({ memberId: "...", couponCode: "COUP-ABC123" })
`$3
`
// Find unmatched transactions
ol_transaction_list({ matched: false })// Assign to member (triggers point campaigns)
ol_transaction_assign_member({ documentNumber: "INV-999", loyaltyCardNumber: "CARD-123" })
`$3
`
// First, find the Gold tier level ID
ol_tierset_get_tiers({ tierSetId: "..." })// Create a segment targeting Gold tier members
ol_segment_create({
name: "Gold Members",
parts: [{
criteria: [{
type: "tier",
tierIds: ["gold-level-id"]
}]
}]
})
// Create campaign with double points effect
ol_campaign_create({
type: "direct",
trigger: "transaction",
translations: { en: { name: "Double Points for Gold", description: "Gold members earn 2x points" } },
// Required: activity.startsAt, rules[].name. Use effects[].effect (not type). pointsRule is a STRING expression (not an object).
activity: { startsAt: "2024-01-01T00:00:00Z" },
rules: [{
name: "Double points",
effects: [{
effect: "give_points",
pointsRule: "transaction.grossValue * 2"
}]
}],
audience: {
target: "segment",
segments: ["segment-id"]
},
active: true
})
// Test the campaign before it triggers
ol_campaign_simulate({
trigger: "transaction",
transaction: { grossValue: 100 },
customer: { email: "gold-member@example.com" }
})
`$3
`
// Create segment for members with 10+ transactions
ol_segment_create({
name: "VIP Customers",
description: "Members with 10 or more purchases",
parts: [{
criteria: [{
type: "transaction_count",
min: 10
}]
}],
active: true
})// Check segment membership
ol_segment_get_members({ segmentId: "..." })
// Use for campaign targeting
ol_campaign_create({
type: "direct",
trigger: "transaction",
translations: { en: { name: "VIP Bonus" } },
activity: { startsAt: "2024-01-01T00:00:00Z" },
rules: [{
name: "VIP Bonus Points",
effects: [{ effect: "give_points", pointsRule: "50" }]
}],
audience: { target: "segment", segments: ["vip-segment-id"] },
active: true
})
`$3
`
// Create an achievement for making 5 purchases
ol_achievement_create({
translations: { en: { name: "Frequent Shopper", description: "Make 5 purchases" } },
rules: [{
type: "direct",
trigger: "transaction",
aggregation: { type: "quantity" },
completeRule: {
periodGoal: 5,
period: { type: "day", consecutive: 1 }
}
}],
badgeTypeId: "shopper-badge-id",
active: true
})// Check member progress
ol_achievement_get_member_progress({ memberId: "...", achievementId: "..." })
// List all member achievements and badges
ol_achievement_list_member_achievements({ memberId: "..." })
ol_badge_get_member_badges({ memberId: "..." })
`$3
`
// Parts use OR logic - member matches if ANY part matches
// Criteria within parts use AND logic - must match ALL criteria in that part// Example: (10+ transactions) OR (5-9 transactions)
ol_segment_create({
name: "High Value Members",
parts: [
{
// Part 1: Frequent shoppers
criteria: [
{ type: "transaction_count", min: 10, max: 999999 }
]
},
{
// Part 2: Moderately frequent shoppers (OR with Part 1)
criteria: [
{ type: "transaction_count", min: 5, max: 9 }
]
}
]
})
`$3
`
// Discover available ACL resources and actions
ol_acl_get_resources()// Create a role with VIEW-only permissions
ol_role_create({
name: "Analyst",
permissions: [
{ resource: "ANALYTICS", access: "VIEW" },
{ resource: "MEMBER", access: "VIEW" },
{ resource: "TRANSACTION", access: "VIEW" },
{ resource: "CAMPAIGN", access: "VIEW" }
]
})
// Create admin with analyst role
ol_admin_create({
email: "analyst@company.com",
password: "SecurePass123!",
firstName: "Data",
lastName: "Analyst",
roles: ["analyst-role-id"]
})
`$3
`
// Get admin to create API key for
ol_admin_list({ email: "integration@company.com" })// Create API key - CRITICAL: Save the token immediately!
ol_apikey_create({
adminId: "admin-uuid",
name: "CRM Integration Key",
expirationDate: "2025-12-31"
})
// Response includes token that is ONLY shown once
// List API keys (tokens not shown)
ol_apikey_list({ adminId: "admin-uuid" })
`$3
`
// Get high-level dashboard metrics
ol_analytics_dashboard()// Analyze tier distribution
ol_analytics_tiers({ dateFrom: "2024-01-01", dateTo: "2024-12-31" })
// Check points economy
ol_analytics_points({ dateFrom: "2024-01-01", dateTo: "2024-12-31" })
// Analyze specific campaign
ol_analytics_campaign_detail({ campaignId: "campaign-uuid" })
// Get wallet-specific metrics
ol_analytics_units({ walletTypeCode: "points" })
`$3
`
// List recent audit entries
ol_audit_list({ perPage: 50 })// Filter by specific user
ol_audit_list({ username: "admin@company.com" })
// Filter by entity type and date range
ol_audit_list({
entityType: "MEMBER",
dateFrom: "2024-01-01",
dateTo: "2024-01-31"
})
// Export audit logs for compliance
ol_audit_export({
dateFrom: "2024-01-01",
dateTo: "2024-12-31"
})
`$3
`
// Create a new store for a region
ol_store_create({
code: "EU",
name: "European Store",
currency: "EUR",
active: true
})// List all stores
ol_store_list()
// Use storeCode in subsequent operations
ol_member_create({
email: "customer@eu.example.com",
firstName: "Jean",
lastName: "Dupont",
storeCode: "EU"
})
`$3
`
// Discover available event types
ol_webhook_events()// Subscribe to member creation events
ol_webhook_create({
eventName: "member.created",
url: "https://crm.example.com/webhooks/loyalty",
headers: [
{ headerName: "Authorization", headerValue: "Bearer crm-token" }
]
})
// List current subscriptions
ol_webhook_list()
// Update subscription URL
ol_webhook_update({
webhookSubscriptionId: "...",
url: "https://crm-v2.example.com/webhooks/loyalty"
})
`$3
`
// Create import with CSV content
ol_import_create({
type: "member",
fileContent: "email,firstName,lastName\njohn@example.com,John,Doe\njane@example.com,Jane,Smith",
fileName: "members.csv"
})// Poll import status
ol_import_list({ type: "member" })
// Check individual item statuses
ol_import_get({ importId: "..." })
`$3
`
// Create export for campaign codes
ol_export_create({
type: "campaignCode",
filters: { campaignId: "campaign-uuid" }
})// Poll until status is 'done'
ol_export_get({ exportId: "..." })
// Download the CSV file
ol_export_download({ exportId: "..." })
`$3
`
// Create import for adding points to multiple members
ol_import_create({
type: "unitTransferAdding",
fileContent: "loyaltyCardNumber,points,comment\nCARD-001,500,Promotion bonus\nCARD-002,500,Promotion bonus"
})// Check import progress
ol_import_get({ importId: "..." })
``---
- GitHub: OpenLoyalty/openloyalty-mcp
- Open Loyalty: openloyalty.io
- MCP Protocol: modelcontextprotocol.io
MIT