MCP (Model Context Protocol) payment transport helpers.
Provides constants and helper functions for embedding MPP payment flows
in JSON-RPC messages. Where MPP.Plug handles HTTP 402 challenges via
headers, this module handles the equivalent over MCP's _meta convention.
Constants
Five constants defined by the MPP transport spec for MCP:
payment_required_code/0— JSON-RPC error code-32042verification_failed_code/0— JSON-RPC error code-32043credential_meta_key/0—"org.paymentauth/credential"payment_required_meta_key/0—"org.paymentauth/payment-required"receipt_meta_key/0—"org.paymentauth/receipt"
Server Helpers
Build JSON-RPC error responses and extract/attach payment data:
extract_credential/1— pull credential fromparams._metapayment_required_error/1— build-32042error with challengesverification_failed_error/2— build-32043error with problem detailsattach_receipt/3— add receipt + challengeId toresult._meta
Client Helpers
Detect payment-required errors and manage credentials:
payment_required?/1— check if error is-32042extract_challenges/1— parse challenges from error dataattach_credential/2— insert credential intoparams._meta
API Functions
| Function | Arity | Description | Param Kinds |
|---|---|---|---|
attach_credential | 2 | Attach a payment credential to JSON-RPC request params via _meta. | params: value, credential: value |
extract_challenges | 1 | Extract and parse payment challenges from a JSON-RPC error map. | error: value |
payment_required? | 1 | Check whether a JSON-RPC error map indicates payment is required. | error: value |
attach_receipt | 3 | Attach a payment receipt to a JSON-RPC result map via _meta. | result: value, receipt: value, challenge_id: value |
verification_failed_error | 2 | Build a JSON-RPC error map for verification failed (-32043) with problem details. | challenges: value, problem: value |
payment_required_error | 1 | Build a JSON-RPC error map for payment required (-32042) with one or more challenges. | challenges: value |
extract_credential | 1 | Extract a payment credential from JSON-RPC request params _meta. | params: value |
receipt_meta_key | 0 | Metadata key for receipts in result._meta. | - |
payment_required_meta_key | 0 | Metadata key for payment-required results in result._meta. | - |
credential_meta_key | 0 | Metadata key for credentials in params._meta. | - |
verification_failed_code | 0 | JSON-RPC error code for verification failed (-32043). | - |
payment_required_code | 0 | JSON-RPC error code for payment required (-32042). | - |
Summary
Functions
Attach a payment credential to JSON-RPC request params via _meta.
Attach a payment receipt to a JSON-RPC result map via _meta.
Metadata key for credentials in params._meta.
Extract and parse payment challenges from a JSON-RPC error map.
Extract a payment credential from JSON-RPC request params _meta.
Check whether a JSON-RPC error map indicates payment is required.
JSON-RPC error code for payment required (-32042).
Build a JSON-RPC error map for payment required (-32042) with one or more challenges.
Metadata key for payment-required results in result._meta.
Metadata key for receipts in result._meta.
JSON-RPC error code for verification failed (-32043).
Build a JSON-RPC error map for verification failed (-32043) with problem details.
Functions
@spec attach_credential(map(), MPP.Credential.t()) :: map()
Attach a payment credential to JSON-RPC request params via _meta.
Parameters
params- JSON-RPC request params map (value)credential- AnMPP.Credential.t()struct (value)
Returns
Params map with _meta containing the credential (map)
Composes With
extract_credentialextract_challenges
# descripex:contract
%{
params: %{
params: %{description: "JSON-RPC request params map", kind: :value},
credential: %{description: "An `MPP.Credential.t()` struct", kind: :value}
},
returns: %{
type: :map,
description: "Params map with `_meta` containing the credential"
},
composes_with: [:extract_credential, :extract_challenges]
}
@spec attach_receipt(map(), MPP.Receipt.t(), String.t()) :: map()
Attach a payment receipt to a JSON-RPC result map via _meta.
Parameters
result- JSON-RPC result map (value)receipt- AnMPP.Receipt.t()struct (value)challenge_id- The challenge ID this receipt fulfills (value)
Returns
Result map with _meta containing the receipt and challengeId (map)
Composes With
extract_credentialpayment_required_error
# descripex:contract
%{
params: %{
result: %{description: "JSON-RPC result map", kind: :value},
challenge_id: %{
description: "The challenge ID this receipt fulfills",
kind: :value
},
receipt: %{description: "An `MPP.Receipt.t()` struct", kind: :value}
},
returns: %{
type: :map,
description: "Result map with `_meta` containing the receipt and `challengeId`"
},
composes_with: [:extract_credential, :payment_required_error]
}
@spec credential_meta_key() :: String.t()
Metadata key for credentials in params._meta.
Returns
Key "org.paymentauth/credential" (string)
# descripex:contract
%{
returns: %{type: :string, description: "Key `\"org.paymentauth/credential\"`"}
}
@spec extract_challenges(map()) :: {:ok, [MPP.Challenge.t()]} | {:error, :no_challenges | :invalid_challenge}
@spec extract_challenges(map()) :: {:error, :no_challenges}
@spec extract_challenges(map()) :: {:error, :invalid_challenge}
@spec extract_challenges(map()) :: {:ok, [MPP.Challenge.t()]} | {:error, :no_challenges | :invalid_challenge}
@spec extract_challenges(map()) :: {:ok, [MPP.Challenge.t()]} | {:error, :no_challenges | :invalid_challenge}
@spec extract_challenges(map()) :: {:error, :no_challenges}
Extract and parse payment challenges from a JSON-RPC error map.
Parameters
error- JSON-RPC error map withdata.challenges(value)
Returns
{:ok, [challenge]} or {:error, :no_challenges | :invalid_challenge} (tagged_tuple)
Errors
:no_challenges:invalid_challenge
Composes With
payment_required?payment_required_error
# descripex:contract
%{
params: %{
error: %{
description: "JSON-RPC error map with `data.challenges`",
kind: :value
}
},
errors: [:no_challenges, :invalid_challenge],
returns: %{
type: :tagged_tuple,
description: "`{:ok, [challenge]}` or `{:error, :no_challenges | :invalid_challenge}`"
},
composes_with: [:payment_required?, :payment_required_error]
}
@spec extract_credential(map()) :: {:ok, MPP.Credential.t()} | {:error, :no_credential | :invalid_credential | :invalid_challenge}
@spec extract_credential(map()) :: {:error, :invalid_credential}
@spec extract_credential(map()) :: {:error, :no_credential}
Extract a payment credential from JSON-RPC request params _meta.
Parameters
params- JSON-RPC request params map with optional_metacontaining a credential (value)
Returns
{:ok, credential} or {:error, :no_credential | :invalid_credential | :invalid_challenge} (tagged_tuple)
Errors
:no_credential:invalid_credential:invalid_challenge
Composes With
attach_credentialattach_receipt
# descripex:contract
%{
params: %{
params: %{
description: "JSON-RPC request params map with optional `_meta` containing a credential",
kind: :value
}
},
errors: [:no_credential, :invalid_credential, :invalid_challenge],
returns: %{
type: :tagged_tuple,
description: "`{:ok, credential}` or `{:error, :no_credential | :invalid_credential | :invalid_challenge}`"
},
composes_with: [:attach_credential, :attach_receipt]
}
@spec payment_required?(map()) :: boolean()
@spec payment_required?(map()) :: boolean()
@spec payment_required?(map()) :: boolean()
@spec payment_required?(map()) :: false
Check whether a JSON-RPC error map indicates payment is required.
Parameters
error- JSON-RPC error map withcodefield (value)
Returns
true if error code is -32042 (boolean)
# descripex:contract
%{
params: %{
error: %{description: "JSON-RPC error map with `code` field", kind: :value}
},
returns: %{type: :boolean, description: "`true` if error code is `-32042`"}
}
@spec payment_required_code() :: integer()
JSON-RPC error code for payment required (-32042).
Returns
Error code -32042 (integer)
# descripex:contract
%{returns: %{type: :integer, description: "Error code `-32042`"}}
@spec payment_required_error(MPP.Challenge.t() | [MPP.Challenge.t()]) :: map()
@spec payment_required_error([MPP.Challenge.t()]) :: map()
Build a JSON-RPC error map for payment required (-32042) with one or more challenges.
Parameters
challenges- A singleMPP.Challengestruct or a list of challenges (value)
Returns
JSON-RPC error map with code, message, and data containing httpStatus, challenges, and problem (map)
Composes With
extract_challengesverification_failed_error
# descripex:contract
%{
params: %{
challenges: %{
description: "A single `MPP.Challenge` struct or a list of challenges",
kind: :value
}
},
returns: %{
type: :map,
description: "JSON-RPC error map with `code`, `message`, and `data` containing `httpStatus`, `challenges`, and `problem`"
},
composes_with: [:extract_challenges, :verification_failed_error]
}
@spec payment_required_meta_key() :: String.t()
Metadata key for payment-required results in result._meta.
Returns
Key "org.paymentauth/payment-required" (string)
# descripex:contract
%{
returns: %{
type: :string,
description: "Key `\"org.paymentauth/payment-required\"`"
}
}
@spec receipt_meta_key() :: String.t()
Metadata key for receipts in result._meta.
Returns
Key "org.paymentauth/receipt" (string)
# descripex:contract
%{returns: %{type: :string, description: "Key `\"org.paymentauth/receipt\"`"}}
@spec verification_failed_code() :: integer()
JSON-RPC error code for verification failed (-32043).
Returns
Error code -32043 (integer)
# descripex:contract
%{returns: %{type: :integer, description: "Error code `-32043`"}}
@spec verification_failed_error( MPP.Challenge.t() | [MPP.Challenge.t()], MPP.Errors.t() ) :: map()
@spec verification_failed_error([MPP.Challenge.t()], MPP.Errors.t()) :: map()
Build a JSON-RPC error map for verification failed (-32043) with problem details.
Parameters
challenges- A singleMPP.Challengestruct or a list of challenges (value)problem- AnMPP.Errors.t()struct with RFC 9457 problem details (value)
Returns
JSON-RPC error map with code, message, and data including problem details (map)
Composes With
payment_required_errorextract_challenges
# descripex:contract
%{
params: %{
problem: %{
description: "An `MPP.Errors.t()` struct with RFC 9457 problem details",
kind: :value
},
challenges: %{
description: "A single `MPP.Challenge` struct or a list of challenges",
kind: :value
}
},
returns: %{
type: :map,
description: "JSON-RPC error map with `code`, `message`, and `data` including problem details"
},
composes_with: [:payment_required_error, :extract_challenges]
}