X402.MCP.Client (X402 v0.6.0)

Copy Markdown View Source

Client half of the x402 MCP transport: pay for tool calls automatically.

call/3 drives an arbitrary tool-call function (any MCP client library, or a plain function in tests) through the x402 detect → sign → retry-once loop:

  1. Perform the tool call. A result that is not payment-required is returned as-is.
  2. Extract the PaymentRequired object from the payment-required tool result (or from a 402/-32042 JSON-RPC error).
  3. Invoke the :on_payment_required hook, which may cancel.
  4. Build and sign a payment via X402.Client.build_payment/3 and retry the tool call once with the payload in request _meta["x402/payment"].
  5. Return the retried result with the decoded settlement receipt from result _meta["x402/payment-response"], when present.

A tool call is never paid twice: at most one payment retry is made, a second payment-required result is returned as-is, and requests that already carry _meta["x402/payment"] are refused.

Example

{:ok, signer} = X402.Signer.LocalKey.new(System.fetch_env!("PAYER_KEY"))

request = %{"name" => "premium_search", "arguments" => %{"query" => "x402"}}

{:ok, %{result: result, payment_response: receipt, paid: true}} =
  X402.MCP.Client.call(request, &MyMCP.call_tool/1,
    signer: signer,
    max_amount: "10000",
    on_payment_required: fn payment_required ->
      IO.inspect(payment_required["accepts"], label: "about to pay")
      :ok
    end
  )

The tool-call function receives the (possibly payment-carrying) request map and may return the tool result map directly, {:ok, result}, or {:error, reason}.

Summary

Types

A tool-call function driven by call/3.

A completed tool call.

Functions

Builds the request _meta map paying for a payment-required response.

Performs a tool call, paying for the tool if it requires payment.

Types

call_error()

@type call_error() ::
  :payment_already_attempted
  | :payment_cancelled
  | :invalid_tool_result
  | {:transport_error, term()}
  | X402.Client.build_error()

call_fun()

@type call_fun() :: (map() -> map() | {:ok, map()} | {:error, term()})

A tool-call function driven by call/3.

response()

@type response() :: %{result: map(), payment_response: map() | nil, paid: boolean()}

A completed tool call.

:result is the final tool result map; :payment_response holds the decoded settlement receipt from _meta["x402/payment-response"] when the server sent one, otherwise nil; :paid tells whether a payment was signed and submitted.

Functions

build_payment_meta(payment_required_or_result, signer, opts \\ [])

(since 0.6.0)
@spec build_payment_meta(map(), X402.Signer.t(), keyword()) ::
  {:ok, %{required(String.t()) => map()}} | {:error, X402.Client.build_error()}

Builds the request _meta map paying for a payment-required response.

Accepts either a decoded PaymentRequired map or the payment-required tool result that carries one, selects and signs a payment option via X402.Client.build_payment/3, and returns the _meta entries to merge into the retried tool-call request. Options are forwarded to X402.Client.build_payment/3.

Use this instead of call/3 when your MCP library exposes request _meta but you want to drive the retry yourself.

call(request, call_fun, opts)

(since 0.6.0)
@spec call(map(), call_fun(), keyword()) :: {:ok, response()} | {:error, call_error()}

Performs a tool call, paying for the tool if it requires payment.

See the module documentation for the full flow. Returns {:ok, response()} with the final tool result, or {:error, reason} when the payment was cancelled, could not be built, or the tool-call function failed.

Options

  • :signer - Required. A struct implementing X402.Signer, used to sign the payment.

  • :network (String.t/0) - Payment selection filter — see X402.Client.select_requirements/2.

  • :scheme (String.t/0) - Payment selection filter — see X402.Client.select_requirements/2.

  • :asset (String.t/0) - Payment selection filter — see X402.Client.select_requirements/2.

  • :max_amount - Maximum amount (atomic units) this client will pay — the budget guard for automated payers. Requirements above it are never selected.

  • :valid_after_buffer (non_neg_integer/0) - Clock-skew buffer for the authorization's validAfter, in seconds. The default value is 60.

  • :on_payment_required - Budget/consent hook invoked with the decoded PaymentRequired map before any payment is signed. Return :cancel to abort with {:error, :payment_cancelled}; any other return value continues. The default value is nil.