Skip to main content
Glama

send_onchain

Send Bitcoin payments directly on-chain to any Bitcoin address using the Strike wallet. Specify the recipient address and amount in satoshis to complete transactions.

Instructions

Send an on-chain Bitcoin payment to a Bitcoin address. Currently only available with Strike wallet.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
addressYesBitcoin address to send to (e.g., bc1q...)
amount_satsYesAmount to send in satoshis

Implementation Reference

  • The main handler function for the `send_onchain` MCP tool. It validates inputs, checks wallet compatibility, performs budget authorization, delegates the actual transaction to the wallet (LND or Strike), records the spend, and formats the result.
    async def send_onchain(
        address: str,
        amount_sats: int,
        wallet: "Union[StrikeWallet, LndWallet, None]" = None,
        budget_service: "BudgetService | None" = None,
    ) -> str:
        """
        Send an on-chain Bitcoin payment to a Bitcoin address.
    
        Supports Strike and LND wallets. The payment is sent from your
        wallet balance.
    
        Args:
            address: Bitcoin address to send to (e.g., bc1q...)
            amount_sats: Amount to send in satoshis
            wallet: Strike or LND wallet instance
            budget_service: BudgetService for spending limits
    
        Returns:
            JSON with payment result including transaction details
        """
        if not address or not address.strip():
            return json.dumps({
                "success": False,
                "error": "Bitcoin address is required"
            })
    
        if amount_sats <= 0:
            return json.dumps({
                "success": False,
                "error": "Amount must be greater than 0 sats"
            })
    
        if not wallet:
            return json.dumps({
                "success": False,
                "error": "Wallet not configured. Set STRIKE_API_KEY or LND_REST_HOST+LND_MACAROON_HEX for on-chain payments."
            })
    
        # Verify it's a supported wallet type
        from ..strike_wallet import StrikeWallet
        from ..lnd_wallet import LndWallet
        if not isinstance(wallet, (StrikeWallet, LndWallet)):
            provider_name = type(wallet).__name__.replace("Wallet", "")
            return json.dumps({
                "success": False,
                "error": f"{provider_name} does not support on-chain payments. Use Strike or LND wallet.",
                "errorCode": "NOT_SUPPORTED",
                "hint": "Set STRIKE_API_KEY or LND_REST_HOST+LND_MACAROON_HEX for on-chain payments."
            })
    
        # Check budget if configured
        if budget_service:
            try:
                budget_result = await budget_service.check_approval_level(amount_sats)
                from ..config import ApprovalLevel
                if budget_result.level == ApprovalLevel.DENY:
                    return json.dumps({
                        "success": False,
                        "error": f"Budget check failed: {budget_result.denial_reason}",
                    })
            except Exception as e:
                logger.warning(f"Budget check failed: {e}")
    
        try:
            result = await wallet.send_onchain(address.strip(), amount_sats)
    
            if not result.success:
                return json.dumps({
                    "success": False,
                    "error": result.error_message,
                    "errorCode": result.error_code,
                })
    
            # Record spend if budget service available
            if budget_service:
                try:
                    total_sats = amount_sats + (result.fee_sats or 0)
                    budget_service.record_spend(total_sats)
                    budget_service.record_payment_time()
                except Exception:
                    pass
    
            provider_name = "LND" if isinstance(wallet, LndWallet) else "Strike"
    
            if result.state == "COMPLETED":
                message = f"On-chain payment of {amount_sats} sats sent to {address}"
            else:
                message = f"On-chain payment initiated (status: {result.state})"
    
            return json.dumps({
                "success": True,
                "provider": provider_name,
                "payment": {
                    "id": result.payment_id,
                    "txId": result.txid,
                    "state": result.state,
                    "amountSats": result.amount_sats,
                    "feeSats": result.fee_sats,
                },
                "message": message,
            }, indent=2)
    
        except Exception as e:
            logger.exception("Error sending on-chain payment")
            return json.dumps({
                "success": False,
                "error": sanitize_error(str(e))
            })
Behavior2/5

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

No annotations are provided, so the description carries full burden. It states the action is a payment but does not disclose behavioral traits such as transaction irreversibility, network fees, confirmation times, authentication requirements, or rate limits. The Strike wallet mention adds some context but is insufficient for a mutation tool with no annotation coverage.

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 a single, efficient sentence that directly states the tool's function. It is appropriately sized and front-loaded, with no wasted words, though it could be slightly more structured by separating functional details from limitations.

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 the complexity of a financial transaction tool with no annotations and no output schema, the description is incomplete. It lacks critical information such as return values, error conditions, security implications, or how it differs from other payment-related sibling tools, making it inadequate for safe and effective use.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters ('address' and 'amount_sats') adequately. The description does not add any meaning beyond what the schema provides, such as format examples or constraints, but the high coverage justifies the baseline score of 3.

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

Purpose4/5

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

The description clearly states the action ('send') and resource ('on-chain Bitcoin payment to a Bitcoin address'), making the purpose evident. However, it does not explicitly differentiate from sibling tools like 'pay_invoice' or 'pay_l402_challenge', which might also involve payments but through different mechanisms, so it lacks sibling distinction.

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?

The description provides no guidance on when to use this tool versus alternatives. It mentions 'Currently only available with Strike wallet,' which is a limitation but not a usage guideline. There is no indication of prerequisites, when-not-to-use scenarios, or comparisons to sibling tools like 'pay_invoice' for off-chain payments.

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/refined-element/lightning-enable-mcp'

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