Metadata-Version: 2.4
Name: cycles4sale-mcp
Version: 0.1.3
Summary: MCP server for the cycles4sale cycles marketplace on the Internet Computer — monitor supply/demand and trade + move funds non-custodially, signed locally with icp-cli.
Author: onicai
License: MIT
Project-URL: Homepage, https://cycles-4-sale.com
Keywords: mcp,internet-computer,icp,cycles,marketplace,agent
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Topic :: Office/Business :: Financial
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: mcp>=1.2.0
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"

# cycles4sale-mcp

An [MCP](https://modelcontextprotocol.io) server that lets an AI agent interact with the
**cycles4sale** cycles marketplace on the Internet Computer — live at
**[cycles-4-sale.com](https://cycles-4-sale.com)**.

It exposes two tiers as one `uvx` command:

- **Monitor (read-only)** — watch supply, demand, prices and the order book. No identity, no funds.
- **Trade** — buy and sell cycles and move ICP / cycles, **non-custodially**. Every call is signed
  locally by your own [icp-cli](https://internetcomputer.org/) identity; the key never leaves your machine
  and the canister only ever pulls the live allowance you approve.

## Requirements

- Python 3.10+
- [`icp` (icp-cli)](https://internetcomputer.org/docs) on your `PATH` — the server shells out to it for
  every canister call and for signing. (`--read-only` still needs `icp` for the public queries, but no
  identity and no funds.)
- [`uv` / `uvx`](https://docs.astral.sh/uv/) to run it without a manual install (optional).

## Quick start

### Monitor the market (no funds, no identity)

```bash
uvx cycles4sale-mcp --read-only
```

Only the monitor tools are registered: `market_snapshot`, `quote`, `order_book`, `whoami`.

### Trade (needs an icp-cli identity + funds)

```bash
# Creates the identity if it doesn't exist and prints its principal:
uvx cycles4sale-mcp --identity my-agent \
    --max-icp-per-trade 50000000 \
    --daily-icp-budget 200000000
```

Fund the printed principal by sending it ICP (to buy) and/or cycles (to sell) — ICRC-1, null
subaccount. **The funded balance is the hard ceiling**: the agent can never spend more than you put on
that identity, and the caps below tighten it further.

## Wiring it into an MCP client

Add the server to your client config (stdio transport). Example for a Claude-style `mcpServers` block:

```json
{
  "mcpServers": {
    "cycles4sale": {
      "command": "uvx",
      "args": ["cycles4sale-mcp", "--identity", "my-agent", "--max-icp-per-trade", "50000000"]
    }
  }
}
```

For a read-only feed, use `"args": ["cycles4sale-mcp", "--read-only"]`.

### Streamable HTTP

To serve over HTTP (endpoint `/mcp`) instead of stdio:

```bash
uvx cycles4sale-mcp --read-only --http --host 127.0.0.1 --port 8080
# -> http://127.0.0.1:8080/mcp
```

## Tools

**Monitor (always available):**

| Tool              | What it returns                                                                          |
| ----------------- | ---------------------------------------------------------------------------------------- |
| `market_snapshot` | Supply, demand, lifetime volume, the discount/fee rates, and buyer/seller eff. discounts |
| `quote`           | Live ICP price (and fee, seller proceeds) to buy `num_lots` whole lots                    |
| `order_book`      | Current listings and open buy orders                                                     |
| `whoami`          | The agent identity, mode, configured caps, and session spend                             |

**Trade + wallet (only when not `--read-only`):**

| Tool                  | What it does                                                       |
| --------------------- | ----------------------------------------------------------------- |
| `my_positions`        | Your listing, open buy order, and ICP + cycles balances           |
| `buy`                 | Buy cycles by committing up to `max_icp_e8s` of ICP               |
| `sell`                | List `num_lots` whole lots of your cycles for sale (`0` delists)   |
| `cancel_buy`          | Cancel your open buy order and revoke the ICP allowance           |
| `cancel_listing`      | Cancel your listing and revoke the cycles allowance               |
| `balances`            | Your ICP (e8s) and cycles balances                                |
| `send_icp`            | Send ICP to a principal                                           |
| `send_cycles`         | Send cycles to a principal                                        |
| `deposit_to_canister` | Withdraw cycles as REAL cycles onto a canister (top up its fuel)   |
| `receive_address`     | Your agent principal — fund the agent by sending ICP/cycles to it |

## Guardrails

| Flag                         | Effect                                                                        |
| ---------------------------- | ----------------------------------------------------------------------------- |
| `--read-only`                | Registers only the monitor tools; no identity, no funds.                      |
| `--max-icp-per-trade E8S`    | Rejects any single ICP outflow (buy / `send_icp`) larger than this.           |
| `--daily-icp-budget E8S`     | Rejects ICP outflows once the session's cumulative total would exceed this.   |
| `--dry-run`                  | Trade + wallet tools return the planned approve/call instead of executing it. |

The daily budget is an in-process counter and resets when the server restarts. Trades are
non-custodial: `buy`/`sell` `approve` exactly what's needed to the broker, call, then revoke the
standing allowance when nothing rests.
