Skip to main content
Glama

create_coupon

Generate discount coupons for Stream by specifying name, value, and type (percentage or fixed amount with currency). Configure active status for promotional campaigns.

Instructions

Create a new discount coupon on Stream.

Set is_percentage to True for percentage discount, False for fixed amount. For fixed coupons, currency is required (e.g. SAR, USD).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYes
discount_valueYes
is_percentageNo
currencyNo
is_activeNo

Implementation Reference

  • The create_coupon handler function decorated with @mcp.tool. It accepts parameters (name, discount_value, is_percentage, currency, is_active), creates a CreateCouponRequest body, gets an API client, and makes a POST request to create the coupon.
    async def create_coupon(
        name: str,
        discount_value: float,
        is_percentage: bool = False,
        currency: str | None = None,
        is_active: bool = True,
        ctx: Context = None,  # type: ignore[assignment]
    ) -> dict[str, Any]:
        """Create a new discount coupon on Stream.
    
        Set *is_percentage* to True for percentage discount, False for fixed amount.
        For fixed coupons, *currency* is required (e.g. SAR, USD).
        """
        body = CreateCouponRequest(
            name=name,
            discount_value=discount_value,
            is_percentage=is_percentage,
            currency=currency,
            is_active=is_active,
        )
        client = await get_client(ctx)
        try:
            return await client.post(_BASE, body.model_dump(exclude_none=True))
        except StreamAPIError as exc:
            return _err(exc)
  • Pydantic BaseModel for validating create_coupon request parameters. Defines fields for name, discount_value, currency, is_percentage, and is_active with proper constraints and descriptions.
    class CreateCouponRequest(BaseModel):
        """Request body for creating a new coupon."""
    
        name: str = Field(..., min_length=1, max_length=80, description="Coupon display name.")
        discount_value: float = Field(..., ge=0, description="Discount value (amount or percentage).")
        currency: str | None = Field(
            default=None,
            description="ISO-4217 currency code. Required when is_percentage is false. Must be null when is_percentage is true.",
        )
        is_percentage: bool = Field(default=False, description="True for percentage discount, false for fixed amount.")
        is_active: bool = Field(default=True, description="Whether the coupon is active.")
  • The register function that defines and registers the create_coupon tool using the @mcp.tool decorator. This function is called during MCP server initialization to register all coupon-related tools.
    def register(mcp: FastMCP) -> None:
        """Register all coupon tools on *mcp*."""
    
        @mcp.tool
        async def create_coupon(
            name: str,
            discount_value: float,
            is_percentage: bool = False,
            currency: str | None = None,
            is_active: bool = True,
            ctx: Context = None,  # type: ignore[assignment]
        ) -> dict[str, Any]:
            """Create a new discount coupon on Stream.
    
            Set *is_percentage* to True for percentage discount, False for fixed amount.
            For fixed coupons, *currency* is required (e.g. SAR, USD).
            """
            body = CreateCouponRequest(
                name=name,
                discount_value=discount_value,
                is_percentage=is_percentage,
                currency=currency,
                is_active=is_active,
            )
            client = await get_client(ctx)
            try:
                return await client.post(_BASE, body.model_dump(exclude_none=True))
            except StreamAPIError as exc:
                return _err(exc)
  • Main registration orchestrator that imports the coupons module and calls coupons.register(mcp) to register all coupon tools including create_coupon.
    def register_all_tools(mcp: FastMCP) -> None:
        """Import every tool / resource module and call its ``register(mcp)``."""
        from stream_mcp.tools import (
            coupons,
            customers,
            docs,
            invoices,
            payment_links,
            payments,
            products,
        )
    
        payment_links.register(mcp)
        customers.register(mcp)
        products.register(mcp)
        payments.register(mcp)
        coupons.register(mcp)
        invoices.register(mcp)
        docs.register(mcp)
  • The get_client helper function used by create_coupon to obtain a StreamClient instance. It handles both local (stdio) and remote (SSE/http) modes by retrieving the client from lifespan context or creating a per-user client from the Bearer token.
    async def get_client(ctx: "Context") -> StreamClient:
        """Return a :class:`StreamClient` for the current request.
    
        Resolution order:
    
        1. **Lifespan client** — used in local / stdio mode where a single
           ``STREAM_API_KEY`` is set as an environment variable.
        2. **Per-user client** — used in remote mode where each user passes
           their own API key as a Bearer token and (optionally) a custom
           base URL via the ``X-Stream-Base-URL`` header.
        """
        # ── 1. Local mode: shared client from server lifespan ─────────────
        shared_client = ctx.lifespan_context.get("client")
        if shared_client is not None:
            return shared_client
    
        # ── 2. Remote mode: per-user client from Bearer token ─────────────
        api_key = current_api_key.get()
        if not api_key:
            raise StreamError(
                "No Stream API key found. "
                "In local mode, set the STREAM_API_KEY env var. "
                "In remote mode, pass your key as a Bearer token in the Authorization header."
            )
    
        base_url = current_base_url.get() or settings.stream_base_url
        cache_key = f"{api_key}::{base_url}"
    
        if cache_key not in _client_cache:
            client = StreamClient(
                api_key=api_key,
                base_url=base_url,
                timeout=settings.stream_timeout,
                max_retries=settings.stream_max_retries,
            )
            await client.__aenter__()
            _client_cache[cache_key] = client
            logger.info(
                "Created cached StreamClient for remote user (key=…%s, base=%s)",
                api_key[-4:], base_url,
            )
    
        return _client_cache[cache_key]

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/streampayments/stream'

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