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

Use MPP with Foundry

Foundry includes native MPP support on Tempo. When an RPC endpoint returns 402 Payment Required, Foundry automatically handles the payment challenge with no wrapper scripts, middleware, or code changes.

Every Foundry tool works transparently with MPP-gated endpoints:

  • cast — queries and transactions
  • forge — scripts and forked tests
  • anvil — local forks of paid endpoints
  • chisel — interactive REPL sessions

How MPP works with Foundry

When you point any Foundry tool at an MPP-gated RPC URL, the built-in transport intercepts 402 responses and resolves them using MPP's session flow:

  1. First request — Foundry sends a normal JSON-RPC request to the endpoint.
  2. 402 challenge — The server responds with 402 Payment Required and a WWW-Authenticate: Payment header describing the price.
  3. Key discovery — Foundry reads your signing key from $TEMPO_HOME/wallet/keys.toml (default ~/.tempo/wallet/keys.toml) or the TEMPO_PRIVATE_KEY env var. If the server offers multiple payment challenges (e.g. different chains or currencies), Foundry automatically picks the one matching your key's chain ID and spending allowance.
  4. Channel open — If no payment channel exists, Foundry opens one on-chain with a deposit (default: 100,000 base units). This is a one-time on-chain lockup — unused balance remains in the channel.
  5. Voucher payment — Foundry signs an off-chain voucher against the open channel and retries the request with an Authorization: Payment header.
  6. Auto top-up — When a channel's deposit is exhausted, Foundry sends a top-up transaction. The server accepts it with 204 No Content, then Foundry signs a fresh voucher and retries automatically.
  7. Channel reuse — Subsequent requests reuse the same channel. Channel state is persisted to $TEMPO_HOME/foundry/channels.json (default ~/.tempo/foundry/channels.json) across process invocations.

Foundry MPP setup

Install the Tempo CLI

curl -fsSL https://tempo.xyz/install | bash

Install Foundry

Tempo support now ships in the latest Foundry releases:

foundryup

All standard Foundry commands work as before — MPP activates only when an endpoint returns 402.

Configure your wallet

tempo wallet login

This creates ~/.tempo/wallet/keys.toml with your signing key. Foundry discovers this key automatically on the first 402 response.

Alternatively, set the TEMPO_PRIVATE_KEY environment variable:

export TEMPO_PRIVATE_KEY=0xabc…123

Use MPP endpoints

Point any Foundry tool at an MPP-gated RPC URL. No additional flags or config needed.

cast block-number --rpc-url https://rpc.mpp.tempo.xyz

Foundry MPP examples

MPP requests with cast

Query chain state through a paid endpoint:

# Get latest block number
cast block-number --rpc-url https://rpc.mpp.tempo.xyz
 
# Read a contract
cast call 0x20c0000000000000000000000000000000000000 \
  "balanceOf(address)(uint256)" 0xYourAddress \
  --rpc-url https://rpc.mpp.tempo.xyz

MPP requests in forge script

Run deployment or read scripts against a paid endpoint:

// script/ReadBlock.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
 
import "forge-std/Script.sol";
 
contract ReadBlock is Script {
    function run() public view {
        console.log("block", block.number);
        console.log("chain", block.chainid);
    }
}
forge script script/ReadBlock.s.sol --rpc-url https://rpc.mpp.tempo.xyz

MPP requests in forked forge test

Fork a paid endpoint in tests using vm.createSelectFork:

// test/MppFork.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
 
import "forge-std/Test.sol";
 
contract MppForkTest is Test {
    function test_fork_via_mpp() public {
        vm.createSelectFork("https://rpc.mpp.tempo.xyz");
        assertGt(block.number, 0);
        assertEq(block.chainid, 4217);
    }
}
forge test --match-test test_fork_via_mpp -vvv

MPP requests with Anvil

Fork a paid endpoint locally. Local RPC calls stay local, but any upstream fetches Anvil makes to the fork URL go through MPP:

anvil --fork-url https://rpc.mpp.tempo.xyz

MPP requests with Chisel

Interactive REPL against a paid endpoint:

chisel --fork-url https://rpc.mpp.tempo.xyz
➜ block.number
Type: uint256
├ Hex: 0x...
└ Decimal: 1234567

Foundry MPP configuration

MPP deposit amount

Set the fallback deposit amount used when the server does not suggest one:

export MPP_DEPOSIT=500000
cast block-number --rpc-url https://rpc.mpp.tempo.xyz

The deposit determines how many RPC calls you can make before the channel needs a top-up. When a channel is exhausted, Foundry automatically tops it up.

MPP key discovery

Foundry discovers MPP signing keys in this order:

  1. TEMPO_PRIVATE_KEY env var — highest priority, no keychain metadata
  2. $TEMPO_HOME/wallet/keys.toml — created by tempo wallet login, includes keychain signing mode and authorized signer metadata

Within keys.toml, the key selection priority is:

  • Passkey entries first
  • Entries with an inline private key second
  • First entry as fallback

Foundry needs a usable inline private key — entries without one are skipped.

When the server offers multiple chains or currencies, Foundry picks the first key that matches both the chain ID and currency from the challenge.

MPP channel persistence

Open channels are saved to $TEMPO_HOME/foundry/channels.json (default ~/.tempo/foundry/channels.json). This allows channel reuse across process invocations — you won't re-open a channel every time you run cast or forge.

Channels are automatically evicted when fully spent or closed. If the server restarts and returns 410 Gone, Foundry clears stale local state and opens a fresh channel on the next request.

Tempo MPP testnet workflow

Use the Moderato testnet MPP endpoint for development:

cast block-number --rpc-url https://rpc.mpp.moderato.tempo.xyz
 
# Mainnet
cast block-number --rpc-url https://rpc.mpp.tempo.xyz

Fund your testnet wallet with tempo wallet fund before making requests.

MPP gas sponsorship

Some MPP endpoints sponsor gas fees on behalf of the caller. When the server's challenge includes a feePayer flag, Foundry delegates gas payment to the server, so no native balance is needed for gas.

Troubleshoot MPP with Foundry

ErrorCauseFix
tempo: command not foundTempo CLI not installedRun curl -fsSL https://tempo.xyz/install | bash
no supported MPP challengeMissing wallet key or wrong chain/currencyRun tempo wallet login or check keys.toml
410 GoneStale local channel stateRe-run the command — Foundry clears stale state and opens a fresh channel
access key does not existSigning key not yet provisioned on-chainFoundry retries automatically with a key provisioning bundle — no action needed

Next steps for MPP with Foundry