MPP.Mcp (mpp v0.12.0)

Copy Markdown View Source

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:

Server Transport Adapter

A full server-side transport: run JSON-RPC requests through payment verification (including the default credential replay dedup shared with MPP.Plug) before invoking your handler:

  • init/1 — build transport config from the same options as MPP.Plug
  • call/3 — verify the request's credential, invoke the handler, attach the receipt (or return a -32042/-32602/-32043 error with challenges)

Server Helpers

Build JSON-RPC error responses and extract/attach payment data:

Client Helpers

Detect payment-required errors and manage credentials:

API Functions

FunctionArityDescriptionParam Kinds
attach_credential2Attach a payment credential to JSON-RPC request params via _meta.params: value, credential: value
extract_challenges1Extract and parse payment challenges from a JSON-RPC error map or full JSON-RPC response.error: value
payment_required?1Check whether a JSON-RPC error map (or full JSON-RPC response) indicates payment is required.error: value
attach_receipt3Attach a payment receipt to a JSON-RPC result map via _meta.result: value, receipt: value, challenge_id: value
verification_failed_error2Build a JSON-RPC error map for verification failed (-32043) with problem details.challenges: value, problem: value
payment_required_error1Build a JSON-RPC error map for payment required (-32042) with one or more challenges.challenges: value
extract_credential1Extract a payment credential from JSON-RPC request params _meta.params: value
call3Run a JSON-RPC request through MPP server-side payment verification before invoking a handler.request: value, config: value, handler: value
init1Build server-side MCP transport configuration from the same endpoint options accepted by MPP.Plug.opts: value
receipt_meta_key0Metadata key for receipts in result._meta.-
payment_required_meta_key0Metadata key for payment-required results in result._meta.-
credential_meta_key0Metadata key for credentials in params._meta.-
verification_failed_code0JSON-RPC error code for verification failed (-32043).-
payment_required_code0JSON-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.

Run a JSON-RPC request through MPP server-side payment verification before invoking a handler.

Metadata key for credentials in params._meta.

Extract and parse payment challenges from a JSON-RPC error map or full JSON-RPC response.

Extract a payment credential from JSON-RPC request params _meta.

Build server-side MCP transport configuration from the same endpoint options accepted by MPP.Plug.

Check whether a JSON-RPC error map (or full JSON-RPC response) 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

attach_credential(params, credential)

@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 - An MPP.Credential.t() struct (value)

Returns

Params map with _meta containing the credential (map)

Composes With

  • extract_credential
  • extract_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]
}

attach_receipt(result, receipt, challenge_id)

@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 - An MPP.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_credential
  • payment_required_error
# descripex:contract
%{
  params: %{
    result: %{description: "JSON-RPC result map", kind: :value},
    receipt: %{description: "An `MPP.Receipt.t()` struct", kind: :value},
    challenge_id: %{
      description: "The challenge ID this receipt fulfills",
      kind: :value
    }
  },
  returns: %{
    type: :map,
    description: "Result map with `_meta` containing the receipt and `challengeId`"
  },
  composes_with: [:extract_credential, :payment_required_error]
}

call(request, config, handler)

@spec call(map(), MPP.Plug.Config.t(), (map() ->
                                    map() | {:ok, map()} | {:error, map()})) ::
  map()

Run a JSON-RPC request through MPP server-side payment verification before invoking a handler.

Parameters

  • request - JSON-RPC request map with params._meta payment credential (value)
  • config - MCP transport config from init/1 (value)
  • handler - Function receiving the request after verification and returning a JSON-RPC response or result map (value)

Returns

JSON-RPC response with payment-required/verification error, or successful result._meta receipt (map)

Composes With

  • extract_credential
  • payment_required_error
  • attach_receipt
# descripex:contract
%{
  params: %{
    request: %{
      description: "JSON-RPC request map with params._meta payment credential",
      kind: :value
    },
    config: %{description: "MCP transport config from init/1", kind: :value},
    handler: %{
      description: "Function receiving the request after verification and returning a JSON-RPC response or result map",
      kind: :value
    }
  },
  returns: %{
    type: :map,
    description: "JSON-RPC response with payment-required/verification error, or successful result._meta receipt"
  },
  composes_with: [:extract_credential, :payment_required_error, :attach_receipt]
}

credential_meta_key()

@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\"`"}
}

extract_challenges(map)

@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()) ::
  {: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 or full JSON-RPC response.

Parameters

  • error - JSON-RPC error map with data.challenges, or a full response envelope (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`, or a full response envelope",
      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]
}

extract_credential(map)

@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 _meta containing 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_credential
  • attach_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]
}

init(opts)

@spec init(keyword()) :: MPP.Plug.Config.t()

Build server-side MCP transport configuration from the same endpoint options accepted by MPP.Plug.

Parameters

  • opts - Keyword options including :secret_key, :realm, and one or more payment methods (value)

Returns

MPP.Plug.Config reused by the MCP server adapter (struct)

Composes With

  • call
# descripex:contract
%{
  params: %{
    opts: %{
      description: "Keyword options including :secret_key, :realm, and one or more payment methods",
      kind: :value
    }
  },
  returns: %{
    type: :struct,
    description: "`MPP.Plug.Config` reused by the MCP server adapter"
  },
  composes_with: [:call]
}

payment_required?(map)

@spec payment_required?(map()) :: boolean()
@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 (or full JSON-RPC response) indicates payment is required.

Parameters

  • error - JSON-RPC error map with code field, or a full response envelope (value)

Returns

true if error code is -32042 (boolean)

# descripex:contract
%{
  params: %{
    error: %{
      description: "JSON-RPC error map with `code` field, or a full response envelope",
      kind: :value
    }
  },
  returns: %{type: :boolean, description: "`true` if error code is `-32042`"}
}

payment_required_code()

@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`"}}

payment_required_error(challenge)

@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 single MPP.Challenge struct 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_challenges
  • verification_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]
}

payment_required_meta_key()

@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\"`"
  }
}

receipt_meta_key()

@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\"`"}}

verification_failed_code()

@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`"}}

verification_failed_error(challenge, problem)

@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 single MPP.Challenge struct or a list of challenges (value)
  • problem - An MPP.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_error
  • extract_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]
}