Skip to main content
Glama

buy_domain

Start the domain purchase process via Stripe checkout. After verifying domain availability and displaying the price, submit registrant details to complete the order. The domain is registered in your name with WHOIS privacy.

Instructions

Start the purchase flow for an available domain via Stripe checkout.

IMPORTANT: Before calling this tool, you MUST first call check_domain to get the price, then clearly show the user the price and get their explicit confirmation before proceeding. Never call buy_domain without the user seeing and approving the price first.

The registrant contact details are required because the domain will be registered in the buyer's name (they become the legal owner). WHOIS privacy is enabled by default, so these details are not publicly visible.

Creates a Stripe checkout session. Returns a checkout URL that the user should open in their browser to complete payment securely via Stripe, plus the order ID for tracking.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
domainYesThe domain to purchase (e.g. "coolstartup.com").
first_nameYesRegistrant's first name.
last_nameYesRegistrant's last name.
emailYesRegistrant's email address.
address1YesRegistrant's street address.
cityYesRegistrant's city.
stateYesRegistrant's state or province.
postal_codeYesRegistrant's postal/zip code.
countryYes2-letter ISO country code (e.g. "US", "GB", "DE").
phoneYesPhone number in format +1.5551234567.
org_nameNoOrganization name (optional, leave empty for individuals).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • MCP tool handler for buy_domain. Accepts domain and registrant contact details, builds payload, POSTs to /buy on backend to create Stripe checkout session.
    async def buy_domain(
        domain: str,
        first_name: str,
        last_name: str,
        email: str,
        address1: str,
        city: str,
        state: str,
        postal_code: str,
        country: str,
        phone: str,
        org_name: str = "",
    ) -> dict:
        """Start the purchase flow for an available domain via Stripe checkout.
    
        IMPORTANT: Before calling this tool, you MUST first call check_domain
        to get the price, then clearly show the user the price and get their
        explicit confirmation before proceeding. Never call buy_domain without
        the user seeing and approving the price first.
    
        The registrant contact details are required because the domain will be
        registered in the buyer's name (they become the legal owner). WHOIS
        privacy is enabled by default, so these details are not publicly visible.
    
        Creates a Stripe checkout session. Returns a checkout URL that the
        user should open in their browser to complete payment securely via
        Stripe, plus the order ID for tracking.
    
        Args:
            domain: The domain to purchase (e.g. "coolstartup.com").
            first_name: Registrant's first name.
            last_name: Registrant's last name.
            email: Registrant's email address.
            address1: Registrant's street address.
            city: Registrant's city.
            state: Registrant's state or province.
            postal_code: Registrant's postal/zip code.
            country: 2-letter ISO country code (e.g. "US", "GB", "DE").
            phone: Phone number in format +1.5551234567.
            org_name: Organization name (optional, leave empty for individuals).
    
        Returns:
            Dict with order_id, checkout_url, price_cents, and price_display.
        """
        payload = {
            "domain": domain,
            "registrant": {
                "first_name": first_name,
                "last_name": last_name,
                "email": email,
                "org_name": org_name,
                "address1": address1,
                "city": city,
                "state": state,
                "postal_code": postal_code,
                "country": country,
                "phone": phone,
            },
        }
        async with httpx.AsyncClient(base_url=BACKEND_URL, timeout=15) as client:
            resp = await client.post("/buy", json=payload)
            if resp.status_code == 400:
                return resp.json()
            resp.raise_for_status()
            return resp.json()
  • Backend FastAPI route /buy that checks availability, gets price, creates order, creates Stripe checkout session, returns order_id and checkout_url.
    async def buy_domain(body: BuyRequest, request: Request):
        """Create a Stripe checkout session and order for a domain purchase."""
        domain = body.domain.strip().lower()
    
        result = await _check_availability(domain)
        if not result["available"]:
            raise HTTPException(status_code=400, detail=f"Domain {domain} is not available")
    
        pool = request.app.state.pool
        opensrs = request.app.state.opensrs
        try:
            wholesale_cents = await _get_price(domain, opensrs)
        except Exception as exc:
            raise HTTPException(status_code=502, detail=f"Price lookup failed: {exc}")
    
        tld = domain.rsplit(".", 1)[-1] if "." in domain else "com"
        retail_cents = calculate_retail_cents(wholesale_cents, tld)
    
        order = await create_order(
            pool,
            domain=domain.rsplit(".", 1)[0] if "." in domain else domain,
            tld=tld,
            amount_cents=retail_cents,
            wholesale_cents=wholesale_cents,
            stripe_session_id=None,
            registrant_contact=body.registrant.model_dump(),
        )
    
        try:
            checkout = await asyncio.to_thread(
                create_checkout_session, domain, retail_cents, order["id"]
            )
        except Exception as exc:
            raise HTTPException(status_code=502, detail=f"Payment setup failed: {exc}")
    
        async with pool.acquire() as conn:
            await conn.execute(
                "UPDATE orders SET stripe_session_id = $1 WHERE id = $2",
                checkout["session_id"],
                order["id"],
            )
    
        return {
            "order_id": order["id"],
            "checkout_url": checkout["checkout_url"],
            "price_cents": retail_cents,
            "price_display": format_price(retail_cents),
        }
  • Pydantic BuyRequest model with domain and RegistrantContact for input validation on the buy endpoint.
    class BuyRequest(BaseModel):
        domain: str
        registrant: RegistrantContact
  • Import statement that triggers registration of buy_domain and buy_domain_crypto tools on the FastMCP instance.
    # Import buy tools so they register on the same mcp instance
    import instadomain.mcp_tools_buy  # noqa: E402, F401
  • Pricing helper calculate_retail_cents used by the buy route to compute retail price from wholesale cost using flat markup or percentage markup.
    def calculate_retail_cents(wholesale_cents: int, tld: str) -> int:
        """Calculate the retail price in cents for a domain.
    
        Standard domains (wholesale at or below the TLD threshold) get a flat
        markup. Premium domains (above the threshold) get a percentage markup.
    
        For unknown TLDs, falls back to .com thresholds and markup.
        """
        threshold = WHOLESALE_THRESHOLDS.get(tld, WHOLESALE_THRESHOLDS["com"])
        markup = STANDARD_MARKUP.get(tld, STANDARD_MARKUP["com"])
    
        if wholesale_cents <= threshold:
            return wholesale_cents + markup
        else:
            return int(wholesale_cents * (1 + PREMIUM_MARKUP_PCT))
    
    
    def format_price(cents: int) -> str:
        """Format a price in cents as a dollar string like '$10.99'."""
        return f"${cents / 100:.2f}"
Behavior4/5

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

Discloses that it creates a Stripe checkout session, returns checkout URL and order ID, explains that registrant details are required for legal ownership, and mentions WHOIS privacy. Lacks explicit statement about charging the user, but checkout session implies payment.

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

Conciseness5/5

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

Well-structured with clear sections: purpose, important prerequisite note, explanatory context, and return value description. Every sentence serves a purpose without being verbose.

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

Completeness5/5

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

Covers prerequisites, legal implications of registrant data, payment flow, and output. Complete for a purchase tool with many parameters and no annotations.

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

Parameters4/5

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

Input schema has 100% coverage, so baseline is 3. Description adds value by explaining that registrant details are needed for ownership and that WHOIS privacy hides them, providing context beyond the schema.

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?

Clearly states the tool starts a purchase flow for a domain via Stripe checkout. Distinguishes from siblings like check_domain and buy_domain_crypto by specifying the payment method and flow.

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

Usage Guidelines5/5

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

Explicitly instructs to call check_domain first, show price to user, get confirmation before proceeding. Provides clear when-to-use and when-not-to-use guidance.

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/nach-dakwale/instadomain-mcp'

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