MPP - 機器支付協議
MPP 是一個開放協議(由 Tempo 和 Stripe 共同撰寫),用於標準化機器對機器支付的 HTTP 402 Payment Required。客戶端在同一 HTTP 請求中付款 - 無需帳戶、API 金鑰或結帳流程。
核心協定規範已提交給 IETF,名為 Payment HTTP Authentication Scheme。
本技能中的程式碼使用佔位符代幣名稱(<USDC_TEMPO_MAINNET>、<PATHUSD_TESTNET>);實際地址位於 Tempo 文件 和 references/tempo-method.md 中。
核心架構
三個基本元素驅動每一次 MPP 支付:
- Challenge(挑戰) - 伺服器發出的支付要求(在
WWW-Authenticate: Payment標頭中) - Credential(憑證) - 客戶端提交的支付證明(在
Authorization: Payment標頭中) - Receipt(收據) - 伺服器確認支付成功(在
Payment-Receipt標頭中)
支付方式與意圖
MPP 與支付方式無關。每種方法都定義了自己的結算軌道:
| 方法 | 軌道 | SDK 套件 | 狀態 |
|---|---|---|---|
| Tempo | TIP-20 穩定幣(Tempo 鏈) | mppx(內建) | 生產環境 |
| Stripe | 卡/錢包(SPT)+ 鏈上加密貨幣存款 | mppx(內建) | 生產環境 |
| EVM | EIP-3009 穩定幣授權(相容 x402-exact) | mppx(內建) | 生產環境 |
| Lightning | 比特幣閃電網路 | @buildonspark/lightning-mpp-sdk | 生產環境 |
| Stellar | Stellar 上的 SEP-41 代幣,使用 charge + channel | @stellar/mpp | 生產環境(channel 線路規範仍在起草中 - 可能會有變動) |
| Solana | Solana 原生 charge + session(SOL、SPL、Token-2022) | @solana/mpp | 生產環境 |
| Monad | Monad charge(ERC-3009,結算模式) | @monad-crypto/mpp | 生產環境 |
| NEAR Intents | 透過 1Click 存款地址進行跨鏈 charge | @defuse-protocol/nearintents-mpp-sdk | 生產環境(非無信任 - 透過結算後端路由,廣告為 methodDetails.settlementBackend: "near-intents" 以供按方法設定風險策略) |
| RedotPay | RedotPay 餘額(rdt)或穩定幣證明,僅 charge | @redotpay/mpp | 生產環境 |
| Card | 加密網路代幣(Visa) | mpp-card | 生產環境 |
| 自訂 | 任何軌道 | Method.from() + Method.toClient/toServer | 可擴展 |
每種方法的深入探討:references/tempo-method.md、references/stripe-method.md、references/lightning-method.md、references/custom-methods.md。
| 意圖 | 模式 | 最適合 |
|---|---|---|
| charge | 每次請求一次性付款 | API 呼叫、內容存取、固定價格端點 |
| session | 透過支付通道隨用隨付 | LLM 串流、按量計費、高頻 API |
| subscription | 透過授權金鑰(Tempo)進行週期性存取 - 請參閱 references/subscriptions.md | 計劃/層級,其中的存取與按請求計費分開 |
快速入門:伺服器端 (TypeScript)
import { Mppx, tempo } from 'mppx/server'
const mppx = Mppx.create({
methods: [tempo({
currency: '<PATHUSD_TESTNET>', // pathUSD 測試網
recipient: '0xYourAddress',
})],
})
export async function handler(request: Request) {
const result = await mppx.charge({ amount: '0.01' })(request)
if (result.status === 402) return result.challenge
return result.withReceipt(Response.json({ data: '...' }))
}
安裝:npm install mppx viem(mppx 0.8.15 需要 viem >= 2.54.0)。
使用 npx mppx validate http://localhost:3000 端到端驗證完成的伺服器。
快速入門:客戶端 (TypeScript)
import { privateKeyToAccount } from 'viem/accounts'
import { Mppx, tempo } from 'mppx/client'
// Polyfills globalThis.fetch 自動處理 402
Mppx.create({
methods: [tempo({ account: privateKeyToAccount('0x...') })],
})
const res = await fetch('https://api.example.com/paid')
// 當伺服器返回 402 時,付款會透明地進行
在瀏覽器中,mppx 0.6.0 更改了預設行為:polyfilled fetch 僅向同源端點發送 Accept-Payment,因此跨來源付費 API 需要 acceptPaymentPolicy('always' / { origins: [...] })。客戶端 fetch 會重試增量挑戰,最多 maxPaymentRetries 次(預設為 3)。對於非全域替代方案(Fetch.from/polyfill/restore、Mppx.restore()),請參閱 references/typescript-sdk.md。
快速入門:伺服器端 (Python)
from fastapi import FastAPI
from mpp import Credential, Receipt
from mpp.server import Mpp
from mpp.methods.tempo import tempo, ChargeIntent
app = FastAPI()
server = Mpp.create(method=tempo(
currency="<PATHUSD_TESTNET>",
recipient="0xYourAddress", intents={"charge": ChargeIntent()},
))
@app.get("/resource")
@server.pay(amount="0.50")
async def get_resource(request, credential: Credential, receipt: Receipt):
return {"data": "paid content", "payer": credential.source}
安裝:pip install "pympp[tempo]"。有關完整模式,請參閱 references/python-sdk.md。
快速入門:伺服器端 (Rust)
安裝:cargo add mpp --features tempo,server。有關完整模式,請參閱 references/rust-sdk.md。
框架中介軟體 (TypeScript)
每個框架都有自己的導入路徑(mppx/nextjs、mppx/hono、mppx/express、mppx/elysia):
// Next.js
import { Mppx, tempo } from 'mppx/nextjs'
const mppx = Mppx.create({ methods: [tempo({ currency: '<PATHUSD_TESTNET>', recipient: '0x...' })] })
export const GET = mppx.charge({ amount: '0.1' })(() => Response.json({ data: '...' }))
// Hono
import { Mppx, tempo } from 'mppx/hono'
app.get('/resource', mppx.charge({ amount: '0.1' }), (c) => c.json({ data: '...' }))
有關 Express 和 Elysia 的範例,請參閱 references/typescript-sdk.md。
會話:隨用隨付串流
會話開啟一次支付通道,然後對每個請求使用鏈下憑證 - 每次請求無需區塊鏈交易。延遲低於 100 毫秒,每次請求費用接近於零。
會話 v2(自 mppx 0.7.0 起為預設): tempo.session() 是 TIP-1034 預編譯通道流程;早期的託管合約實作是會話 v1,仍然可以作為已棄用的 tempo.sessionLegacy 使用。預期 v2 的客戶端會拒絕 v1 會話並回退到 charge 路徑,因此請確保客戶端和伺服器使用匹配的流程。兩個客戶端 API:tempo.session({ account, maxDeposit }) 使用 Mppx.create() 註冊該方法(透過 fetch 透明處理 402),而 tempo.session.manager({ account, maxDeposit }) 返回一個受管理的客戶端,用於直接生命週期控制(.sse()、.close())。
// 伺服器 - 具有自動結算的會話端點
const mppx = Mppx.create({
methods: [tempo.session({
currency: '<PATHUSD_TESTNET>', recipient: '0x...',
store: Store.redis(redis),
settlementSchedule: { amount: '1.00', intervalMs: 300_000 },
bootstrap: true, // 讓回訪客戶端在此路由上恢復其通道
})],
})
const result = await mppx.session({ amount: '0.001', unitType: 'token' })(request)
if (result.status === 402) return result.challenge
return result.withReceipt(Response.json({ data: '...' }))
// 伺服器 - 按單詞計費的 SSE 串流
export const GET = mppx.session({ amount: '0.001', unitType: 'word' })(
async () => async function* (stream) {
for (const word of ['hello', 'world']) {
await stream.charge()
yield word
}
}
)
// 客戶端 - 具有自動管理通道的會話
Mppx.create({ methods: [tempo({ account, maxDeposit: '1' })] })
const res = await fetch('http://localhost:3000/api/resource')
// 第 1 個請求:在鏈上開啟通道;第 2 個以後:鏈下憑證
會話也可以透過 WebSocket 使用 Ws.serve() 進行串流。有關完整的生命週期、結算、儲存、SSE 和 WebSocket 模式以及通道恢復,請參閱 references/sessions.md。
多方法支援
在單一端點上接受 Tempo 穩定幣、Stripe 卡和 Lightning Bitcoin:
const mppx = Mppx.create({
methods: [
tempo({ currency: '<PATHUSD_TESTNET>', recipient: '0x...' }),
stripe.charge({ client: new Stripe(key), networkId: 'profile_...', paymentMethodTypes: ['card'] }),
spark.charge({ mnemonic: process.env.MNEMONIC! }),
],
})
使用 Mppx.compose() 在單個 402 回應中呈現多種方法並設定按路線定價。在挑戰端點和驗證端點應用相同的分支,否則 402 廣告的選項會少於伺服器接受的選項。請參閱 references/typescript-sdk.md。
支付連結 (HTML)
在支付方法配置上設定 html: true 會在瀏覽器中訪問 402 端點時呈現一個瀏覽器友好的支付頁面,具有主題樣式、多方法組合標籤頁和 Solana 錢包支援。Service Worker 處理憑證提交,然後頁面重新載入並顯示已支付的回應。
透過 mppx/html 匯出(Config、Text、Theme)進行自訂,並使用 Html.init(methodName) 建立自訂方法的支付連結。
零美元身份驗證(證明憑證)
驗證代理身分而無需付款。客戶端簽署一個針對挑戰 ID 的 EIP-712 證明,而不是建立交易 - 無需燃料費,無需轉移資金。
// 伺服器 - 零美元 charge,使用儲存進行重放保護
const mppx = Mppx.create({
methods: [tempo.charge({ currency: '<PATHUSD_TESTNET>', recipient: '0x...', store })],
})
const result = await mppx.charge({ amount: '0' })(request)
從 mppx 0.8.0 開始,這些證明繫結到付款人錢包:EIP-712 Proof 型別資料(匯出為 tempo.Proof)在網域版本 3 中攜帶了一個 account 欄位,因此為一個帳戶簽署的證明無法再針對另一個帳戶進行驗證。
使用案例:身分驗證、長時間執行的作業輪詢、付費解鎖後免費後續存取、多步驟代理管道。請參閱 mpp.dev/advanced/identity。
支付代理
在現有 API 前設置 MPP 支付閘道:
// import { openai, Proxy } from 'mppx/proxy' - Proxy.create({ services: [...] }) 內部的服務
openai({
apiKey: process.env.OPENAI_API_KEY,
routes: {
'POST /v1/chat/completions': mppx.charge({ amount: '0.05' }),
'GET /v1/models': true, // 字面量 `true` 標記為免費路由
},
})
內建預設 openai()、anthropic()、stripe(),以及適用於任何上游的 custom()。有關 Proxy.create()、它所提供的探索端點以及非代理伺服器的 discovery() 輔助函數,請參閱 references/discovery-and-proxy.md。
MCP 傳輸
MCP 工具呼叫可以使用 JSON-RPC 錯誤碼 -32042(伺服器也可能發出 -32043)來要求付款:
// 伺服器 - 從 mppx/server 匯入 tempo,而不是 mppx/tempo
import { McpServer } from 'mppx/mcp/server'
import { tempo } from 'mppx/server'
const server = McpServer.wrap(baseServer, { methods: [tempo.charge({ /* ... */ })], secretKey })
// 客戶端 - 支援支付的 MCP 客戶端(從 mppx/client 匯入 tempo)
import { McpClient } from 'mppx/mcp/client'
import { tempo } from 'mppx/client'
const mcp = McpClient.wrap(client, { methods: [tempo({ account })] })
const result = await mcp.callTool({ name: 'premium_tool', arguments: {} })
MCP-over-HTTP 挑戰在同一支援支付的 fetch 中結算,並且傳輸在兩端都可以透過 Transport.from/http/mcp/mcpSdk 進行插拔。請參閱 references/transports.md。
Privy 伺服器錢包
來自 @privy-io/node/viem 的 createViemAccount(需要 @privy-io/node >= 0.20.0)返回一個由 Privy 伺服器錢包支援的 viem Account,因此它可以取代 tempo({ account }) 中的任何本機帳戶。
伺服器端簽名適用於應用程式擁有的伺服器錢包;使用者擁有的嵌入式錢包需要授權金鑰或金鑰仲裁。有關完整設定和手動 toAccount() 建構,請參閱 references/typescript-sdk.md。
測試與 CLI
# 建立一個帳戶(儲存在金鑰鏈中),然後在測試網上注入資金
npx mppx account create
npx mppx account fund --network testnet
# 發送付費請求
npx mppx http://localhost:3000/resource
# 解析挑戰而不簽署它
npx mppx sign --dry-run --challenge '<www-authenticate value>'
# 端到端驗證伺服器實作
npx mppx validate http://localhost:3000
CLI 還涵蓋 init、sessions(檢視/關閉列表)、discover、services、mcp add 和 skills add。配置來自 MPPX_CONFIG 或明確的 --config - 不會從工作目錄自動探索。完整參考:references/cli.md。
SDK 套件
| 語言 | 套件 | 安裝 |
|---|---|---|
| TypeScript | mppx | npm install mppx |
| Python | pympp | pip install "pympp[tempo]" |
| Rust | mpp | cargo add mpp --features tempo,client,server |
| Ruby | mpp-rb(官方,由 Stripe 提供) | 請參閱儲存庫了解 gem 名稱 |
| Go | mpp-go(官方,由 Tempo 提供) | go get github.com/tempoxyz/mpp-go |
| Elixir | mpp(社群) | hex.pm/packages/mpp |
| Swift | mpp-swift(社群) | 請參閱儲存庫 |
功能說明,根據 SDK 原始碼而非文件矩陣檢查(上游發布了兩個不一致的矩陣):
- Session 意圖:僅 TypeScript 和 Rust。
- Proof Credentials(零美元身份驗證):TypeScript
…
[為翻譯而截斷]