Rule Mcp Server — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Rule Mcp Server (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A Model Context Protocol (MCP) server for the Rule marketing automation platform. The server provides full access to Rule's REST API v2 for subscriber management, campaigns, transactional messages, and much more.
You have two easy ways to run this server:
The server is hosted at `https://rule-mcp-server-production.up.railway.app`. This is the fastest way to get started because there is no setup or cloning required. Just point your MCP client at the endpoint and provide your Rule API key.
npxIf you prefer to run the server locally, you do not need to clone this repo or hardcode a path. Any computer with Node.js 18+ can run it with:
npx -y rule-mcp-serverThis works well for Claude Desktop, Claude Code, and other MCP clients that launch local commands.
#### Claude Desktop
Add to your claude_desktop_config.json:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json{
"mcpServers": {
"rule": {
"type": "streamable-http",
"url": "https://rule-mcp-server-production.up.railway.app/mcp",
"headers": {
"Authorization": "Bearer YOUR_RULE_API_KEY"
}
}
}
}Restart Claude Desktop after saving.
#### Claude Desktop with local npx
{
"mcpServers": {
"rule": {
"command": "npx",
"args": ["-y", "rule-mcp-server"],
"env": {
"RULE_API_KEY": "YOUR_RULE_API_KEY"
}
}
}
}This is the easiest local setup because it works on any computer without changing file paths.
#### Claude Code (CLI)
claude mcp add rule --transport streamable-http --header "Authorization: Bearer YOUR_RULE_API_KEY" https://rule-mcp-server-production.up.railway.app/mcp#### Cursor / other MCP clients
Use the Streamable HTTP transport with:
https://rule-mcp-server-production.up.railway.app/mcpAuthorization: Bearer YOUR_RULE_API_KEYMany teams have more than one Rule account or key, such as Production, Staging, or Client A.
#### Hosted HTTP clients
Add multiple MCP server entries, one per key:
{
"mcpServers": {
"rule-production": {
"type": "streamable-http",
"url": "https://rule-mcp-server-production.up.railway.app/mcp",
"headers": {
"Authorization": "Bearer RULE_PRODUCTION_KEY"
}
},
"rule-staging": {
"type": "streamable-http",
"url": "https://rule-mcp-server-production.up.railway.app/mcp",
"headers": {
"Authorization": "Bearer RULE_STAGING_KEY"
}
}
}
}#### Local npx clients
The server now supports a shared RULE_API_KEYS list plus a selected label via RULE_API_KEY_NAME.
{
"mcpServers": {
"rule-production": {
"command": "npx",
"args": ["-y", "rule-mcp-server"],
"env": {
"RULE_API_KEYS": "{\"Production\":\"RULE_PRODUCTION_KEY\",\"Staging\":\"RULE_STAGING_KEY\"}",
"RULE_API_KEY_NAME": "Production"
}
},
"rule-staging": {
"command": "npx",
"args": ["-y", "rule-mcp-server"],
"env": {
"RULE_API_KEYS": "{\"Production\":\"RULE_PRODUCTION_KEY\",\"Staging\":\"RULE_STAGING_KEY\"}",
"RULE_API_KEY_NAME": "Staging"
}
}
}
}Supported formats for RULE_API_KEYS:
{"Production":"key_1","Staging":"key_2"}[{"name":"Production","key":"key_1"},{"name":"Staging","key":"key_2"}]Production=key_1;Staging=key_2Verify the hosted server is running:
GET https://rule-mcp-server-production.up.railway.app/health
→ {"status":"ok"}#### rule_create_subscribers Create one or multiple subscribers with support for:
Example:
{
"subscribers": {
"email": "[email protected]",
"phone_number": "+46701234567",
"language": "sv",
"fields": [
{
"key": "Profile.FirstName",
"value": "Anna",
"type": "text"
},
{
"key": "Purchase.LastOrderDate",
"value": "2024-03-20 12:00:00",
"type": "datetime"
}
]
},
"tags": ["Newsletter", "Customer"],
"update_on_duplicate": true,
"automation": "reset"
}#### rule_get_subscribers List all subscribers with pagination (max 100 per page).
#### rule_get_subscriber Get detailed subscriber information by email, phone, or ID.
#### rule_get_subscriber_fields Get all custom field values for a subscriber organized by groups.
#### rule_update_subscriber Update subscriber details including email, phone, language, tags, and custom fields.
#### rule_delete_subscriber Permanently remove a subscriber.
#### rule_add_subscriber_tags Add tags to a subscriber (creates tags if they don't exist, triggers automations).
#### rule_get_subscriber_tags List all tags for a subscriber.
#### rule_clear_subscriber_tags Remove all tags from a subscriber (doesn't delete tags).
#### rule_delete_subscriber_tag Remove a specific tag from a subscriber.
#### rule_get_tags List all tags with pagination.
#### rule_get_tag Get tag details with optional subscriber count.
#### rule_update_tag Update tag name or description.
#### rule_delete_tag Permanently delete a tag.
#### rule_clear_tag Remove all subscribers from a tag.
#### rule_get_segments List all sync-at segments with pagination.
#### rule_send_transaction Send individual transactional email or SMS.
Email Example:
{
"transaction_type": "email",
"transaction_name": "Password Reset",
"subject": "Reset Your Password",
"from": {
"name": "My Company",
"email": "[email protected]"
},
"to": {
"name": "John Doe",
"email": "[email protected]"
},
"content": {
"plain": "UGFzc3dvcmQgcmVzZXQ=", // Base64 encoded
"html": "PHA+UGFzc3dvcmQgcmVzZXQ8L3A+" // Base64 encoded
}
}SMS Example (0.40 SEK per message):
{
"transaction_type": "text_message",
"from": {
"name": "My Company"
},
"to": {
"phone_number": "+46701234567"
},
"content": "Your verification code is: 123456"
}#### rule_get_templates List all available email templates.
#### rule_get_template Get template details including supported content blocks.
#### rule_get_campaigns List campaigns with optional filtering:
#### rule_create_campaign Create a draft campaign with recipients and content.
#### rule_get_campaign Get campaign details including recipients.
#### rule_get_campaign_statistics Get campaign performance metrics:
#### rule_send_campaign Send a campaign immediately.
#### rule_schedule_campaign Schedule campaign for future delivery.
Example:
{
"send_at": "2024-12-25 10:00:00",
"subject": "Holiday Greetings",
"message_type": "email",
"language": "sv",
"from": {
"name": "My Company",
"email": "[email protected]"
},
"recipients": {
"tags": [
{ "identifier": "Newsletter" }
],
"segments": [
{ "identifier": "InactiveUsers", "negative": true }
]
},
"content": {
"plain": "...",
"html": "..."
}
}#### rule_delete_campaign Permanently delete a campaign.
#### rule_create_groups_and_fields Create custom field groups and fields.
Example:
{
"fields": [
{
"key": "Profile.FirstName",
"type": "text"
},
{
"key": "Orders.LastPurchase",
"type": "datetime"
},
{
"key": "Preferences.Categories",
"type": "multiple"
}
]
}Supported field types:
text - Text stringsdate - Dates (YYYY-MM-DD)datetime - Timestamps (YYYY-MM-DD HH:MM:SS)time - Time values (HH:MM:SS)multiple - Arrays of stringsjson - JSON-encoded data#### rule_get_groups List all custom field groups with their fields.
#### rule_get_group Get a specific group's fields.
#### rule_get_suppressions List all suppressions (bounces, spam complaints, unsubscribes).
#### rule_get_preference_groups List all preference groups with available preferences.
#### rule_get_subscriber_preferences Get a subscriber's preferences for a specific group.
#### rule_update_subscriber_preferences Update subscriber's opt-in/opt-out status.
Example:
{
"identifier": "[email protected]",
"preference_group_id": 1,
"preferences": [
{
"preference_id": 1,
"is_opted_in": true
},
{
"preference_id": 2,
"is_opted_in": false
}
]
}#### rule_get_journeys List automation journeys with optional filtering by name or preference.
// Create subscriber with profile data and order history
{
"subscribers": {
"email": "[email protected]",
"fields": [
{ "key": "Profile.FirstName", "value": "Erik", "type": "text" },
{ "key": "Orders.LastOrder", "value": "2024-03-20", "type": "date" },
{ "key": "Orders.TotalSpent", "value": "2500", "type": "text" }
]
},
"tags": ["Customer", "HighValue"],
"update_on_duplicate": true
}// Send order confirmation
{
"transaction_type": "email",
"transaction_name": "Order Confirmation",
"subject": "Your Order #12345",
"from": {
"name": "My Shop",
"email": "[email protected]"
},
"to": {
"name": "Customer Name",
"email": "[email protected]"
},
"content": {
"plain": btoa("Thank you for your order!"),
"html": btoa("<h1>Thank you!</h1><p>Your order is confirmed.</p>")
}
}// Create campaign
const campaign = await rule_create_campaign({
"subject": "Spring Sale - 30% Off",
"message_type": "email",
"from": { "name": "My Shop", "email": "[email protected]" },
"recipients": {
"tags": [{ "identifier": "Newsletter" }]
},
"content": { "plain": "...", "html": "..." }
});
// Send immediately
await rule_send_campaign(campaign);// Add tags
await rule_add_subscriber_tags({
"identifier": "[email protected]",
"tags": ["VIP", "Spring2024Campaign"]
});
// Remove specific tag
await rule_delete_subscriber_tag({
"identifier": "[email protected]",
"tag_identifier": "Spring2024Campaign"
});// Import subscribers and trigger welcome flow
{
"subscribers": [
{ "email": "[email protected]", "fields": [...] },
{ "email": "[email protected]", "fields": [...] }
],
"tags": ["Newsletter"],
"automation": "force", // Trigger automation flows
"sync_subscribers": true
}Retry-After headermeta.next URL from responses for next pagesync_subscribers: trueThe API key can be provided in three ways (this server uses Bearer token):
Authorization: Bearer YOUR-API-KEY?apikey=YOUR-API-KEY"apikey": "YOUR-API-KEY"Common error responses:
// 401 - Not authorized
{ "error": "NotAuthorized" }
// 404 - Resource not found
{ "error": "SubscriberNotFound", "message": "Could not find subscriber" }
// 400 - Validation error
{
"error": "BadRequest",
"message": "Some fields could not be validated",
"fields": {
"email": ["The email field is required"]
}
}
// 409 - Duplicate
{ "error": "DuplicateSubscriber", "message": "Subscriber already exists" }
// 429 - Rate limit exceeded
"Too Many Attempts."// When order is created in Shopify
async function syncOrderToRule(order) {
await rule_create_subscribers({
subscribers: {
email: order.customer.email,
fields: [
{ key: "Orders.LastOrder", value: order.created_at, type: "datetime" },
{ key: "Orders.LastAmount", value: order.total_price, type: "text" },
{ key: "Orders.ProductNames", value: order.line_items.map(i => i.title), type: "multiple" }
]
},
tags: ["Customer", `Order${order.order_number}`],
update_on_duplicate: true
});
}// Trigger cart abandonment flow
async function handleAbandonedCart(cart) {
await rule_create_subscribers({
subscribers: {
email: cart.email,
fields: [
{ key: "Cart.AbandonedAt", value: new Date().toISOString(), type: "datetime" },
{ key: "Cart.Items", value: JSON.stringify(cart.items), type: "json" }
]
},
tags: ["AbandonedCart"],
automation: "reset", // Restart abandoned cart flow
update_on_duplicate: true
});
}// Schedule follow-up campaign
async function scheduleFollowUp(purchaseData) {
const followUpDate = new Date();
followUpDate.setDate(followUpDate.getDate() + 7);
await rule_schedule_campaign({
send_at: followUpDate.toISOString().slice(0, 19).replace('T', ' '),
subject: "How are you enjoying your purchase?",
message_type: "email",
from: { name: "My Shop", email: "[email protected]" },
recipients: {
tags: [{ identifier: `Order${purchaseData.orderId}` }]
},
content: {
plain: btoa("..."),
html: btoa("...")
}
});
}Rule can send webhooks for various events. Configure at: https://app.rule.io/#/settings/developer
Available webhook events:
Example webhook payload (transaction sent):
{
"message": {
"id": 111111,
"transaction_id": 111111,
"subject": "Password Reset",
"type": "email",
"created_at": "2024-03-20 12:00:00"
},
"subscriber": {
"id": 111111,
"email": "[email protected]",
"phone_number": "+46701234567"
}
}MIT
For issues with the MCP server, please create an issue in the repository.
For Rule API questions, contact: [email protected]
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.