Skip to main content
Glama

pay

Send payments to recipients using Pix keys, email, phone, CPF, CNPJ, or IBAN. Processes transactions in cents with multi-provider routing and supports payment memos.

Instructions

Send money to a destination via the best available provider. Amount in cents.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
amountYesAmount in cents. Example: 5000 = R$50.00
currencyNoISO 4217 currency codeBRL
destinationYesRecipient: Pix key, email, phone, CPF, CNPJ, IBAN
destination_typeNoType hint: EMAIL, PHONE, CPF, CNPJ, RANDOM, IBAN
noteNoPayment memo
providerNoForce a specific provider

Implementation Reference

  • Registration and handling logic for the "pay" MCP tool.
    server.tool(
      "pay",
      "Send money to a destination via the best available provider. Amount in cents.",
      PaySchema.shape,
      async (params) => {
        const check = guardrails.checkPay(params);
    
        if (!check.allowed) {
          guardrails.audit({
            timestamp: new Date().toISOString(),
            type: "payment",
            action: "pay",
            tool: "pay",
            amount: params.amount,
            currency: params.currency,
            destination: params.destination,
            status: "blocked",
            reason: check.reason,
          });
          return textResult(`Payment blocked: ${check.reason}`);
        }
    
        // Note: recordSpend is NOT called here because no money moves yet.
        // Spend is recorded when the user confirms and pay is called again,
        // reaching the try block below which calls recordSpend().
        if (check.needs_confirmation) {
          guardrails.audit({
            timestamp: new Date().toISOString(),
            type: "payment",
            action: "pay",
            tool: "pay",
            amount: params.amount,
            currency: params.currency,
            destination: params.destination,
            status: "pending_confirmation",
            reason: check.reason,
          });
    
          const formatted = (params.amount / 100).toFixed(2);
          return textResult(
            `Confirmation required\n\n` +
              `  Amount:  ${params.currency} ${formatted}\n` +
              `  To:      ${params.destination}\n` +
              `  Reason:  ${check.reason}\n\n` +
              `Please confirm with the user before proceeding. ` +
              `Call pay again with the same parameters after approval.`
          );
        }
    
        try {
          const provider = pickProvider(params.currency, undefined, params.provider);
          const result = await provider.pay(params);
    
          guardrails.recordSpend(params.amount);
          guardrails.audit({
            timestamp: new Date().toISOString(),
            type: "payment",
            action: "pay",
            tool: "pay",
            amount: params.amount,
            currency: params.currency,
            provider: provider.name,
            destination: params.destination,
            status: "executed",
          });
    
          return jsonResult({
            success: true,
            message: `Sent ${params.currency} ${(params.amount / 100).toFixed(2)} to ${params.destination} via ${provider.name}`,
            ...result,
          });
        } catch (err) {
          guardrails.audit({
            timestamp: new Date().toISOString(),
            type: "payment",
            action: "pay",
            tool: "pay",
            amount: params.amount,
            currency: params.currency,
            destination: params.destination,
            status: "failed",
            reason: formatError(err),
          });
    
          return textResult(`Payment failed: ${formatError(err)}`);
        }
      }
    );
  • Implementation of the "pay" method within the Woovi provider.
    async pay(req: PayRequest): Promise<PayResult> {
      const correlationID =
        req.correlation_id ?? `junto-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
    
      const raw = await this.request("POST", "/payment", {
        value: req.amount,
        destinationAlias: req.destination,
        destinationAliasType: this.mapDestinationType(req.destination_type),
        correlationID,
        comment: req.note ?? "Payment via Junto",
      });
    
      const data = WooviPaymentResponse.parse(raw);
    
      return {
        id: correlationID,
        status: (data.payment.status as PayResult["status"]) ?? "CREATED",
        provider: this.name,
        amount: req.amount,
        currency: "BRL",
        destination: req.destination,
        timestamp: new Date().toISOString(),
        metadata: { woovi_response: data.payment },
      };
    }
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'best available provider' selection logic but fails to disclose critical financial operation traits: whether the transaction is irreversible (requiring 'refund'), if it requires pre-authorization, rate limits, or failure behaviors.

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 two-sentence structure is appropriately front-loaded with the action verb. While 'Amount in cents' appears redundant given complete schema coverage, it earns its place as critical safety information preventing decimal errors in financial transactions.

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

Completeness3/5

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

Given the high schema coverage, the description meets minimum viability. However, for a high-stakes financial mutation tool lacking annotations and output schema, it omits expected safety context about fund availability checks and transaction finality.

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%, establishing a baseline of 3. The description repeats 'Amount in cents' which appears verbatim in the schema's amount parameter description, adding no new semantic value. It does not clarify parameter interdependencies (e.g., destination_type hinting destination format).

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 core action ('Send money') and target ('destination'), distinguishing it from siblings like 'charge' (receive) and 'refund' (reverse). However, it stops short of explicitly clarifying that this debits funds from the user's account, which would strengthen differentiation from non-financial tools.

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 versus 'charge' or 'refund', nor are prerequisites mentioned (e.g., verifying sufficient balance via the 'balance' tool first). The description lacks 'when-not-to-use' exclusions or alternative recommendations.

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/vrllrv/junto-mcp'

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