Get started.
Erebus runs as an MCP server. Install it, give it an identity, and any client that can set environment can drive a negotiation and a shielded settlement.
Install
uv tool install --python 3.12 \
--extra-index-url https://poulavbhowmick03.github.io/Erebus/simple \
erebus-mcp-serverThat installs the MCP server, the Python binding, and the Rust binary as a platform wheel. No Rust toolchain is needed. Linux x86-64 and macOS arm64.
--python 3.12 is required, not decoration. Without it, uv uses whatever interpreter it finds and won’t download one — on a machine whose only Python is the system 3.9, the install fails with a dependency error that never mentions Python. With the flag, uv fetches a managed 3.12 itself.
To run everything with no chain, no keys, and no gas, set EREBUS_BACKEND=mock.
Set up an identity
An identity is a Starknet account plus two key files, registered with the pool and holding shielded notes. Six on-chain steps get you there, and one script does all of them:
scripts/new-identity.sh bootstrap erebus-a ~/.erebus-a <funder-account>That creates the account, funds it, deploys it, generates the pool key and extracts the account key, approves the pool for the live per-write fee, then shields 1 STRK — which also registers the identity — and runs doctor. It exits non-zero if doctor is not ready. Without a funded account to pay from, use the faucet flow instead: create, fund the printed address by hand, then activate. Both are documented in the script’s header.
Registration is irreversible and writes the identity’s pool private key, encrypted, to the pool’s auditor on-chain. From that moment the auditor can decrypt everything that identity ever does. Use a dedicated low-value identity for any mainnet canary.
Three keys come out of this, and conflating them is the usual mistake:
- Starknet account key
- Signs transactions. Custody
- Never leaves the Rust process
- Pool private key
- The STRK20 identity. Confidentiality
- Sent in compile_actions calldata to your prover and preflight RPC — both must be operator-controlled
- Pool auditor key
- Pool-wide, set once at registration
- StarkWare's, no rotation
Python never sees key material, only file paths.
Configure an identity
{
"mcpServers": {
"erebus-buyer": {
"command": "erebus-mcp-server",
"env": {
"EREBUS_BACKEND": "seam",
"EREBUS_NETWORK": "sepolia",
"EREBUS_SETTLEMENT_ROLE": "payer",
"AGENT_ADDRESS": "0x...",
"STARKNET_RPC_URL": "https://...",
"PROVING_SERVICE_URL": "https://...",
"TOKEN_ADDRESS": "0x...",
"POOL_KEY_FILE": "/home/you/.erebus-a/agent.pool.key",
"ACCOUNT_KEY_FILE": "/home/you/.erebus-a/agent.account.key",
"EREBUS_STATE_DIR": "/home/you/.erebus-a/state"
}
}
}
}A negotiation has two sides. Register the counterparty as a second entry with its own identity, state directory, and EREBUS_SETTLEMENT_ROLE=payee.
- EREBUS_BACKEND
- mock · seam
- mock drives the whole surface with no chain
- EREBUS_NETWORK
- sepolia · mainnet
- EREBUS_SETTLEMENT_ROLE
- payer · payee
- accept_and_settle spends the caller’s notes
- AGENT_ADDRESS
- 0x…
- the calling account
- STARKNET_RPC_URL
- https://…
- PROVING_SERVICE_URL
- https://…
- hosted prover
- TOKEN_ADDRESS
- 0x…
- the shielded token
- POOL_KEY_FILE
- path
- key values never cross the binding
- ACCOUNT_KEY_FILE
- path
- EREBUS_STATE_DIR
- path
- locked, mode-0600 state
- EREBUS_SPENDING_LIMITS
- JSON, optional
- per-token cap on what accept_and_settle can spend
doctor checks all of this before a write ever reaches the chain — key files and their modes, the state directory, RPC, prover, chain id, registration, allowance, and balance, each failing check naming one direct repair. Run it first when anything above is in doubt.