Metadata-Version: 2.4
Name: worm-mcp
Version: 0.1.0
Summary: MCP server for Worm prediction markets on Solana
Project-URL: Homepage, https://worm.wtf
Project-URL: Documentation, https://docs.worm.wtf
Project-URL: Repository, https://github.com/wormwtf/worm-mcp
Project-URL: Issues, https://github.com/wormwtf/worm-mcp/issues
Author-email: Worm <support@worm.wtf>
License-Expression: MIT
License-File: LICENSE
Keywords: mcp,prediction-markets,solana,trading,worm
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.25
Requires-Dist: mcp>=1.2.0
Requires-Dist: worm-sdk[signing]>=0.9.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">
  <img src="https://www.worm.wtf/images/logo.png" alt="Worm" width="110px" />
  <h1>Worm MCP</h1>
  <p>Browse, trade, and manage prediction markets from any AI agent.</p>
  <p>
    🌐 <a href="https://worm.wtf">Worm</a> &nbsp;·&nbsp;
    📖 <a href="https://docs.worm.wtf">Docs</a> &nbsp;·&nbsp;
    📦 <a href="https://github.com/wormwtf/worm-sdk">worm-sdk</a> &nbsp;·&nbsp;
    🐛 <a href="https://github.com/wormwtf/worm-mcp/issues">Issues</a> &nbsp;·&nbsp;
    ⚖️ <a href="LICENSE">MIT</a>
  </p>
  <p>
    <a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="Python 3.10+" /></a>
    <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
  </p>
</div>

## Installation

worm-mcp runs over stdio; your MCP client launches it on demand. Set `WALLET_PRIVATE_KEY` to enable authenticated and trading tools, or omit it to use only the public, read-only tools.

Pick the flow that fits you:

- **[For users](#for-users)**: you just want to use the tool in your MCP client. Your client launches it with `uvx`; no manual install.
- **[For developers](#for-developers)**: you want to modify the code. Clone the repo and run it from a local editable install.

### For users

Your client launches worm-mcp on demand; `uvx` fetches and runs it for you.

**Claude Code**: register it once from the CLI; `--scope user` makes it available in every project:

```bash
claude mcp add --scope user worm \
  -e WALLET_PRIVATE_KEY=<base58-solana-private-key> \
  -- uvx worm-mcp
```

Confirm with `claude mcp list` (shows `worm … ✓ Connected`).

**Cursor**: add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project), then enable it under **Settings → MCP**:

```json
{
  "mcpServers": {
    "worm": {
      "command": "uvx",
      "args": ["worm-mcp"],
      "env": { "WALLET_PRIVATE_KEY": "<base58-solana-private-key>" }
    }
  }
}
```

**Claude Desktop**: **Settings → Developer → Edit Config** opens `claude_desktop_config.json`; add the same `mcpServers` block and restart the app.

**Smithery**: [Smithery](https://smithery.ai) installs it into a supported client with one command (it runs locally over stdio, so your key stays on your machine):

```bash
npx -y @smithery/cli install worm-mcp --client claude
```

**Other clients** (Windsurf, Cline, Zed, VS Code, …): same launch: command `uvx`, args `["worm-mcp"]`, plus the `WALLET_PRIVATE_KEY` env. Only the config file location differs.

> No `uv`? `pipx run worm-mcp` or `pip install worm-mcp` work too.

### For developers

Run worm-mcp from a local clone, for hacking on the code or running an unpublished build. Clone and set up an editable environment:

```bash
git clone https://github.com/wormwtf/worm-mcp.git
cd worm-mcp
uv venv
uv pip install -e ".[dev]"
uv run ruff check src
WALLET_PRIVATE_KEY=... worm-mcp     # run the stdio server directly
```

Point your client at the editable checkout so code changes take effect on the next client restart. Either add `--with-editable` to the uvx launch:

```bash
claude mcp add --scope user worm \
  -e WALLET_PRIVATE_KEY=<base58-solana-private-key> \
  -- uvx --from /path/to/worm-mcp --with-editable /path/to/worm-mcp worm-mcp
```

…or point the client's `command` straight at the venv binary the editable install creates (`args` can be omitted):

```json
{
  "mcpServers": {
    "worm": {
      "command": "/path/to/worm-mcp/.venv/bin/worm-mcp",
      "env": { "WALLET_PRIVATE_KEY": "<base58-solana-private-key>" }
    }
  }
}
```

## Verify

Ask your client *"List trending markets on Worm"* (public) or *"What's my Worm account summary?"* (confirms auth): a sensible answer means it's wired up.

## Requirements

- An MCP client (Claude Code, Cursor, Claude Desktop, …)
- [`uv`](https://docs.astral.sh/uv/) (or `pipx` / `pip`)
- A funded Solana wallet (only for trading and other authenticated tools)

## Environment variables

| Variable | Required | Purpose |
|---|---|---|
| `WALLET_PRIVATE_KEY` | for writes | Base58 Solana private key (the export from Phantom/Solflare; a 64-byte hex keypair also works). Signs transactions locally and bootstraps HMAC credentials on first run, cached in `~/.worm/config.json`. |
| `WORM_API_KEY` / `WORM_API_SECRET` | no | Use existing HMAC credentials instead of bootstrapping |
| `WORM_API_BASE` | no | API base URL (default `https://api.worm.wtf`) |

## Tools

### Public (no credentials)

| Tool | Description |
|---|---|
| `search` | Search markets and events by text and filters |
| `list_markets` | Browse markets by category, state, or sort |
| `get_market` | Full market detail (outcomes, fees, config, state) |
| `get_market_stats` | Volume, market cap, and trade count |
| `get_market_price` | Mid-price snapshot for an outcome |
| `get_orderbook` | Spot orderbook bids and asks |
| `get_market_candles` | OHLCV candles (5m / 30m) |
| `get_market_trades` | Recent public trades |
| `get_market_margin_activity` | Public margin activity feed |
| `list_events` | Browse events (groups of related markets) |
| `get_event` | Full event detail with all markets |
| `list_sports` | Sports and leagues catalog |
| `estimate_margin_position` | Preview a leveraged position |
| `read_worm_docs` | Fetch Worm documentation pages |

### Authenticated read (HMAC)

| Tool | Description |
|---|---|
| `get_account_summary` | Your profile |
| `get_account_assets` | Portfolio share balances |
| `get_account_pnl` | PnL breakdown |
| `list_orders` / `get_order` | Your spot orders |
| `list_trades` | Your trade fills |
| `list_margin_positions` / `get_margin_position` | Your margin positions |
| `list_margin_requests` / `get_margin_request` | Your margin position requests |
| `list_margin_settlements` | Margin settlements |
| `list_redeems` / `get_redeem` | Your redeem records |
| `list_api_keys` | Your API keys |

### Authenticated write (HMAC)

| Tool | Description |
|---|---|
| `cancel_margin_request` | Cancel a pending margin request |
| `close_margin_position` | Close a margin position |
| `set_tp_sl` / `remove_tp_sl` | Set / clear take-profit and stop-loss |
| `claim_margin_settlement` | Claim a resolved settlement |
| `revoke_api_key` | Revoke an API key |

### Authenticated write: local signing (needs `WALLET_PRIVATE_KEY`)

| Tool | Description |
|---|---|
| `place_order` / `cancel_order` | Place / cancel a spot order |
| `open_margin_position` | Open a leveraged position |
| `redeem` | Redeem winnings from a resolved market |

## Notes for agents

- **Spot vs margin**: `place_order` is for non-margin (orderbook) markets; use `open_margin_position` when `margin_enabled=true`. Margin markets quote against an AMM, so `get_orderbook` may be empty; size with `estimate_margin_position`.
- **Margin lifecycle**: `open_margin_position` returns a *position-request* pubkey; the actual position appears via `list_margin_positions` (match `position_request_pubkey`) once funding completes. TP/SL is unsupported on Hyperliquid-backed markets.
- **Leverage**: always call `estimate_margin_position` and confirm with the user before opening; leverage carries liquidation risk.
- **Docs on demand**: call `read_worm_docs` with no arguments for the index, then pass a path for exact API schemas and examples.

## Features

- 38 tools across markets, events, search, sports, account, orders, trades, margin, redeems, key management, and docs
- Local Solana keypair signing, so your private key never leaves the MCP process
- Auto-bootstrapped HMAC credentials: set one env var and the rest is automatic
- Public market data works with no credentials at all
- Built on the official [`worm-sdk`](https://pypi.org/project/worm-sdk/), with full type hints

## Architecture

```
┌──────────────┐  stdio   ┌────────────┐  HTTPS + HMAC  ┌──────────────┐
│  MCP client  │ ◀──────▶ │  worm-mcp  │ ◀────────────▶ │  Worm API    │
│ (Claude etc.)│          │  (Python)  │                │ api.worm.wtf │
└──────────────┘          └─────┬──────┘                └──────────────┘
                                │ ed25519 signing (orders, margin, redeems)
                                ▼
                          worm-sdk + solders (local keypair)
```

See [rate limits](https://docs.worm.wtf/api-reference/rate-limits) in the docs. Markets are viewable at `https://worm.wtf/market/{condition_id}`.

## Security

- Your private key is used only to sign transactions locally; it is never sent to the Worm API or any third party.
- Bootstrapped HMAC credentials are cached at `~/.worm/config.json` with `0600` permissions, keyed by API base URL and wallet, so multiple wallets or environments (e.g. `WORM_API_BASE` overrides) each keep their own credentials instead of clobbering one another. Writes are atomic and locked, so concurrent clients can't corrupt or lose cached credentials.
- Use a dedicated wallet funded with only what you intend to trade, and keep the key out of version control and shared configs.

## Troubleshooting

- **`uvx: command not found`**: install [`uv`](https://docs.astral.sh/uv/), or use `pipx run worm-mcp` / `pip install worm-mcp`.
- **Tools don't appear**: fully restart the client; it spawns the server once at startup. In Claude Code, check `claude mcp list`.
- **Authentication errors**: confirm `WALLET_PRIVATE_KEY` is a valid base58 Solana key; delete `~/.worm/config.json` to force a fresh credential bootstrap.
