Skip to content

feat(api): add native MPP (Machine Payments Protocol) support#2398

Closed
decofe wants to merge 1 commit intoe2b-dev:mainfrom
decofe:tempo/add-mpp-support
Closed

feat(api): add native MPP (Machine Payments Protocol) support#2398
decofe wants to merge 1 commit intoe2b-dev:mainfrom
decofe:tempo/add-mpp-support

Conversation

@decofe
Copy link
Copy Markdown

@decofe decofe commented Apr 15, 2026

Summary

Add native HTTP 402 payment support via the Machine Payments Protocol so AI agents can pay for E2B sandbox usage with crypto (Tempo USDC) instead of API keys.

Motivation

MPP enables no-signup, pay-per-use access to E2B sandboxes. An AI agent with a Tempo wallet can create and manage sandboxes by paying per request — no API key, no account, no billing setup. This is especially useful for autonomous agents that need compute on demand.

Changes

OpenAPI spec (spec/openapi.yml)

  • Add PaymentAuth security scheme (http/payment)
  • Add PaymentAuth as an alternative auth option on sandbox endpoints: create, kill, connect, timeout, refreshes

Config (packages/api/internal/cfg/model.go)

  • Add MPP_ENABLED, MPP_SECRET_KEY, MPP_REALM, MPP_CURRENCY, MPP_RECIPIENT, MPP_TEAM_ID env vars

Auth (packages/api/internal/handlers/payment_auth.go)

  • PaymentAuthenticator implements auth.Authenticator for the PaymentAuth security scheme
  • Maps MPP-authenticated requests to a pre-configured team via MPP_TEAM_ID

Middleware (packages/api/internal/middleware/mpp.go)

  • Gin middleware handling the full 402 challenge/credential flow
  • Issues WWW-Authenticate: Payment challenges when no auth is present
  • Verifies payment credentials and sets Payment-Receipt header
  • Skips requests that already have API key or bearer auth

Payment method (packages/api/internal/handlers/mpp_method.go)

  • TempoMethod / TempoChargeIntent implementing mpp-go/server.Method interface
  • Placeholder verification (HMAC challenge binding verified by mpp-go; full on-chain verification can be added later)

Wiring (packages/api/main.go)

  • Add PaymentAuthenticator to authenticator chain when MPP_ENABLED=true
  • Add MPP middleware after LaunchDarkly context, before rate limiting
  • Add Accept-Payment to CORS allowed headers

Store (packages/api/internal/handlers/store.go)

  • Add GetTeamByID using existing GetTeamWithTierByTeamID query

Dependency

  • Add github.com/tempoxyz/mpp-go to go.mod

Protocol flow

Agent                                    E2B API
  │                                        │
  │  POST /sandboxes (no auth)             │
  ├───────────────────────────────────────>│
  │                                        │
  │  402 + WWW-Authenticate: Payment ...   │
  │<───────────────────────────────────────┤
  │                                        │
  │  POST /sandboxes                       │
  │  Authorization: Payment <credential>   │
  ├───────────────────────────────────────>│
  │                                        │
  │  201 Created                           │
  │  Payment-Receipt: <receipt>            │
  │<───────────────────────────────────────┤

Testing

This is gated behind MPP_ENABLED=false (default), so existing behavior is unchanged. When enabled, requires MPP_SECRET_KEY, MPP_REALM, MPP_CURRENCY, MPP_RECIPIENT, and MPP_TEAM_ID.

Prompted by: georgios

Add HTTP 402 payment support so AI agents can pay for sandbox usage
with crypto (Tempo) instead of API keys.

- Add PaymentAuth security scheme to OpenAPI spec
- Add MPP config fields (MPP_ENABLED, MPP_SECRET_KEY, etc.)
- Add PaymentAuthenticator for OpenAPI auth validation
- Add MPP Gin middleware for 402 challenge/credential flow
- Add TempoMethod implementing mpp-go server.Method interface
- Add GetTeamByID to APIStore for MPP team lookup
- Wire MPP into auth chain and middleware stack
- Gate sandbox create, connect, kill, timeout, refresh behind 402

Uses github.com/tempoxyz/mpp-go for the payment protocol.

Amp-Thread-ID: https://ampcode.com/threads/T-019d8d82-1698-749a-8b5b-92b6d5cd77fe
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 69db744f84

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/api/main.go
Comment on lines +213 to +216
// MPP (Machine Payments Protocol) middleware for 402 payment support.
if config.MPPEnabled {
tempoMethod := handlers.NewTempoMethod(config.MPPCurrency, config.MPPRecipient)
r.Use(customMiddleware.MPPMiddleware(customMiddleware.MPPConfig{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Register MPP middleware before OpenAPI auth validation

In packages/api/main.go, the OAPI validator is installed before MPPMiddleware, so unauthenticated POST /sandboxes requests are rejected during security validation and never reach the middleware that generates WWW-Authenticate: Payment challenges. This breaks the first step of the documented 402 handshake (no-auth request -> challenge), because clients cannot obtain a challenge to construct a payment credential.

Useful? React with 👍 / 👎.

}

// Skip if the request already has standard E2B auth.
if c.GetHeader("X-API-Key") != "" || hasBearer(c.GetHeader("Authorization")) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Exempt Supabase-authenticated calls from MPP interception

The skip condition in packages/api/internal/middleware/mpp.go only recognizes X-API-Key and Authorization: Bearer, so requests authenticated via X-Supabase-Token/X-Supabase-Team are treated as unauthenticated and get challenged/charged by MPP when it is enabled. That regresses existing Supabase auth flows on billable sandbox endpoints despite valid credentials.

Useful? React with 👍 / 👎.

@gakonst
Copy link
Copy Markdown

gakonst commented Apr 15, 2026

Closing per offline convo - will bring proxy repo instead.

@tvi
Copy link
Copy Markdown
Contributor

tvi commented Apr 15, 2026

Thanks for the prototype. We are going to be implemeting this feature differently.

@tvi tvi closed this Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants