Skip to main content
Glama
dgb-tools
by dgb-tools
README.md
# dgb-digidollar-mcp

> ⚠️ **TESTNET ONLY — PROOF OF CONCEPT.** This is experimental software for the
> DigiByte testnet. It moves no real money and is not audited. Do not point it at
> mainnet or a wallet holding real funds. The testnet-only guard is on by default.

An [MCP](https://modelcontextprotocol.io) server that lets an AI agent (Claude, etc.)
pay for a service in **DigiDollar** — DigiByte's collateral-backed, USD-denominated
stablecoin — following the [x402](https://x402.org) pay-and-retry pattern:

1. Agent requests a service → service replies `402 Payment Required` with a DigiDollar address + price.
2. Agent calls **`pay_invoice`** → this server checks the operator's spend policy, then pays.
3. Agent calls **`payment_status`** → confirms the tx landed, then retries the request.

The agent never holds keys. The wallet and the spend caps live here, on the operator's
machine. **Allowance, not custody.**

## Why DigiDollar, and why this settles the "did I get paid in DD?" question

Agent payments need **stable pricing** — nobody wants an API call that costs 30%
more because the token moved. That's why the rest of the agent economy settles in
USDC. But USDC has an issuer-level blacklist, and Base has a single sequencer:
two kill switches. DigiDollar has neither — it's minted against locked DGB
collateral on a proof-of-work L1, with no freeze function in the protocol.

**DGB secures it. DigiDollar spends it.**

The obvious worry for a merchant is: *"how do I know I was paid in DigiDollar and
not just bare DGB sent to the same address?"* It turns out the protocol makes that
impossible by construction:

- DigiDollar has its **own address type** (`DD` / `TD` / `RD` prefix), distinct from `dgb1…`/`dgbt1…`.
- It has its **own UTXO set** (`listdigidollarutxos`, `getdigidollarbalance`).
- A plain DGB address **fails `validateddaddress` outright** — this server refuses to send to one.

So DD and DGB cannot be confused. A merchant checking `getdigidollarbalance` /
`listdigidollarutxos` is, by definition, seeing DigiDollar.

Amounts, one sharp edge worth knowing: `senddigidollar` reads an **integer as cents**
but a **decimal as dollars** (`10000` = $100, `10000.00` = $10,000). This server always
converts to integer cents internally so that 100x foot-gun can't fire.

## Architecture

```
Your machine                               Your node host
┌─────────────────────────┐                ┌──────────────────────────┐
│ Claude ── MCP server ───┼── SSH tunnel ──┼─> digibyted (testnet26)  │
│           (this repo)   │  :14026        │   RPC 127.0.0.1:14026    │
└─────────────────────────┘                └──────────────────────────┘
```

The node's RPC is bound to localhost on the node host and never exposed to the
internet. `tunnel.sh` forwards a local port to it over SSH (key-only auth
recommended). If you run the node on the same machine as the MCP server, you can
skip the tunnel and point `DGB_RPC_URL` straight at the local node.

## Try it yourself

You provide your own node and your own keys — that's the point. Nothing here is
hosted; there is no shared server to trust.

**1. Run a DigiByte DigiDollar testnet node.** Install DigiByte Core
[v9.26.4+](https://github.com/DigiByte-Core/digibyte/releases) and start it on
testnet with RPC enabled. Minimal `digibyte.conf`:

```ini
testnet=1
server=1
[test]
rpcbind=127.0.0.1
rpcallowip=127.0.0.1
rpcuser=YOUR_RPC_USER
rpcpassword=YOUR_STRONG_RPC_PASSWORD
```

Let it sync testnet26 (the DigiDollar test network). Confirm with
`digibyte-cli -datadir=... getblockchaininfo` → `"chain": "test"`.

**2. Create a wallet and get some testnet DGB.**

```bash
digibyte-cli -datadir=... createwallet mcp-sandbox
digibyte-cli -datadir=... -rpcwallet=mcp-sandbox getnewaddress
```

Paste that address into the **[DigiByte testnet faucet](http://154.12.247.176:8080)**
and it'll send you free tDGB. (Testnet coins are worthless by design — they exist
so you can build and break things without risking anything.)

**3. Mint some DigiDollar.** DD doesn't exist until someone locks DGB collateral to
create it. Check what you'd need, then mint:

```bash
# what collateral does $100 of DD cost at lock tier 0 (1 hour)?
digibyte-cli -datadir=... -rpcwallet=mcp-sandbox estimatecollateral 10000 0

# mint $100 (amount is in CENTS; tier 0 = 1h lock, tiers run 0-9 up to 10 years)
digibyte-cli -datadir=... -rpcwallet=mcp-sandbox mintdigidollar 10000 0
```

Heads-up: the short tiers are heavily over-collateralised (tier 0 is ~1000%), so
$100 of DD locks roughly 390,000 tDGB at current prices. Longer locks need less.
The faucet won't give you that much in one go — either claim over a few days, ask
in the DigiByte community, or use a longer lock tier.

**4. Configure and self-test.**

```bash
npm install
cp .env.example .env      # fill in your RPC user/password (+ SSH host if remote)
./tunnel.sh &             # only if the node is on another host; leave running
npm run smoke             # connectivity + policy self-test — moves no funds
```

**5. Connect it to Claude.** Add the server to your MCP client config (see
`claude-config-snippet.json`, with the paths adjusted to where you cloned this).
Then ask the agent to check the balance and pay a small testnet invoice. Watch
the policy layer block anything over your caps.

## Tools

| Tool | What it does |
|------|--------------|
| `check_balance` | DigiDollar balance (USD) + DGB balance + node sync + current policy state. |
| `pay_invoice` | Send `amountUsd` of **DigiDollar** to a DD address, subject to policy. Returns txid. |
| `pay_invoice_dgb` | Secondary path: pay in plain DGB instead. Separate caps. |
| `payment_status` | Confirmation count for a txid (the x402 retry gate). |

## Safety policy (`.env`)

- `DGB_REQUIRE_TESTNET=true` — server refuses to run unless the node reports `chain=test`.
- `DD_MAX_PAYMENT_USD` / `DD_MAX_DAILY_USD` — DigiDollar caps, in US dollars.
- `DGB_MAX_PAYMENT` / `DGB_MAX_DAILY` — separate caps for the raw-DGB path.

DigiDollar and DGB get **separate ledgers and separate caps** — a dollar and a DGB
are not interchangeable units, so they are never netted against each other.

## Roadmap

- [x] **Milestone 1** — pay in plain testnet DGB (`sendtoaddress`).
- [x] **Milestone 2** — pay in **DigiDollar** (`senddigidollar`), USD-denominated, with
      DD-address validation. Proven live on testnet26.
- [ ] **Milestone 3** — a 402 merchant library: emit invoices, watch for DD payment, ship on confirm.
- [ ] **Milestone 4** — publish to the MCP registry.

## Help wanted

**Milestone 3** is where collaboration is most welcome: the **merchant side**. A
drop-in library so any service can emit a `402 Payment Required` with a DigiDollar
invoice, watch for the payment, and deliver on confirmation. Issues and PRs welcome.

## Status

Proven live on testnet26 — an AI agent paid **$2.50 and $1.25 in DigiDollar** to a
merchant wallet (confirmed on-chain), while the policy layer correctly blocked a
payment over the cap and refused to send DigiDollar to a bare DGB address.

This is a rough proof of concept, not production software. It should never touch
mainnet or real funds.

## More

- Install: `npm i -g dgb-digidollar-mcp` (or `npx dgb-digidollar-mcp`)
- The merchant side: [dgb-x402](https://github.com/dgb-tools/dgb-x402)
- Query the chain: [dgb-chain-mcp](https://github.com/dgb-tools/dgb-chain-mcp)
- Background: [the write-up](https://medium.com/@sapidseoblog/i-asked-claude-about-digibytes-digidollar-supply-ed064140a29f) · [DigiByte-Core discussion](https://github.com/orgs/DigiByte-Core/discussions/426)

Built for the DigiByte community. Testnet only. Not financial software.