PerformanceBlog
Tempo MCP serverGive agents search and read tools for Tempo docs
Skip to content
LogoLogo

Server quickstart

Plug MPP into any server framework to accept payments for protected resources. Use mppx middleware for your framework, or call mppx/server directly with the Fetch API.

MPP server framework middleware

Use the framework-specific middleware from mppx to integrate payment into your server. Each middleware handles the 402 challenge/credential flow and attaches receipts automatically.

import { Mppx, tempo } from 'mppx/nextjs'
 
const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})
 
export const GET =
  mppx.charge({ amount: '0.1' })
  (() => Response.json({ data: '...' }))

Manual MPP server mode

If you prefer full control over the payment flow, use mppx/server directly with the Fetch API.

import { Mppx, tempo } from 'mppx/server'
 
const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})
 
export async function handler(request: Request) {
  const response = await mppx.charge({ amount: '0.1' })(request)
 
  // Payment required: send 402 response with challenge
  if (response.status === 402) return response.challenge
 
  // Payment verified: attach receipt and return resource
  return response.withReceipt(Response.json({ data: '...' }))
}

MPP payment realm

The realm identifies your server in payment challenges and on-chain attribution. By default, mppx auto-detects it from environment variables (HOSTNAME, VERCEL_URL, etc.), but this can produce incorrect values in containerized environments where HOSTNAME is set to an internal identifier (e.g. a Kubernetes pod name).

Set realm explicitly to your public domain:

const mppx = Mppx.create({
  realm: 'api.example.com', 
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

You can also set the MPP_REALM environment variable instead of passing it in code.

MPP push and pull modes

Tempo charges support two transaction submission modes, determined by the client:

  • pull mode (default): the client signs the transaction and sends the serialized transaction to the server. The server broadcasts it and verifies on-chain. This enables the server to sponsor gas fees via a feePayer.
  • push mode: the client builds, signs, and broadcasts the transaction itself (for example, via a browser wallet). It sends the transaction hash to the server, which verifies the payment by fetching the receipt.

Your server handles both modes automatically — no configuration required. The server inspects the credential payload type (transaction for pull, hash for push) and verifies accordingly.

MPP fee sponsorship

To sponsor gas fees for pull-mode clients, pass a feePayer account to tempo():

import { Mppx, tempo } from 'mppx/server'
import { privateKeyToAccount } from 'viem/accounts'
 
const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    feePayer: privateKeyToAccount('0x…'),
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

When a pull-mode client submits a signed transaction, the server co-signs with the fee payer account before broadcasting. Push-mode clients pay their own gas, so feePayer is ignored for those requests.

Test your MPP server

After your server is running, test it with the mppx CLI:

# Create an account funded with testnet tokens
$ npx mppx account create
 
# Make a paid request
$ npx mppx <your-server>/resource

Next steps for MPP servers