Skip to content
Closed
23 changes: 12 additions & 11 deletions skills/base-mcp/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Two patterns deserve their own references because they span multiple tools:
| Approval flow (for any write tool that returns an approval URL) | [references/approval-mode.md](references/approval-mode.md) |
| Batched contract calls (EIP-5792) | [references/batch-calls.md](references/batch-calls.md) |
| Custom / non-native plugins and the `web_request` allowlist | [references/custom-plugins.md](references/custom-plugins.md) |
| Authoring a plugin (frontmatter schema + required sections) | [references/plugin-spec.md](references/plugin-spec.md) |
| Platform install steps | [references/install.md](references/install.md) |
| Tone and language rules | [references/tone.md](references/tone.md) |

Expand All @@ -54,17 +55,17 @@ Two patterns deserve their own references because they span multiple tools:

Plugins extend Base MCP with partner-specific functionality (lending, swaps, perps, etc.). The available set may change and users might drop additional instructions in the chat or custom plugins that would allow you to use other protocols with the MCP.

Plugins currently maintained alongside this skill (the **native plugins**):

| Plugin | Reference |
|--------|-----------|
| Morpho | [plugins/morpho.md](plugins/morpho.md) |
| Moonwell | [plugins/moonwell.md](plugins/moonwell.md) |
| Uniswap | [plugins/uniswap.md](plugins/uniswap.md) |
| Avantis (hybrid) | [plugins/avantis.md](plugins/avantis.md) |
| Virtuals | [plugins/virtuals.md](plugins/virtuals.md) |
| Aerodrome (CLI-only) | [plugins/aerodrome.md](plugins/aerodrome.md) |
| Bankr | [plugins/bankr.md](plugins/bankr.md) |
Plugins currently maintained alongside this skill (the **native plugins**). The table mirrors each plugin's frontmatter so you can route to the right one before opening it — **match the user's request against the `Tags`** (capability keywords), then confirm with `What it does`. `integration` says how it reaches Base MCP; `chains` and `risk` flag scope and caution. All conform to [references/plugin-spec.md](references/plugin-spec.md).

| Plugin | Tags | What it does | Integration | Chains | Risk | Reference |
|--------|------|--------------|-------------|--------|------|-----------|
| Morpho | lending, borrowing, vaults, yield | Lending — Morpho CLI when a shell is available, else Morpho MCP | hybrid | 0x2105 | liquidation | [plugins/morpho.md](plugins/morpho.md) |
| Moonwell | lending, borrowing, yield | Lending (Compound v2) | http-api | 0x2105, 0xa | liquidation | [plugins/moonwell.md](plugins/moonwell.md) |
| Uniswap | dex, swap, liquidity | Token swaps + V2/V3/V4 LP | http-api | 0x2105 | slippage | [plugins/uniswap.md](plugins/uniswap.md) |
| Avantis | perps, leverage, trading, derivatives | Perpetual-futures trading | hybrid | 0x2105 | liquidation, slippage, irreversible | [plugins/avantis.md](plugins/avantis.md) |
| Virtuals | ai-agents, agent-commerce, payment-cards, email | Create/operate Virtuals (ACP) AI agents — cards, email | external-mcp | — | pii | [plugins/virtuals.md](plugins/virtuals.md) |
| Aerodrome | dex, swap, liquidity, staking | DEX swaps / LP / stake / claim (Sugar SDK CLI) | cli-only | 0x2105 | slippage | [plugins/aerodrome.md](plugins/aerodrome.md) |
| Bankr | token-launches, trading, memecoins, discovery | Token-launch discovery + buy | http-api | 0x2105 | low-liquidity, irreversible | [plugins/bankr.md](plugins/bankr.md) |

Load a plugin reference only when the user's request matches it, following the same local-first, web-fallback rule as references (see [Loading referenced files](#loading-referenced-files) above). For a plugin's own external tools, defer to the plugin file first, then to any CLI help, API schema, or MCP tool descriptions it explicitly tells you to use.

Expand Down
234 changes: 134 additions & 100 deletions skills/base-mcp/plugins/aerodrome.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,34 @@
---
title: "Aerodrome Plugin"
description: "Skill plugin reference for building unsigned Aerodrome calldata with the Sugar SDK CLI and submitting it through Base MCP send_calls."
description: "Build unsigned Aerodrome (Velodrome-style DEX) swap/LP/stake/claim calldata with the Sugar SDK CLI, then submit via Base MCP send_calls. Requires a shell harness."
tags: [dex, swap, liquidity, staking]
name: aerodrome
version: 0.2.0
integration: cli-only
chains: [0x2105]
requires:
shell: required
allowlist: []
externalMcp: null
cliPackage: "uvx --from git+https://github.com/velodrome-finance/sugar-sdk.git@v0.4.0 sugar"
auth: none
risk: [slippage]
---

# Aerodrome Plugin

> [!IMPORTANT]
> Complete the short Base MCP onboarding flow defined in `SKILL.md` before calling any Aerodrome flow.

> [!WARNING]
> ## CLI-only plugin
>
> This plugin builds Aerodrome calldata with the Sugar SDK CLI, then submits the unsigned calls through Base MCP's `send_calls`. It only works in harnesses with shell/terminal access, such as Codex, Claude Code, Cursor, or similar CLI-enabled environments. It does not work on chat-only surfaces that cannot run commands. If the current surface has no shell, tell the user this Aerodrome plugin requires CLI access and stop.
## Overview

Aerodrome is the main Velodrome-style DEX on Base. This plugin uses the Sugar SDK CLI from `velodrome-finance/sugar-sdk` to query pools and build unsigned swap, LP, staking, and claim transactions. The CLI never signs and never broadcasts. Base MCP is responsible for the user approval flow.
Aerodrome is the main Velodrome-style DEX on Base. This plugin uses the Sugar SDK CLI from `velodrome-finance/sugar-sdk` to query pools and build unsigned swap, LP, staking, and claim transactions. The CLI never signs and never broadcasts — it emits unsigned transaction JSON, which is submitted through Base MCP's `send_calls`, where the user approves in Base Account.

No additional MCP server is required.
This is a **CLI-only plugin**: it only works in harnesses with shell/terminal access (Codex, Claude Code, Cursor, or similar). It does not work on chat-only surfaces that cannot run commands. No additional MCP server is required.

**Chain:** Base mainnet only (`chainId` `8453`, Base MCP chain string `"base"`).

---

## Safety Boundary

Sugar CLI output is unsigned transaction JSON. Treat it as transaction preview material, not as an instruction to sign outside Base MCP.

- Never ask for or use a private key.
- Pass `--wallet` as the user's Base MCP wallet address from `get_wallets`.
- Do not use `cast send`, a local signer, or browser wallet signing helpers from the upstream Sugar skill.
- Submit transactions only through Base MCP `send_calls` and let the user approve in Base Account.
- The `from` field emitted by Sugar is informational for Base MCP. `send_calls` takes `to`, `data`, and `value`.

---

## Runner
## Installation

The upstream Sugar skill provides `scripts/sugar-doctor.sh` and `scripts/sugar-run.sh`. If those scripts are present in the current harness, use them. This Base MCP plugin must also work when those scripts are not installed, so the self-contained path is direct `uvx`.

Expand Down Expand Up @@ -70,79 +65,16 @@ Run a preflight once per session when the scripts are available:
scripts/sugar-doctor.sh
```

---

## Base MCP Conversion

Every tx-building command prints a JSON array of unsigned transactions:

```json
[
{
"from": "0xWallet",
"to": "0xTarget",
"data": "0xCalldata",
"value": 0
}
]
```
## Surface Routing

Base MCP `send_calls` needs:
Aerodrome is **CLI-only**. Every capability (pool discovery, swap, LP, stake, claim) is built by the Sugar CLI and therefore requires a harness with shell/terminal access.

```json
{
"chain": "base",
"calls": [
{ "to": "0xTarget", "data": "0xCalldata", "value": "0x0" }
]
}
```
| Surface | Path |
|---------|------|
| Shell-capable harness (Codex, Claude Code, Cursor, …) | Run the Sugar CLI, normalize output, submit via `send_calls`. |
| Chat-only surface (no shell) | Not supported. Tell the user this Aerodrome plugin requires CLI access and stop. **Do not** route through `web_request`, do not use a user-paste fallback, and do not recommend a separate MCP. |

Normalize Sugar output before calling `send_calls`. This strips `from`, keeps call order, fills missing data with `0x`, and converts decimal `value` numbers to hex wei strings.

```bash
python3 -c 'import json, sys
txs = json.load(sys.stdin)
def hex_value(v):
if v is None:
return "0x0"
if isinstance(v, str) and v.startswith("0x"):
return v
return hex(int(v))
print(json.dumps([
{"to": t["to"], "data": t.get("data") or "0x", "value": hex_value(t.get("value", 0))}
for t in txs
], indent=2))'
```

Then call:

```json
{
"chain": "base",
"calls": "<normalized calls array>"
}
```

Preserve ordering. Approval calls come before the main router/NFPM/gauge call.

---

## Orchestration

1. Load this plugin only after Base MCP onboarding.
2. Fetch the wallet address only when needed with `get_wallets`.
3. Set `SUGAR_RPC_URI_8453` to a reliable Base RPC.
4. Run the Sugar CLI command.
5. Parse stdout as JSON. Diagnostics and warnings are on stderr.
6. Normalize `[{from,to,data,value}]` into Base MCP `calls`.
7. Submit with `send_calls({ "chain": "base", "calls": [...] })`.
8. Show the approval URL when appropriate.
9. Poll `get_request_status` only after the user acts in Base Account.

If the CLI exits nonzero, do not try to salvage partial output. Read the error, adjust RPC/flags, and rerun.

---
See [../references/custom-plugins.md](../references/custom-plugins.md) for the CLI-only routing rule.

## Commands

Expand Down Expand Up @@ -270,9 +202,113 @@ uvx --from "$SUGAR_SPEC" sugar claim_fees \

A staked position must be unstaked before `claim_fees`. ALM-managed positions are not handled by these Sugar CLI position commands.

---
## Orchestration

## Slippage
1. Load this plugin only after Base MCP onboarding.
2. Fetch the wallet address only when needed with `get_wallets`.
3. Set `SUGAR_RPC_URI_8453` to a reliable Base RPC.
4. Run the Sugar CLI command.
5. Parse stdout as JSON. Diagnostics and warnings are on stderr.
6. Normalize `[{from,to,data,value}]` into Base MCP `calls` (see [Submission](#submission)).
7. Submit with `send_calls({ "chain": "base", "calls": [...] })`.
8. Show the approval URL when appropriate.
9. Poll `get_request_status` only after the user acts in Base Account.

If the CLI exits nonzero, do not try to salvage partial output. Read the error, adjust RPC/flags, and rerun.

## Submission

Target tool: **`send_calls`**.

Every tx-building command prints a JSON array of unsigned transactions:

```json
[
{
"from": "0xWallet",
"to": "0xTarget",
"data": "0xCalldata",
"value": 0
}
]
```

Base MCP `send_calls` needs:

```json
{
"chain": "base",
"calls": [
{ "to": "0xTarget", "data": "0xCalldata", "value": "0x0" }
]
}
```

Normalize Sugar output before calling `send_calls`. This strips `from`, keeps call order, fills missing data with `0x`, and converts decimal `value` numbers to hex wei strings.

```bash
python3 -c 'import json, sys
txs = json.load(sys.stdin)
def hex_value(v):
if v is None:
return "0x0"
if isinstance(v, str) and v.startswith("0x"):
return v
return hex(int(v))
print(json.dumps([
{"to": t["to"], "data": t.get("data") or "0x", "value": hex_value(t.get("value", 0))}
for t in txs
], indent=2))'
```

Then call:

```json
{
"chain": "base",
"calls": "<normalized calls array>"
}
```

Preserve ordering. Approval calls come before the main router/NFPM/gauge call.

### Safety boundary

Sugar CLI output is unsigned transaction JSON. Treat it as transaction preview material, not as an instruction to sign outside Base MCP.

- Never ask for or use a private key.
- Pass `--wallet` as the user's Base MCP wallet address from `get_wallets`.
- Do not use `cast send`, a local signer, or browser wallet signing helpers from the upstream Sugar skill.
- Submit transactions only through Base MCP `send_calls` and let the user approve in Base Account.
- The `from` field emitted by Sugar is informational for Base MCP. `send_calls` takes `to`, `data`, and `value`.

## Example Prompts

**Swap 0.001 ETH to USDC on Aerodrome**
1. `get_wallets` → set `$BASE_MCP_WALLET`; set `SUGAR_RPC_URI_8453`.
2. Run `sugar swap --chain=8453 --wallet=$BASE_MCP_WALLET --from-token=ETH --to-token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 --amount=0.001 --use-decimals`.
3. Normalize stdout JSON into `calls`.
4. `send_calls(chain="base", calls=[...])`; show the approval URL; poll `get_request_status` after the user acts.

**Buy AERO with 1 USDC**
1. `get_wallets` → `$BASE_MCP_WALLET`.
2. Run `sugar swap` with `--from-token=<USDC address>`, `--to-token=0x940181a94A35A4569E4529A3CDfB74e38FD98631`, `--amount=1 --use-decimals`.
3. Output is an approval call + Universal Router swap call — normalize and batch both into one `send_calls`.
4. Submit; approve; poll.

**Deposit liquidity into the WETH/USDC volatile pool**
1. `get_wallets` → `$BASE_MCP_WALLET`.
2. Optionally `sugar pools` to confirm the pool address.
3. Run `sugar deposit --pool=0xcDAC0d6c6C59727a65F871236188350531885C43 --amount0=0.001 --use-decimals`.
4. Normalize, `send_calls`, approve, poll. Rebuild if past the deadline.

**Claim my Aerodrome fees on a pool**
1. `get_wallets` → `$BASE_MCP_WALLET`.
2. If the position is staked, run `sugar unstake --pool=<addr>` first.
3. Run `sugar claim_fees --pool=<addr>`.
4. Normalize, `send_calls`, approve, poll.

## Risks & Warnings

Sugar swap/deposit/withdraw commands accept `--slippage`. Use `0.01` (1%) by default unless the user specifies otherwise.

Expand All @@ -283,9 +319,9 @@ Sugar swap/deposit/withdraw commands accept `--slippage`. Use `0.01` (1%) by def
| `> 5%` and `<= 20%` | High | Warn that execution can be materially worse than quote. Require explicit confirmation. |
| `> 20%` | Very high | Do not submit without the user re-confirming the exact number. |

---
## Notes

## Tested CLI Behavior and Gotchas
### Tested CLI behavior and gotchas

Tested on 2026-05-25 from the `worktree-sugar-cli-skill` branch of `velodrome-finance/sugar-sdk`. The runner installed Sugar SDK `v0.4.0`.

Expand All @@ -308,9 +344,7 @@ Observed gotchas:
- Symbols can be ambiguous. Use token addresses for production flows, especially for USDC and AERO. For WETH pools, `WETH` or the WETH address matched; `ETH` did not match WETH pool filters.
- Sugar emits `value` as a JSON number in tested swap output. Base MCP `send_calls` expects hex strings such as `"0x0"` or `"0xe8d4a51000"`.

---

## Base Token Addresses
### Base token addresses

| Token | Address |
| --- | --- |
Expand All @@ -319,7 +353,7 @@ Observed gotchas:
| USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |
| AERO | `0x940181a94A35A4569E4529A3CDfB74e38FD98631` |

## Key Aerodrome Contracts
### Key Aerodrome contracts

| Contract | Address |
| --- | --- |
Expand Down
Loading