Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .mppx-docs-sync
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
# When updating docs from mppx changes, bump this SHA to HEAD of mppx main
# after incorporating the new features/changes into the docs site.

mppx_version=0.0.0-main-20260911134810
mppx_sha=3c14a65a7ea55247f943a6c209ce67a1e8c57239
mppx_version=0.0.0-main-20260914191442
mppx_sha=eda059a13e4667368e065cdca51789f2a17777e6
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"hono": "^4.12.27",
"lottie-web": "^5.13.0",
"mermaid": "^11.15.0",
"mppx": "0.0.0-main-20260911134810",
"mppx": "0.0.0-main-20260914191442",
"nuqs": "2.9.1",
"react": "^19",
"react-dom": "^19",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/pages.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ type Page =
| { path: '/sdk/typescript/client/Method.tempo.subscription'; render: 'static' }
| { path: '/sdk/typescript/client/Mppx.create'; render: 'static' }
| { path: '/sdk/typescript/client/Mppx.preparePayment'; render: 'static' }
| { path: '/sdk/typescript/client/Mppx.prepareRequest'; render: 'static' }
| { path: '/sdk/typescript/client/Mppx.restore'; render: 'static' }
| { path: '/sdk/typescript/client/Transport.from'; render: 'static' }
| { path: '/sdk/typescript/client/Transport.http'; render: 'static' }
Expand Down
19 changes: 18 additions & 1 deletion src/pages/sdk/typescript/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ x402 payments support compatible EVM `exact` Challenges and use the same account

## Validate command

Use `mppx validate` to automatically verify an MPP server implementation end-to-end. The command tests discovery, challenge formats, error handling, and the full payment flow.
Use `mppx validate` to automatically verify an MPP server implementation end-to-end. The command tests `/llms.txt`, OpenAPI discovery, Challenge formats, error handling, and the full payment flow. A missing, empty, or non-text `/llms.txt` appears as a non-blocking `suggested` result.

```bash [terminal]
$ mppx validate https://api.example.com
Expand All @@ -87,6 +87,23 @@ Run `mppx validate` against both test and production versions of your server. On

When your config declares payment methods, `mppx validate` uses their signing accounts, approval hooks, chain policies, and Session stores instead of substituting built-in methods or preflighting the local CLI wallet.

### Programmatic validation

Import `validate` from `mppx/validation` when you need structured results.

```ts twoslash [validate.ts]
import { validate } from 'mppx/validation'

const result = await validate({
skipPayment: true,
url: 'https://api.example.com',
})

console.log(result.summary.suggested)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Show the validation summary output

Add a // @log: comment showing an expected suggested count after this call. The example introduces programmatic validation specifically to demonstrate the structured result, but currently omits the required inline output and leaves readers without a concrete result shape.

AGENTS.md reference: AGENTS.md:L297-L300

Useful? React with 👍 / 👎.

```

The `summary` contains `failed`, `passed`, `skipped`, `suggested`, and `warnings` counts. Individual checks use the matching `severity`, including `'suggested'` for optional improvements such as publishing `/llms.txt`. Suggested checks don't make validation fail.

## Environment variables

| Variable | Description |
Expand Down
14 changes: 14 additions & 0 deletions src/pages/sdk/typescript/client/Mppx.create.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,16 @@ type Mppx = {
request?: RequestInit
},
) => Promise<PreparedPayment>
/** Prepares a Challenge with the exact HTTP request that produced it. */
prepareRequest: (
input: RequestInfo | URL,
init?: RequestInit,
options?: {
acceptPayment?: string | AcceptPayment.Entry[]
maxRedirects?: number
orderChallenges?: OrderChallenges
},
) => Promise<PreparedRequest>
/** The original, unwrapped fetch — bypasses payment interception. */
rawFetch: typeof globalThis.fetch
/** The transport used. */
Expand All @@ -344,6 +354,10 @@ type Mppx = {

Selects and snapshots a supported Challenge without signing it. The returned object lets you inspect the terms, create the Credential later, and attach it through the correct Payment auth, x402, or MCP protocol. See [`Mppx.preparePayment`](/sdk/typescript/client/Mppx.preparePayment).

### `prepareRequest`

Follows safe pre-payment redirects and prepares the exact HTTP request that returned the Challenge. Use it in Node.js when approval must happen before signing; the paid request doesn't follow redirects. See [`Mppx.prepareRequest`](/sdk/typescript/client/Mppx.prepareRequest).

### `rawFetch`

The original `fetch` function, before payment interception. Use `rawFetch` when you need to make requests that bypass the 402 handler—for example, probing a 402 endpoint for websocket auth tokens or calling APIs that return 402 for non-payment reasons.
Expand Down
2 changes: 2 additions & 0 deletions src/pages/sdk/typescript/client/Mppx.preparePayment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Selects a supported Challenge without creating or attaching its Credential.

For manual HTTP requests that can redirect before payment, use [`Mppx.prepareRequest`](/sdk/typescript/client/Mppx.prepareRequest) to keep the Credential pinned to the exact request that produced the Challenge.

## Usage

```ts twoslash [client.ts]
Expand Down
153 changes: 153 additions & 0 deletions src/pages/sdk/typescript/client/Mppx.prepareRequest.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# `Mppx.prepareRequest` [Prepare a request-bound payment]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the required social-card frontmatter

Add description and imageDescription frontmatter before this H1. Without these fields, sharing the new reference page uses generic metadata and the OG-description generator has no page-specific card text to render.

AGENTS.md reference: AGENTS.md:L241-L246

Useful? React with 👍 / 👎.


Follows safe pre-payment redirects and prepares the exact HTTP request that returned a Challenge.

## Usage

```ts twoslash [client.ts]
import { Mppx, tempo } from 'mppx/client'
import { privateKeyToAccount } from 'viem/accounts'

const mppx = Mppx.create({
methods: [
tempo({
account: privateKeyToAccount(
'0x0123456789012345678901234567890123456789012345678901234567890123',
),
}),
],
polyfill: false,
})

// [!code hl:start]
const payment = await mppx.prepareRequest('https://api.example.com/checkout', {
body: JSON.stringify({ plan: 'pro' }),
headers: { 'Content-Type': 'application/json' },
method: 'POST',
})

console.log(payment.challenge.request)
console.log(payment.redirects)
Comment on lines +29 to +30

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add expected output for the inspection logs

Add a // @log: result after each of these calls, or remove the calls if their output isn't useful. As written, readers can't see what the documented Challenge request and redirect records look like, and the repository requires console output in examples to be shown inline.

AGENTS.md reference: AGENTS.md:L297-L300

Useful? React with 👍 / 👎.


const response = await payment.pay()
// [!code hl:end]

console.log(response.status)
// @log: 200
```

`prepareRequest` sends the request without creating a Credential, follows pre-payment redirects, and stops at the payment-required response. Use it when you need to inspect or approve payment terms while keeping the Credential bound to the request that produced the Challenge.

The method rejects HTTPS downgrade redirects, removes credentials and sensitive headers on cross-origin redirects, and applies standard redirect method changes. `pay` creates the Credential at most once and sends it only to the prepared URL with redirects disabled.

:::warning[Runtime support]
Use `prepareRequest` in Node.js and runtimes that expose manual redirect responses. Browsers return opaque manual redirects, so this method rejects browser redirect chains.
:::

### With request-local selection

Override the configured payment preferences for one request.

```ts twoslash [client.ts]
import { Mppx, tempo } from 'mppx/client'
import type { Account } from 'viem'

declare const account: Account

const mppx = Mppx.create({
methods: [tempo({ account })],
polyfill: false,
})

const payment = await mppx.prepareRequest(
'https://api.example.com/paid',
undefined,
{
acceptPayment: 'tempo/charge;q=1, tempo/session;q=0',
Comment on lines +62 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Highlight the request-local options

Add block highlight markers around the request-local options argument being demonstrated here. This long snippet currently has no highlighted lines, so the relevant override is buried among setup code despite the repository requirement that code blocks longer than five lines highlight their critical section.

AGENTS.md reference: AGENTS.md:L311-L315

Useful? React with 👍 / 👎.

maxRedirects: 5,
orderChallenges: (candidates) => candidates.filter(({ challenge }) =>
challenge.request.amount !== '0'
),
},
)
```

## Return type

```ts
type PreparedRequest = Readonly<{
challenge: Challenge
challenges: readonly Challenge[]
createCredential: (context?: Context) => Promise<string>
method: Method.Client
pay: (context?: Context) => Promise<Response>
redirects: readonly Readonly<{
from: string
status: number
to: string
}>[]
request: Request
response: Response
setCredential: (request: RequestInit, credential: string) => RequestInit
}>
```

### challenge

The selected immutable Challenge.

### challenges

All supported Challenges extracted from the payment-required response.

### createCredential

Creates the selected Challenge's Credential. Repeated or concurrent calls return the same promise.

### method

An immutable snapshot of the configured client method selected for the Challenge.

### pay

Creates and sends the Credential to the prepared request. The paid request uses `redirect: 'manual'`, so the Credential doesn't follow a redirect to another URL.

### redirects

Immutable pre-payment redirect records with each source URL, status code, and destination URL.

### request

The exact request that returned the payment-required response.

### response

The payment-required response returned for `request`.

### setCredential

Returns a request initializer with the Credential attached through the protocol that produced the Challenge.

## Parameters

### init (optional)

- **Type:** `RequestInit`

Request options for the initial HTTP request.

### input

- **Type:** `RequestInfo | URL`

URL or request to prepare.

### options (optional)

- **Type:** `{ acceptPayment?: string | readonly AcceptPayment.Entry[]; maxRedirects?: number; orderChallenges?: OrderChallenges }`

Request-local Challenge selection and redirect limits.

- `acceptPayment` overrides the configured payment preferences.
- `maxRedirects` sets the maximum pre-payment redirects. Defaults to `20`.
- `orderChallenges` filters or sorts supported Challenge candidates.
4 changes: 4 additions & 0 deletions vocs.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,10 @@ export default defineConfig({
text: ".preparePayment",
link: "/sdk/typescript/client/Mppx.preparePayment",
},
{
text: ".prepareRequest",
link: "/sdk/typescript/client/Mppx.prepareRequest",
},
{
text: ".restore",
link: "/sdk/typescript/client/Mppx.restore",
Expand Down
Loading