Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions DEMO.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,39 @@ Times are markers for the final edit; live run is closer to 6 minutes including

> Voiceover: *"Vault is now funded with 5 USDC. The vault PDA is just an address — there's no private key to steal."*

### 1:20–1:50 — issue MCP URL + paste into Claude
### 1:20–1:50 — issue MCP URL + connect a client

1. **MCP sessions** card → enter label `claude-desktop` → **+ New MCP URL**.
2. Click **Copy** on the new row.
3. Cut to terminal:

```bash
cat ~/.claude/claude_desktop_config.json
# paste the URL into mcpServers.aceguard.url, save, relaunch Claude.
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
# paste the bridge config below, save, fully quit + relaunch Claude.
```

Example config:
Claude Desktop only speaks stdio MCP, so we wrap the HTTP endpoint with
`mcp-remote` (community standard bridge, fetched on demand by `npx`):

```json
{
"mcpServers": {
"aceguard": {
"url": "https://x402guard.acedata.cloud/mcp/<TOKEN>"
"command": "npx",
"args": ["-y", "mcp-remote", "https://x402guard.acedata.cloud/mcp/<TOKEN>"]
}
}
}
```

4. Cut back to Claude Desktop — `aceguard_balance`, `aceguard_history`, `aceguard_spend`, `aceguard_pay_for_api` light up in the tools panel.

> Voiceover: *"Any MCP-compatible client works — Claude, Cursor, Cline, custom agents."*
> Voiceover: *"Any MCP-compatible client works. Cursor and Cline take the URL directly; Claude Desktop wraps it with a local stdio bridge. The endpoint itself is plain JSON-RPC — you can drive it from `curl` if you want."*

> 🎬 **Optional B-roll for the demo video**: split-screen the Claude
> Desktop call against a parallel `python scripts/demo.py <URL>` run in a
> terminal. Both produce the same on-chain `agent_vault.spend()` ix —
> proving the boundary lives in the program, not the client.

### 1:50–2:50 — happy-path spend

Expand Down Expand Up @@ -175,7 +182,9 @@ ffmpeg -f avfoundation -framerate 30 -i "1:0" \
| Phantom shows "transaction failed" | Page refresh, click Create vault again — backend rebuilds the same tx because the row is keyed off `vault_pda`. |
| Solana RPC times out (mainnet during peak) | Switch `VITE_SOLANA_RPC_URL` env in `web/.env` to a paid RPC (Helius / QuickNode) and rebuild. |
| `aceguard_pay_for_api` returns "on-chain spend rejected: confirm_timeout" | Retry the same prompt; nonce is freshly issued, no replay risk. |
| Claude Desktop doesn't see the tools after relaunch | Close all Claude windows + relaunch. Tool list refresh happens on app boot, not per-conversation. |
| Claude Desktop shows "MCP could not be loaded" with `{"url": "..."}` config | Switch the config to the `mcp-remote` bridge form (see Step 1:20–1:50). The `{"url": ...}` schema is for Claude.ai web Custom Connectors, not for Claude Desktop, which only speaks stdio. |
| Claude Desktop doesn't see the tools after relaunch | Fully **Cmd+Q** quit Claude (closing the window doesn't reload the MCP config), then relaunch. Tool list refresh happens on app boot, not per-conversation. |
| Suspect the endpoint itself is broken | Run `python scripts/demo.py <MCP-URL>` (or `./scripts/mcp-curl.sh`) — drives the JSON-RPC directly. If that works the endpoint is fine and the issue is client-side. |

## Post-demo cleanup

Expand Down
70 changes: 66 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,21 +181,58 @@ In the **MCP sessions** card on the vault detail page:

This URL is the **only** thing the agent ever sees. It's bound to one vault; the user can revoke it any time.

### Step 4 — Wire the URL into Claude Desktop (1 min)
### Step 4 — Connect a client to your MCP URL (1 min)

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
The MCP endpoint is plain JSON-RPC over HTTP POST. Three ways to use it,
in increasing order of "needs an LLM in the loop":

#### 4a. Verify it works at all (no client required)

Run the bundled CLI demo against your URL — it speaks JSON-RPC directly,
no MCP client / Claude / Cursor / SDK needed:

```bash
# Python (httpx + stdlib only)
python scripts/demo.py https://x402guard.acedata.cloud/mcp/<TOKEN-FROM-STEP-3>

# or with bash + curl + jq
./scripts/mcp-curl.sh https://x402guard.acedata.cloud/mcp/<TOKEN-FROM-STEP-3>
```

The script lists tools, reads on-chain balance, calls
`aceguard_pay_for_api` (full x402 dance — upstream 402 → on-chain
`agent_vault.spend()` → X-Payment retry → 200), and re-reads the balance
to confirm the spend landed. **If this passes, your endpoint is healthy
and any "MCP could not be loaded" error is a client-side problem.**

#### 4b. Claude Desktop (via the `mcp-remote` bridge)

Claude Desktop only speaks **stdio** MCP — it does not load HTTP MCP
endpoints from a `{"url": "..."}` config (that schema is for Claude.ai
web "Custom Connectors", a different product). The community-standard
bridge is `mcp-remote`:

```json
{
"mcpServers": {
"aceguard": {
"url": "https://x402guard.acedata.cloud/mcp/<TOKEN-FROM-STEP-3>"
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://x402guard.acedata.cloud/mcp/<TOKEN-FROM-STEP-3>"
]
}
}
}
```

Quit + relaunch Claude. The four tools light up:
Save to `~/Library/Application Support/Claude/claude_desktop_config.json`
(macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows). Then
**fully quit Claude (Cmd+Q, not just close the window)** and relaunch.
Requires Node ≥ 18 on `PATH` so `npx` can fetch `mcp-remote`.

The four tools light up:

| Tool | Use |
|---|---|
Expand All @@ -204,6 +241,31 @@ Quit + relaunch Claude. The four tools light up:
| `aceguard_spend` | Direct USDC transfer (low-level) |
| `aceguard_pay_for_api` | **The high-level wrapper** — give it a paid URL, it does the full x402 dance |

#### 4c. Cursor / Cline / any other HTTP-MCP-aware client

Cursor and Cline natively understand HTTP / Streamable HTTP MCP, so they
take the URL directly without a bridge. Consult that client's MCP docs
for the exact config field — it is usually `mcpServers.<name>.url` (same
shape Claude Desktop *almost* supports).

#### Or skip MCP entirely — talk to `api.acedata.cloud` from the SDK

If your goal is just to **make a paid AceDataCloud API call from your
own wallet** (without the on-chain policy enforcement that x402guard
adds), the [`@acedatacloud/x402-client`][x402client] SDK is the simpler
path: it plugs into [`@acedatacloud/sdk`][sdk] as a `payment_handler`
that signs the X-Payment header from your local key. See its
[`scripts/test-solana-e2e.ts`][solana-e2e] for a 70-line live demo.

x402guard adds value on top of that path — daily / per-call caps and
endpoint allowlists enforced **on-chain** by an Anchor program — but you
can use the SDK first to confirm the wire-format works, then graduate
to x402guard when you want the spending guardrails.

[x402client]: https://github.com/AceDataCloud/X402Client
[sdk]: https://github.com/AceDataCloud/SDK
[solana-e2e]: https://github.com/AceDataCloud/X402Client/blob/main/typescript/scripts/test-solana-e2e.ts

### Step 5 — Use it (1 min)

In Claude Desktop, ask:
Expand Down
Loading