check_spend on the contract before it is signed, and every approval is recorded immutably on-chain. Your agent cannot bypass these limits even if it tries to modify its own environment, and you get a transparent audit trail of every spend decision.
Off-chain vs on-chain limits
| Off-chain (env vars) | On-chain (Soroban contract) | |
|---|---|---|
| Setup | Set MAX_PER_CALL and MAX_PER_DAY in config | Deploy once with deploy_policy |
| Enforcement | In-process, before signing | Smart contract call before every payment |
| Audit trail | None | Every check recorded on Stellar ledger |
| Bypass risk | Agent with env access could modify limits | Cryptographically enforced — cannot be bypassed in-process |
| Update limits | Edit config and restart | Call set_policy_limits — no redeploy |
| Build required | No | No — WASM ships inside the npm package |
POLICY_CONTRACT_ID in your MCP config, the env var limits (MAX_PER_CALL, MAX_PER_DAY) are ignored for enforcement. The contract’s on-chain values are the authoritative caps.
The policy WASM (
policy.wasm) is bundled inside the nebula-mcp npm package under dist/contracts/. No separate build or CLI step is needed to deploy it.Deploying your policy
Deploy the policy contract
Ask your agent to deploy a new Nebula uploads the bundled WASM, deploys the contract, and initializes it with your limits. The tool returns a contract ID starting with
nebula-policy Soroban contract with your desired limits. Amounts are in XLM/USDC units:C.Example output:Copy the POLICY_CONTRACT_ID
Copy the contract address from the tool output — it starts with
C and is 56 characters long.Add the contract ID to your MCP config
Open your MCP config and paste the contract ID into the
POLICY_CONTRACT_ID env field:Keep
MAX_PER_CALL and MAX_PER_DAY in your config even after setting POLICY_CONTRACT_ID. These values are used as fallbacks during startup validation, but the contract’s on-chain values are what Nebula enforces at runtime.Restart Claude
Quit and reopen Claude Desktop (or reload your MCP host). Nebula connects to the contract on startup.
Updating limits without redeploying
You can change your per-call or daily cap on the existing contract at any time — no new deployment required. Only the wallet that deployed the contract (the owner) can update limits:Checking current spend
Useget_policy_status at any time to see your on-chain limits and rolling usage:
spending_report for a combined view of both off-chain and on-chain limits:
What is and is not limited
On-chain policy limits apply to all agent-initiated outgoing payments:transfer_xlmandtransfer_usdc— checked per transactionx402_fetch— checked before each paymentmpp_open_session— the full budget is checked when the channel opens
x402 Payments
Understand how x402 payments interact with your spending caps.
Connect to Claude
Set up your MCP config and environment variables from scratch.