# `MPP.Mcp`
[🔗](https://github.com/ZenHive/mpp/blob/v0.10.0/lib/mpp/mcp.ex#L1)

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 `-32042`
  * `verification_failed_code/0` — JSON-RPC error code `-32043`
  * `credential_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 from `params._meta`
  * `payment_required_error/1` — build `-32042` error with challenges
  * `verification_failed_error/2` — build `-32043` error with problem details
  * `attach_receipt/3` — add receipt + challengeId to `result._meta`

## Client Helpers

Detect payment-required errors and manage credentials:

  * `payment_required?/1` — check if error is `-32042`
  * `extract_challenges/1` — parse challenges from error data
  * `attach_credential/2` — insert credential into `params._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`). | - |

# `attach_credential`

```elixir
@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`

```elixir
# 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`

```elixir
@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`

```elixir
# 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]
}
```

# `credential_meta_key`

```elixir
@spec credential_meta_key() :: String.t()
```

Metadata key for credentials in `params._meta`.

## Returns

Key `"org.paymentauth/credential"` (`string`)

```elixir
# descripex:contract
%{
  returns: %{type: :string, description: "Key `\"org.paymentauth/credential\"`"}
}
```

# `extract_challenges`

```elixir
@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 with `data.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`

```elixir
# 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]
}
```

# `extract_credential`

```elixir
@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`

```elixir
# 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]
}
```

# `payment_required?`

```elixir
@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 with `code` field (value)

## Returns

`true` if error code is `-32042` (`boolean`)

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

# `payment_required_code`

```elixir
@spec payment_required_code() :: integer()
```

JSON-RPC error code for payment required (`-32042`).

## Returns

Error code `-32042` (`integer`)

```elixir
# descripex:contract
%{returns: %{type: :integer, description: "Error code `-32042`"}}
```

# `payment_required_error`

```elixir
@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`

```elixir
# 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`

```elixir
@spec payment_required_meta_key() :: String.t()
```

Metadata key for payment-required results in `result._meta`.

## Returns

Key `"org.paymentauth/payment-required"` (`string`)

```elixir
# descripex:contract
%{
  returns: %{
    type: :string,
    description: "Key `\"org.paymentauth/payment-required\"`"
  }
}
```

# `receipt_meta_key`

```elixir
@spec receipt_meta_key() :: String.t()
```

Metadata key for receipts in `result._meta`.

## Returns

Key `"org.paymentauth/receipt"` (`string`)

```elixir
# descripex:contract
%{returns: %{type: :string, description: "Key `\"org.paymentauth/receipt\"`"}}
```

# `verification_failed_code`

```elixir
@spec verification_failed_code() :: integer()
```

JSON-RPC error code for verification failed (`-32043`).

## Returns

Error code `-32043` (`integer`)

```elixir
# descripex:contract
%{returns: %{type: :integer, description: "Error code `-32043`"}}
```

# `verification_failed_error`

```elixir
@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`

```elixir
# descripex:contract
%{
  params: %{
    challenges: %{
      description: "A single `MPP.Challenge` struct or a list of challenges",
      kind: :value
    },
    problem: %{
      description: "An `MPP.Errors.t()` struct with RFC 9457 problem details",
      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]
}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
