Skip to main content
Glama

promotions_disable_rule

Disable a cart price rule to stop a promotion from applying in Magento. Use this tool to deactivate specific promotional rules.

Instructions

Disable a cart price rule.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsNoAction parameters as a JSON object

Implementation Reference

  • The handler for the promotions.disable_rule tool. Accepts a rule_id, validates it via DisableRuleSchema, then calls Magento API PUT /V1/salesRules/{rule_id} with is_active: false to disable the cart price rule. Returns a success message.
    // ── Disable Rule ──────────────────────────────────────────────────────
    {
      name: 'promotions.disable_rule',
      description: 'Disable a cart price rule.',
      riskTier: RiskTier.Safe,
      requiresAuth: true,
      handler: async (params: Record<string, unknown>, context: ActionContext) => {
        const validated = DisableRuleSchema.parse(params);
        const client = context.getClient();
        const result = await client.put(`/V1/salesRules/${validated.rule_id}`, {
          rule: { rule_id: validated.rule_id, is_active: false },
        });
        return { message: 'Rule disabled successfully', rule: result };
      },
    },
  • Zod schema for DisableRuleSchema. Only requires rule_id (number, integer). No confirmation or reason needed, unlike EnableRuleSchema.
    export const DisableRuleSchema = z.object({
      rule_id: z.number().int(),
    });
  • src/index.ts:76-78 (registration)
    The tool name 'promotions.disable_rule' is transformed to 'promotions_disable_rule' (dots replaced with underscores) and registered with the MCP server via mcpServer.tool() in the for-loop over all actions.
    for (const action of allActions) {
      // Convert dots to underscores for MCP tool names (e.g. "auth.login" -> "auth_login")
      const toolName = action.name.replace(/\./g, '_');
  • src/index.ts:54-55 (registration)
    The action definition is created by createPromotionsActions(planStore, guardrails, config) and included in the allActions array, making it available for registration.
    ...createPromotionsActions(planStore, guardrails, config),
    ...createCatalogActions(planStore, guardrails, idempotencyLedger, config),
  • The createPromotionsActions factory function that returns all promotion action definitions, including promotions.disable_rule at lines 212-226.
    export function createPromotionsActions(
      planStore: PlanStore,
      guardrails: Guardrails,
      config: McpConfig,
    ): ActionDefinition[] {
      return [
        // ── Prepare Cart Price Rule Create ────────────────────────────────────
        {
          name: 'promotions.prepare_cart_price_rule_create',
          description: 'Validate and prepare a cart price rule for creation. Returns a plan for review.',
          riskTier: RiskTier.Risk,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, _context: ActionContext) => {
            const validated = PrepareCartPriceRuleCreateSchema.parse(params);
    
            // Enforce guardrails
            guardrails.enforceDiscountLimit(validated.simple_action, validated.discount_amount);
    
            // Ensure is_active defaults to false (production-safe)
            const rulePayload = {
              ...validated,
              is_active: validated.is_active ?? false,
            };
    
            // Validate date ordering
            if (rulePayload.from_date && rulePayload.to_date) {
              if (new Date(rulePayload.to_date) <= new Date(rulePayload.from_date)) {
                throw new Error('to_date must be after from_date');
              }
            }
    
            const warnings: string[] = [];
            if (rulePayload.is_active) {
              warnings.push('Rule will be created in ACTIVE state. Consider creating disabled first.');
            }
            if (!rulePayload.to_date) {
              warnings.push('No end date specified. Rule will run indefinitely if enabled.');
            }
    
            const plan = planStore.create(
              'promotions.commit_cart_price_rule_create',
              rulePayload,
              1,
              config.planExpiryMinutes,
              [rulePayload],
              warnings,
            );
    
            return {
              plan_id: plan.plan_id,
              expires_at: plan.expires_at,
              rule_preview: rulePayload,
              warnings,
              message: 'Plan created. Review and call promotions.commit_cart_price_rule_create to execute.',
            };
          },
        },
    
        // ── Commit Cart Price Rule Create ─────────────────────────────────────
        {
          name: 'promotions.commit_cart_price_rule_create',
          description: 'Execute a previously prepared cart price rule creation.',
          riskTier: RiskTier.Risk,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = CommitPlanSchema.parse(params);
            guardrails.requireConfirmation(RiskTier.Risk, params);
    
            const plan = planStore.consume(validated.plan_id);
            if (!plan) {
              throw new Error('Plan not found or expired. Prepare a new plan.');
            }
    
            const client = context.getClient();
            const rulePayload = plan.payload as Record<string, unknown>;
    
            // Map to Magento API format
            const magentoRule = {
              rule: {
                name: rulePayload.name,
                description: rulePayload.description || '',
                is_active: rulePayload.is_active,
                website_ids: rulePayload.website_ids,
                customer_group_ids: rulePayload.customer_group_ids,
                from_date: rulePayload.from_date || null,
                to_date: rulePayload.to_date || null,
                simple_action: rulePayload.simple_action,
                discount_amount: rulePayload.discount_amount,
                discount_qty: rulePayload.discount_qty ?? 0,
                apply_to_shipping: rulePayload.apply_to_shipping ?? false,
                stop_rules_processing: rulePayload.stop_rules_processing ?? false,
                sort_order: rulePayload.sort_order ?? 0,
                coupon_type: rulePayload.coupon_type === 'specific_coupon' ? 2
                  : rulePayload.coupon_type === 'auto' ? 3 : 1,
                uses_per_customer: rulePayload.uses_per_customer ?? 0,
                uses_per_coupon: rulePayload.uses_per_coupon ?? 0,
              },
            };
    
            const result = await client.post('/V1/salesRules', magentoRule);
            return {
              message: 'Cart price rule created successfully',
              rule: result,
            };
          },
        },
    
        // ── Search Rules ──────────────────────────────────────────────────────
        {
          name: 'promotions.search_rules',
          description: 'Search cart price rules by query, website, or enabled status.',
          riskTier: RiskTier.Safe,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = SearchRulesSchema.parse(params);
            const client = context.getClient();
    
            const filterGroups: Array<{ filters: Array<{ field: string; value: string; conditionType?: string }> }> = [];
    
            if (validated.query) {
              filterGroups.push({
                filters: [{ field: 'name', value: `%${validated.query}%`, conditionType: 'like' }],
              });
            }
            if (validated.enabled !== undefined) {
              filterGroups.push({
                filters: [{ field: 'is_active', value: validated.enabled ? '1' : '0', conditionType: 'eq' }],
              });
            }
    
            const searchParams = client.buildSearchParams({
              filterGroups: filterGroups.length > 0 ? filterGroups : undefined,
              pageSize: validated.page_size,
              currentPage: validated.current_page,
            });
    
            const result = await client.get('/V1/salesRules/search', searchParams);
            return result;
          },
        },
    
        // ── Get Rule ──────────────────────────────────────────────────────────
        {
          name: 'promotions.get_rule',
          description: 'Get details of a specific cart price rule.',
          riskTier: RiskTier.Safe,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = GetRuleSchema.parse(params);
            const client = context.getClient();
            const result = await client.get(`/V1/salesRules/${validated.rule_id}`);
            return result;
          },
        },
    
        // ── Update Rule ───────────────────────────────────────────────────────
        {
          name: 'promotions.update_rule',
          description: 'Update an existing cart price rule.',
          riskTier: RiskTier.Risk,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = UpdateRuleSchema.parse(params);
            guardrails.requireConfirmation(RiskTier.Risk, params);
    
            const client = context.getClient();
            const result = await client.put(`/V1/salesRules/${validated.rule_id}`, {
              rule: { rule_id: validated.rule_id, ...validated.patch },
            });
            return { message: 'Rule updated successfully', rule: result };
          },
        },
    
        // ── Enable Rule ───────────────────────────────────────────────────────
        {
          name: 'promotions.enable_rule',
          description: 'Enable a cart price rule.',
          riskTier: RiskTier.Risk,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = EnableRuleSchema.parse(params);
            guardrails.requireConfirmation(RiskTier.Risk, params);
    
            const client = context.getClient();
            const result = await client.put(`/V1/salesRules/${validated.rule_id}`, {
              rule: { rule_id: validated.rule_id, is_active: true },
            });
            return { message: 'Rule enabled successfully', rule: result };
          },
        },
    
        // ── Disable Rule ──────────────────────────────────────────────────────
        {
          name: 'promotions.disable_rule',
          description: 'Disable a cart price rule.',
          riskTier: RiskTier.Safe,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = DisableRuleSchema.parse(params);
            const client = context.getClient();
            const result = await client.put(`/V1/salesRules/${validated.rule_id}`, {
              rule: { rule_id: validated.rule_id, is_active: false },
            });
            return { message: 'Rule disabled successfully', rule: result };
          },
        },
    
        // ── Generate Coupons ──────────────────────────────────────────────────
        {
          name: 'promotions.generate_coupons',
          description: 'Generate coupon codes for an existing cart price rule.',
          riskTier: RiskTier.Risk,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = GenerateCouponsSchema.parse(params);
            guardrails.enforceCouponCap(validated.qty);
            guardrails.requireConfirmation(RiskTier.Risk, params);
    
            const client = context.getClient();
    
            const formatMap: Record<string, string> = {
              alphanumeric: 'alphanum',
              alphabetical: 'alpha',
              numeric: 'num',
            };
    
            const result = await client.post('/V1/salesRules/generate', {
              couponSpec: {
                rule_id: validated.rule_id,
                quantity: validated.qty,
                length: validated.length,
                format: formatMap[validated.format] || 'alphanum',
                prefix: validated.prefix || '',
              },
            });
    
            return {
              message: `Generated ${validated.qty} coupon(s)`,
              coupons: result,
            };
          },
        },
    
        // ── Export Coupons ────────────────────────────────────────────────────
        {
          name: 'promotions.export_coupons',
          description: 'Export coupon codes for a rule in CSV format.',
          riskTier: RiskTier.Safe,
          requiresAuth: true,
          handler: async (params: Record<string, unknown>, context: ActionContext) => {
            const validated = ExportCouponsSchema.parse(params);
            const client = context.getClient();
    
            // Fetch coupons for the rule
            const searchParams = client.buildSearchParams({
              filterGroups: [
                { filters: [{ field: 'rule_id', value: String(validated.rule_id), conditionType: 'eq' }] },
              ],
              pageSize: 10000,
            });
    
            const result = await client.get<{ items: Array<Record<string, unknown>> }>('/V1/coupons/search', searchParams);
            const items = result.items || [];
    
            // Convert to CSV
            const headers = ['coupon_id', 'code', 'usage_limit', 'usage_per_customer', 'times_used', 'is_primary', 'created_at', 'expiration_date'];
            const csvLines = [headers.join(',')];
            for (const item of items) {
              const row = headers.map((h) => {
                const val = item[h];
                return val !== undefined && val !== null ? String(val) : '';
              });
              csvLines.push(row.join(','));
            }
    
            return {
              format: 'csv',
              total_count: items.length,
              csv: csvLines.join('\n'),
            };
          },
        },
      ];
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description only says 'disable' without detailing side effects (e.g., impact on applied coupons, reversibility, required permissions). No annotations exist to compensate, leaving critical behavioral aspects unaddressed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one sentence with no redundancy, but could be restructured to include key context without adding length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, no annotations, and a generic parameter, the description fails to provide a complete understanding of the tool's behavior, inputs, and outputs. It leaves the agent guessing about the effect and required arguments.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has a single 'params' object with a generic description, offering no insight into required fields or structure. The tool description does not elaborate on what parameters are needed, forcing reliance on the schema's vague text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Disable' and the resource 'a cart price rule', directly indicating the tool's action. It distinguishes itself from sibling tools like 'promotions_enable_rule' and 'promotions_get_rule'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives (e.g., when to disable vs. enable or update). There are no prerequisites or context about the rule's state before disabling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thomastx05/magento-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server