Skip to main content
MRP supports two deployment modes: embedded mode for zero-config self-hosting, and external mode for production deployments with PostgreSQL, Redis, and S3.

Embedded mode (zero config)

Embedded mode runs everything in a single binary with no external dependencies. Data is stored locally using SQLite, an in-memory cache, and filesystem-based blob storage.
# Build the relay
go build -o relay ./cmd/relay

# Run it — no environment variables needed
./relay
That’s it. The relay starts on port 8080 with:
  • SQLite database at ./data/mrp.db (WAL mode)
  • In-memory cache for agent status, ACL lookups, and discovery results
  • Filesystem blobs at ./data/blobs/
  • In-memory rate limiter, replay guard, and webhook queue
curl http://localhost:8080/v1/health/ready
# {"status":"ok"}

How mode is selected

The relay auto-detects which mode to use:
ConditionMode
MRP_MODE=embedded setEmbedded
MRP_MODE=external setExternal
DATABASE_URL is setExternal
Nothing setEmbedded (default)

Configuration

Embedded mode accepts these environment variables:
VariableDefaultDescription
MRP_MODEauto-detectForce embedded or external
DATA_DIR./dataDirectory for SQLite database and blob files
PORT8080HTTP server port
LOG_LEVELinfoLog level (debug, info, warn, error)
TIMESTAMP_TOLERANCE5mMax age for request timestamps

Data directory structure

./data/
  mrp.db          # SQLite database (WAL mode)
  blobs/          # Binary blob storage
    blobs/
      <owner_key>/
        <blob_id>       # Blob data
        <blob_id>.meta  # Content-type metadata
The data directory is created automatically on first startup.

When to use embedded mode

  • Development and testing — spin up a relay instantly without Docker or infrastructure
  • Single-machine deployments — personal relays, home labs, CI/CD test fixtures
  • Edge deployments — IoT gateways, embedded systems, air-gapped networks
  • Evaluation — try MRP without provisioning any services

Limitations

  • Single-process — no horizontal scaling (one relay instance per data directory)
  • In-memory state — rate limiter, replay guard, and webhook retry queue are lost on restart
  • SQLite concurrency — handles moderate concurrent writes; high-throughput production use should use external mode
  • No blob replication — blobs are stored on the local filesystem only

External mode (production)

For production deployments, use external mode with PostgreSQL, Redis, and S3-compatible storage:
DATABASE_URL="postgres://mrp:mrp@localhost:5432/mrp?sslmode=disable" \
REDIS_URL="redis://localhost:6379" \
S3_ENDPOINT="http://localhost:9000" \
S3_BUCKET="mrp-blobs" \
S3_ACCESS_KEY="minioadmin" \
S3_SECRET_KEY="minioadmin" \
./relay

Configuration

VariableRequiredDefaultDescription
DATABASE_URLYesPostgreSQL connection string
REDIS_URLYesRedis connection string
PORTNo8080HTTP server port
S3_ENDPOINTNoS3-compatible endpoint URL
S3_BUCKETNoS3 bucket name
S3_ACCESS_KEYNoS3 access key
S3_SECRET_KEYNoS3 secret key
S3_REGIONNous-east-1S3 region
TIMESTAMP_TOLERANCENo5mMax age for request timestamps
LOG_LEVELNoinfoLog level
WEBHOOK_ENCRYPTION_KEYNoEncryption key for stored webhook secrets

Docker Compose

The quickest way to get external mode running locally:
docker compose up -d   # Starts PostgreSQL, Redis, MinIO
make migrate-up        # Run database migrations
make run               # Start the relay

Pointing SDKs to your relay

All MRP SDKs accept a relay URL. Replace https://relay.mrphub.io with your self-hosted relay:
agent = Agent("http://localhost:8080", name="MyBot")

Migrating between modes

There is no built-in migration tool between embedded and external mode. For small deployments, you can export and re-import data using the API. For larger deployments, start with external mode from the beginning.