Stripe Mcp

Stripe MCP: How to Use Stripe MCP Servers

In the rapidly evolving landscape of AI-assisted financial operations, the integration of payment processing platforms with large language models represents a significant advancement for developers and businesses. Stripe MCP (Model Context Protocol) servers establish a secure bridge between conversational AI models and Stripe's robust payment infrastructure, enabling AI assistants to process payments, manage customers, handle subscriptions, and analyze transaction data—all through natural language interfaces. This technical implementation transforms AI assistants from simple text generators into powerful financial operation agents capable of executing secure payment workflows while maintaining proper authentication, authorization, and compliance controls.

Introduction

The Model Context Protocol provides a standardized framework for connecting AI models with external tools and data sources. Stripe MCP servers implement this protocol to create a secure, authenticated interface between AI assistants and Stripe's comprehensive payment ecosystem. By leveraging Stripe's extensive API capabilities, MCP servers enable language models to programmatically create payment intents, manage customers, handle subscriptions, process refunds, and analyze transaction patterns—all while maintaining PCI compliance and enforcing proper security measures for sensitive financial operations.

https://github.com/modelcontextprotocol/servers/tree/main/src/stripe (opens in a new tab)

Technical Architecture of Stripe MCP

MCP Protocol Foundation

Stripe MCP operates within the Model Context Protocol architecture, which defines several key components:

  1. Transport Layer:

    • STDIO (Standard Input/Output): Direct process communication
    • SSE (Server-Sent Events): HTTP-based asynchronous communication
    • WebSocket: Bidirectional real-time communication
  2. Resource Types:

    • Prompts: Templated payment workflow patterns
    • Tools: Executable Stripe API operations
    • Resources: Customer, payment, and account information
  3. Serialization Format: JSON for structured data exchange between client and server

Stripe MCP Architecture

The Stripe MCP server implements a multi-layered architecture optimized for payment operations:

stripe-mcp/
├── src/
│   ├── auth/
│   │   ├── api-key-manager.ts       # API key management
│   │   ├── webhook-validator.ts     # Webhook signature validation
│   │   └── permission-manager.ts    # Operation permission controls
│   ├── services/
│   │   ├── payment-service.ts       # Payment operations
│   │   ├── customer-service.ts      # Customer operations
│   │   ├── subscription-service.ts  # Subscription operations
│   │   └── refund-service.ts        # Refund operations
│   ├── tools/
│   │   ├── payment-tools.ts         # Payment processing tools
│   │   ├── customer-tools.ts        # Customer management tools
│   │   ├── subscription-tools.ts    # Subscription management tools
│   │   └── analytics-tools.ts       # Payment analytics tools
│   ├── resources/
│   │   ├── account-resources.ts     # Account information resources
│   │   └── balance-resources.ts     # Account balance resources
│   └── server.ts                    # MCP server implementation
├── config/
│   └── stripe-config.ts             # Configuration schema
└── package.json                     # Dependencies and scripts

The core technical components include:

  1. API Client Manager: Handles authenticated Stripe API communication
  2. Request Validator: Validates and sanitizes incoming requests
  3. Error Handler: Transforms Stripe API errors into user-friendly messages
  4. Tool Implementations: Translates MCP commands to Stripe API calls
  5. Webhook Processor: Handles asynchronous payment event notifications

Setup and Installation

Prerequisites

To implement Stripe MCP, ensure you have:

  1. Node.js 16+ environment
  2. Stripe account with API keys
  3. Basic understanding of Stripe's payment flows
  4. An MCP-compatible client (e.g., Claude Desktop, Cursor, VS Code)

Authentication Configuration

Before installation, obtain the required Stripe API credentials:

  1. Create or access your Stripe account at https://dashboard.stripe.com (opens in a new tab)
  2. Navigate to Developers > API keys
  3. Copy your "Secret key" (starts with sk_)
  4. For webhook validation, note your webhook signing secret (starts with whsec_)

Installation Methods

Option 1: Using npm

npm install -g stripe-mcp

Option 2: Using Smithery

npx -y @smithery/cli install stripe-mcp --client claude

Option 3: Manual Installation from Source

git clone https://github.com/modelcontextprotocol/servers.git
cd servers/src/stripe
npm install
npm run build

Configuration

The Stripe MCP server requires specific configuration parameters:

  1. API Credentials:

    • STRIPE_API_KEY: Your Stripe secret key
    • STRIPE_WEBHOOK_SECRET: Webhook signing secret (optional)
    • STRIPE_API_VERSION: Stripe API version to target
  2. Security Controls:

    • STRIPE_ALLOWED_OPERATIONS: Comma-separated list of allowed operations
    • STRIPE_MAX_AMOUNT: Maximum transaction amount allowed
    • STRIPE_VERIFICATION_REQUIRED: Require additional verification for high-value transactions
  3. Operational Settings:

    • STRIPE_CURRENCY: Default currency for payments
    • STRIPE_REQUEST_TIMEOUT: API request timeout in milliseconds
    • STRIPE_IDEMPOTENCY_ENABLED: Enable idempotency keys for requests

Example configuration in stripe-config.json:

{
  "api": {
    "key": "sk_test_abcdefghijklmnopqrstuvwxyz",
    "webhookSecret": "whsec_abcdefghijklmnopqrstuvwxyz",
    "version": "2023-10-16",
    "timeout": 30000
  },
  "security": {
    "allowedOperations": ["payments", "customers", "subscriptions"],
    "maxAmount": 10000,
    "verificationRequired": true
  },
  "defaults": {
    "currency": "usd",
    "idempotencyEnabled": true,
    "autoCapture": true
  }
}

Integration with MCP Clients

Claude Desktop Integration

To integrate with Claude Desktop, edit the configuration file:

  • macOS: ~/Library/Application\ Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json

Add the following configuration:

{
  "mcpServers": {
    "stripe": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-stripe"],
      "env": {
        "STRIPE_API_KEY": "sk_test_abcdefghijklmnopqrstuvwxyz",
        "STRIPE_CURRENCY": "usd",
        "STRIPE_ALLOWED_OPERATIONS": "payments,customers,subscriptions"
      }
    }
  }
}

VS Code Integration

For VS Code with GitHub Copilot, add to settings.json:

{
  "github.copilot.chat.mcpServers": [
    {
      "name": "stripe",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-stripe"],
      "env": {
        "STRIPE_API_KEY": "sk_test_abcdefghijklmnopqrstuvwxyz",
        "STRIPE_CURRENCY": "usd"
      }
    }
  ]
}

Core Functionality and Technical Usage

Available Tools

The Stripe MCP server exposes several specialized tools for payment processing:

1. Payment Operations

  • stripe_create_payment: Creates a payment intent

    interface CreatePaymentOptions {
      amount: number;  // Amount in smallest currency unit (cents for USD)
      currency?: string;  // 3-letter ISO currency code
      customerId?: string;  // Stripe customer ID
      paymentMethodId?: string;  // Stripe payment method ID
      description?: string;  // Payment description
      metadata?: Record<string, string>;  // Custom metadata
      receiptEmail?: string;  // Email for receipt
      statementDescriptor?: string;  // Statement descriptor (max 22 chars)
      capture?: boolean;  // Auto-capture the payment
    }
  • stripe_confirm_payment: Confirms a payment intent

    interface ConfirmPaymentOptions {
      paymentIntentId: string;  // Stripe payment intent ID
      paymentMethodId?: string;  // Optional payment method to use
      returnUrl?: string;  // URL for redirect after 3D Secure
    }
  • stripe_cancel_payment: Cancels a payment intent

    interface CancelPaymentOptions {
      paymentIntentId: string;  // Stripe payment intent ID
      cancellationReason?: 'duplicate' | 'fraudulent' | 'requested_by_customer' | 'abandoned';
    }

2. Customer Operations

  • stripe_create_customer: Creates a customer

    interface CreateCustomerOptions {
      email?: string;
      name?: string;
      phone?: string;
      description?: string;
      address?: {
        line1?: string;
        line2?: string;
        city?: string;
        state?: string;
        postal_code?: string;
        country?: string;
      };
      metadata?: Record<string, string>;
      paymentMethodId?: string;  // Attach a payment method
    }
  • stripe_update_customer: Updates a customer

    interface UpdateCustomerOptions {
      customerId: string;
      email?: string;
      name?: string;
      phone?: string;
      description?: string;
      address?: {
        line1?: string;
        line2?: string;
        city?: string;
        state?: string;
        postal_code?: string;
        country?: string;
      };
      metadata?: Record<string, string>;
      defaultPaymentMethodId?: string;
    }

3. Subscription Operations

  • stripe_create_subscription: Creates a subscription

    interface CreateSubscriptionOptions {
      customerId: string;
      priceId: string;  // Stripe price ID
      quantity?: number;
      trialPeriodDays?: number;
      metadata?: Record<string, string>;
      couponId?: string;
      paymentBehavior?: 'default_incomplete' | 'allow_incomplete' | 'error_if_incomplete' | 'pending_if_incomplete';
    }
  • stripe_cancel_subscription: Cancels a subscription

    interface CancelSubscriptionOptions {
      subscriptionId: string;
      cancelAtPeriodEnd?: boolean;  // End at billing period or immediately
      proration?: boolean;  // Prorate charges
      invoice?: boolean;  // Create invoice for remaining time
    }

4. Analytics Operations

  • stripe_list_payments: Retrieves payment history

    interface ListPaymentsOptions {
      limit?: number;
      startingAfter?: string;
      endingBefore?: string;
      created?: {
        gt?: number;  // Unix timestamp
        gte?: number;
        lt?: number;
        lte?: number;
      };
      customerId?: string;
      status?: 'succeeded' | 'pending' | 'canceled';
    }
  • stripe_get_balance: Retrieves account balance

    interface GetBalanceOptions {
      detailed?: boolean;  // Include pending transactions
    }

Technical Usage Patterns

Complete Payment Flow

// 1. Create a customer
const customer = await tools.stripe_create_customer({
  email: "customer@example.com",
  name: "John Doe",
  phone: "+15555555555",
  description: "New customer from MCP integration"
});
 
// 2. Create a payment intent
const paymentIntent = await tools.stripe_create_payment({
  amount: 2500, // $25.00
  currency: "usd",
  customerId: customer.id,
  description: "Purchase of premium service",
  metadata: {
    orderId: "order_12345",
    product: "premium-subscription"
  },
  receiptEmail: customer.email,
  capture: false // For manual capture later
});
 
// 3. Attach payment method to customer (assuming we have a payment method ID)
const paymentMethodId = "pm_card_visa"; // Example test payment method
await tools.stripe_attach_payment_method({
  customerId: customer.id,
  paymentMethodId: paymentMethodId,
  setAsDefault: true
});
 
// 4. Confirm the payment intent with the payment method
const confirmedPayment = await tools.stripe_confirm_payment({
  paymentIntentId: paymentIntent.id,
  paymentMethodId: paymentMethodId
});
 
// 5. Check payment status
if (confirmedPayment.status === 'requires_action') {
  console.log(`3D Secure URL: ${confirmedPayment.next_action.redirect_to_url.url}`);
} else if (confirmedPayment.status === 'succeeded') {
  console.log(`Payment successful. Transaction ID: ${confirmedPayment.id}`);
} else if (confirmedPayment.status === 'requires_capture') {
  // 6. Capture the payment if it's authorized but not captured
  const capturedPayment = await tools.stripe_capture_payment({
    paymentIntentId: confirmedPayment.id,
    amountToCapture: confirmedPayment.amount // Capture full amount
  });
  
  console.log(`Payment captured. Transaction ID: ${capturedPayment.id}`);
}

Subscription Management

// 1. Create a customer
const customer = await tools.stripe_create_customer({
  email: "subscriber@example.com",
  name: "Jane Doe",
  paymentMethodId: "pm_card_visa" // Example test payment method
});
 
// 2. Create a subscription
const subscription = await tools.stripe_create_subscription({
  customerId: customer.id,
  priceId: "price_1234567890", // Example price ID for a subscription plan
  trialPeriodDays: 14,
  metadata: {
    referralSource: "mcp_demo",
    campaignId: "spring_2023"
  }
});
 
console.log(`Subscription created. Status: ${subscription.status}`);
console.log(`Trial ends: ${new Date(subscription.trial_end * 1000)}`);
console.log(`Current period ends: ${new Date(subscription.current_period_end * 1000)}`);
 
// 3. After some time, update the subscription (e.g., change quantity)
const updatedSubscription = await tools.stripe_update_subscription({
  subscriptionId: subscription.id,
  quantity: 2,
  proration: true
});
 
console.log(`Subscription updated. New amount: ${updatedSubscription.items.data[0].plan.amount * updatedSubscription.items.data[0].quantity}`);
 
// 4. Eventually, cancel the subscription at period end
const canceledSubscription = await tools.stripe_cancel_subscription({
  subscriptionId: subscription.id,
  cancelAtPeriodEnd: true
});
 
console.log(`Subscription will be canceled on: ${new Date(canceledSubscription.cancel_at * 1000)}`);

Advanced Implementation Considerations

Secure API Key Management

Stripe MCP implements robust key security measures:

class ApiKeyManager {
  private apiKey: string;
  private readonly keyPattern = /^(sk|pk|rk)_(test|live)_[a-zA-Z0-9]{24,}$/;
  
  constructor(apiKey: string) {
    if (!this.validateApiKey(apiKey)) {
      throw new Error("Invalid Stripe API key format");
    }
    
    this.apiKey = apiKey;
  }
  
  private validateApiKey(key: string): boolean {
    if (!this.keyPattern.test(key)) {
      return false;
    }
    
    // Check key type for specific operations
    const keyType = key.substring(0, 2);
    if (keyType === 'pk') {
      console.warn("Using publishable key has limited capabilities");
    } else if (keyType === 'sk') {
      // Verify if using test or live key
      const envType = key.substring(3, 7);
      if (envType === 'live') {
        console.warn("Using live key - real charges will be made");
      }
    }
    
    return true;
  }
  
  getAuthHeader(): Record<string, string> {
    return {
      Authorization: `Bearer ${this.apiKey}`
    };
  }
}

Idempotency Implementation

To prevent duplicate payment transactions:

class IdempotencyManager {
  private readonly idempotencyKeyPrefix = 'mcp_stripe';
  
  generateIdempotencyKey(operation: string, uniqueIdentifier: string): string {
    const timestamp = new Date().toISOString();
    const rawKey = `${this.idempotencyKeyPrefix}_${operation}_${uniqueIdentifier}_${timestamp}`;
    
    // Create a deterministic hash for the operation
    return crypto
      .createHash('sha256')
      .update(rawKey)
      .digest('hex');
  }
  
  getIdempotencyHeader(operation: string, identifier: string): Record<string, string> {
    return {
      'Idempotency-Key': this.generateIdempotencyKey(operation, identifier)
    };
  }
}

Webhook Integration for Asynchronous Events

For handling payment status updates:

class WebhookHandler {
  private readonly webhookSecret: string;
  
  constructor(webhookSecret: string) {
    this.webhookSecret = webhookSecret;
  }
  
  verifySignature(body: string, signature: string): boolean {
    try {
      const event = Stripe.webhooks.constructEvent(
        body,
        signature,
        this.webhookSecret
      );
      return true;
    } catch (err) {
      console.error(`Webhook signature verification failed: ${err.message}`);
      return false;
    }
  }
  
  async handleWebhook(event: Stripe.Event): Promise<void> {
    // Process different event types
    switch (event.type) {
      case 'payment_intent.succeeded':
        await this.handlePaymentSucceeded(event.data.object);
        break;
      case 'payment_intent.payment_failed':
        await this.handlePaymentFailed(event.data.object);
        break;
      case 'customer.subscription.created':
        await this.handleSubscriptionCreated(event.data.object);
        break;
      // Handle more event types...
    }
  }
  
  // Implement specific event handlers...
}

Troubleshooting Common Technical Issues

API Authentication Problems

If experiencing authentication issues:

async function diagnoseApiConnection(): Promise<DiagnosticResult> {
  try {
    // Try a simple API call that doesn't modify data
    const response = await axios.get('https://api.stripe.com/v1/account', {
      headers: {
        Authorization: `Bearer ${process.env.STRIPE_API_KEY}`
      }
    });
    
    return {
      success: true,
      apiVersion: response.headers['stripe-version'],
      accountType: response.data.business_type,
      message: "API connection successful"
    };
  } catch (error) {
    // Parse Stripe error
    if (error.response) {
      const statusCode = error.response.status;
      const errorType = error.response.data?.error?.type;
      const errorMessage = error.response.data?.error?.message;
      
      if (statusCode === 401) {
        return {
          success: false,
          message: "Authentication failed: Invalid API key",
          details: errorMessage
        };
      } else if (errorType === 'invalid_request_error') {
        return {
          success: false,
          message: "Invalid request error",
          details: errorMessage
        };
      } else {
        return {
          success: false,
          message: `API error (${statusCode})`,
          details: errorMessage
        };
      }
    }
    
    return {
      success: false,
      message: "Connection error",
      details: error.message
    };
  }
}

Payment Failure Analysis

For debugging payment rejections:

function analyzePaymentFailure(error: Stripe.StripeError): PaymentFailureAnalysis {
  const declineCode = error.decline_code;
  const errorCode = error.code;
  const errorType = error.type;
  
  // Common decline codes and their user-friendly explanations
  const declineReasons = {
    'insufficient_funds': "The customer's card has insufficient funds to complete the purchase.",
    'lost_card': "The card has been reported lost.",
    'stolen_card': "The card has been reported stolen.",
    'expired_card': "The card has expired.",
    'incorrect_cvc': "The CVC number is incorrect.",
    'processing_error': "An error occurred while processing the card.",
    'incorrect_number': "The card number is incorrect."
  };
  
  // Determine if retry might help
  const retryableErrors = [
    'processing_error', 
    'rate_limit_error',
    'api_connection_error'
  ];
  
  // Determine recommended action
  let recommendedAction = '';
  if (retryableErrors.includes(errorType)) {
    recommendedAction = "Retry the payment after a brief delay.";
  } else if (declineCode === 'insufficient_funds') {
    recommendedAction = "Ask the customer to use a different payment method.";
  } else if (declineCode === 'expired_card' || declineCode === 'incorrect_number' || declineCode === 'incorrect_cvc') {
    recommendedAction = "Ask the customer to check their card details.";
  } else if (errorType === 'card_error') {
    recommendedAction = "The card was declined. Try a different payment method.";
  } else {
    recommendedAction = "Contact support for assistance.";
  }
  
  return {
    declineCode,
    userFriendlyReason: declineReasons[declineCode] || "The payment was declined.",
    isRetryable: retryableErrors.includes(errorType),
    recommendedAction,
    rawError: error.message
  };
}

Conclusion

Stripe MCP servers represent a powerful technical bridge between conversational AI and secure payment processing infrastructure. By implementing the Model Context Protocol with Stripe's comprehensive API ecosystem, these servers enable AI assistants to manage financial transactions, handle customer data, process subscriptions, and provide valuable payment insights—all while maintaining strict security controls and PCI compliance.

This implementation establishes a foundation for building secure, scalable payment operations that can be triggered through natural language interaction. As both MCP and Stripe's APIs continue to evolve, we can anticipate further advancements in security features, payment capabilities, and integration options.

For developers seeking to extend their AI systems with payment processing capabilities, Stripe MCP offers a standardized, secure approach that abstracts the complexity of payment APIs while providing AI assistants with powerful tools to execute and manage transactions on behalf of businesses. By following the technical patterns outlined in this article, developers can quickly build sophisticated, AI-powered financial operation systems that leverage the security and reliability of Stripe's battle-tested payment infrastructure.