Skip to main content
Glama
README.md
<p align="center">
  <img src="https://raw.githubusercontent.com/vikrambtech2025-png/alpaka-mcp/main/assets/banner.png" alt="alpaka-mcp banner" width="100%" />
</p>

<h1 align="center">🦙 alpaka-mcp</h1>

<p align="center">
  <strong>Trade US stocks, ETFs, and crypto through AI assistants and the terminal</strong>
</p>

<p align="center">
  <a href="https://github.com/vikrambtech2025-png/alpaka-mcp/actions"><img src="https://github.com/vikrambtech2025-png/alpaka-mcp/workflows/CI/badge.svg" alt="CI"></a>
  <a href="https://github.com/vikrambtech2025-png/alpaka-mcp/blob/main/LICENSE"><img src="https://img.shields.io/github/license/vikrambtech2025-png/alpaka-mcp" alt="License"></a>
  <img src="https://img.shields.io/badge/python-3.11+-blue" alt="Python 3.11+">
  <img src="https://img.shields.io/badge/mcp-server-brightgreen" alt="MCP Server">
  <a href="https://alpaca.markets"><img src="https://img.shields.io/badge/alpaca-py-0.30+-orange" alt="alpaca-py"></a>
</p>

<p align="center">
  16 MCP tools &bull; 12 CLI commands &bull; Rate limiting &bull; Retry &bull; Structured logging &bull; Live trading guard
</p>

---

## What is this?

**alpaka-mcp** is a production-ready MCP server + CLI that connects AI assistants (Claude Desktop, Cursor, VS Code Copilot) and your terminal directly to the [Alpaca Trading API](https://alpaca.markets). Trade stocks, ETFs, and crypto with natural language — or from the command line.

Built on [alpaca-py](https://github.com/alpacahq/alpaca-py) and the [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk).

> **Defaults to paper trading** — real market data, simulated funds, zero real money at risk.

---

## Quick Start

### 1. Get Alpaca API Keys (free)

Sign up at **[alpaca.markets](https://alpaca.markets)** → Paper Trading → API Keys

### 2. Install

```bash
git clone https://github.com/vikrambtech2025-png/alpaka-mcp.git
cd alpaka-mcp
uv sync
```

### 3. Configure

```bash
cp .env.example .env
# Add your API keys to .env
```

### 4. Run

```bash
uv run alpaka-mcp          # MCP server (stdio for Claude/Cursor)
uv run alpaka account      # CLI — check account
uv run mcp dev src/alpaka_mcp/server.py  # MCP Inspector
```

---

## Connect to AI Assistants

<details>
<summary><strong>Claude Desktop</strong></summary>

Add to `%AppData%\Claude\claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "alpaka": {
      "command": "uv",
      "args": ["--directory", "C:\\path\\to\\alpaka-mcp", "run", "alpaka-mcp"],
      "env": {
        "ALPACA_API_KEY": "your_key",
        "ALPACA_SECRET_KEY": "your_secret",
        "ALPACA_PAPER": "true"
      }
    }
  }
}
```
</details>

<details>
<summary><strong>Cursor</strong></summary>

Add to `.cursor/mcp.json` in your project root:

```json
{
  "mcpServers": {
    "alpaka": {
      "command": "uv",
      "args": ["--directory", "/path/to/alpaka-mcp", "run", "alpaka-mcp"],
      "env": {
        "ALPACA_API_KEY": "your_key",
        "ALPACA_SECRET_KEY": "your_secret",
        "ALPACA_PAPER": "true"
      }
    }
  }
}
```
</details>

<details>
<summary><strong>VS Code</strong></summary>

Add to `.vscode/mcp.json`:

```json
{
  "servers": {
    "alpaka": {
      "command": "uv",
      "args": ["--directory", "/path/to/alpaka-mcp", "run", "alpaka-mcp"],
      "env": {
        "ALPACA_API_KEY": "your_key",
        "ALPACA_SECRET_KEY": "your_secret",
        "ALPACA_PAPER": "true"
      }
    }
  }
}
```
</details>

---

## MCP Tools (16)

<table>
<tr><th>Account</th><th>Trading</th><th>Positions</th></tr>
<tr>
<td valign="top">

| Tool | Description |
|------|-------------|
| `get_account` | Balance, equity, buying power, day trades |
| `get_portfolio` | All open positions with P&L |

</td>
<td valign="top">

| Tool | Description |
|------|-------------|
| `buy` | Place buy order (market/limit/stop/stop-limit) |
| `sell` | Place sell order (market/limit) |
| `get_orders` | List orders by status and symbols |
| `cancel_order` | Cancel a specific order |
| `cancel_all_orders` | Cancel all open orders |

</td>
<td valign="top">

| Tool | Description |
|------|-------------|
| `get_position` | Single position details |
| `close_position` | Liquidate (full or partial) |

</td>
</tr>
</table>

<table>
<tr><th>Stock Data</th><th>Crypto Data</th><th>Discovery</th></tr>
<tr>
<td valign="top">

| Tool | Description |
|------|-------------|
| `get_stock_quote` | Latest bid/ask quote |
| `get_stock_bars` | Historical OHLCV bars |
| `get_stock_snapshot` | Full snapshot (trade, quote, daily, 1-min) |

</td>
<td valign="top">

| Tool | Description |
|------|-------------|
| `get_crypto_quote` | Latest crypto bid/ask |
| `get_crypto_bars` | Historical crypto OHLCV bars |

</td>
<td valign="top">

| Tool | Description |
|------|-------------|
| `search_assets` | Search stocks/ETFs/crypto by name or symbol |
| `get_market_clock` | Market open/close status |

</td>
</tr>
</table>

---

## CLI Commands (12)

```bash
alpaka account                    # Account balance & buying power
alpaka portfolio                  # Open positions with color-coded P&L
alpaka quote AAPL                 # Bid/ask quote (stocks or crypto)
alpaka buy AAPL --qty 10          # Buy 10 shares
alpaka buy BTC/USD -n 500         # Buy $500 of Bitcoin
alpaka sell AAPL --qty 5          # Sell 5 shares
alpaka orders                     # List open orders
alpaka orders --status closed     # List filled orders
alpaka cancel <order-id>          # Cancel specific order
alpaka cancel-all                 # Cancel everything open
alpaka bars AAPL --tf 1Day        # Historical bars
alpaka clock                      # Is the market open?
alpaka search apple               # Find tradeable assets
```

**All commands support `--json` for machine-readable output:**

```bash
$ uv run alpaka account --json
{
  "status": "ACTIVE",
  "equity": "100000.00",
  "buying_power": "200000.00",
  "cash": "100000.00",
  "portfolio_value": "100000.00",
  "daytrade_count": 0,
  "pattern_day_trader": false,
  "mode": "paper"
}
```

---

## Production Features

| Feature | How It Works |
|---------|-------------|
| **Resilient Client** | Transparent proxy wraps every API call with rate limiting + retry |
| **Rate Limiting** | 3 independent token buckets (200 req/min each) — trading, stock data, crypto |
| **Retry + Backoff** | 3 attempts with 1s/2s/4s exponential backoff on 429, 500, connection errors |
| **Non-Blocking Async** | MCP tools use `asyncio.to_thread()` — event loop never blocks |
| **Structured Logging** | JSON audit trail: `logs/trades.jsonl` + `logs/errors.jsonl` |
| **Input Validation** | Symbols, quantities, prices, order types validated before API calls |
| **Live Trading Guard** | Requires `ALPACA_LIVE_CONFIRM=true` + 5s countdown for real money |
| **Config Validation** | Rejects placeholder API keys with clear setup instructions |
| **Thread Safety** | `lru_cache` client initialization, no mutable global state |
| **CLI Error Handling** | Every command wrapped — clean errors, no tracebacks |

---

## Architecture

```
src/alpaka_mcp/
├── server.py          # MCP server entry point (stdio)
├── cli.py             # 12 Typer commands + JSON output
├── config.py          # pydantic-settings + credential validation
├── clients.py         # ResilientClient proxy (rate limit + retry + async)
├── utils.py           # Response formatting
├── logging.py         # Structured JSON logging
├── rate_limiter.py    # Token bucket rate limiters (sync + async)
├── retry.py           # Exponential backoff (sync + async)
├── validation.py      # Input validation
└── tools/             # 16 MCP tools
    ├── account.py     # get_account, get_portfolio
    ├── trading.py     # buy, sell, get_orders, cancel_order, cancel_all
    ├── positions.py   # get_position, close_position
    ├── stock_data.py  # get_stock_quote, get_stock_bars, get_stock_snapshot
    ├── crypto_data.py # get_crypto_quote, get_crypto_bars
    └── discovery.py   # search_assets, get_market_clock
```

---

## Docker

```bash
# MCP server
docker compose up alpaka-mcp

# CLI via docker
docker compose run --rm alpaka-cli account
docker compose run --rm alpaka-cli portfolio
```

Logs persist in a Docker volume at `/app/logs`.

---

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `ALPACA_API_KEY` | **(required)** | Your Alpaca API key |
| `ALPACA_SECRET_KEY` | **(required)** | Your Alpaca secret key |
| `ALPACA_PAPER` | `true` | Paper trading mode |
| `ALPACA_LIVE_CONFIRM` | `false` | Must be `true` for live trading |
| `ALPACA_LOG_DIR` | `logs` | Log file directory |
| `ALPACA_LOG_LEVEL` | `INFO` | Logging verbosity |

---

## Testing

```bash
# Unit tests (no API keys needed)
uv run pytest tests/ --ignore=tests/test_integration.py -v

# Integration tests (needs real paper API keys)
ALPACA_API_KEY=pk_xxx ALPACA_SECRET_KEY=sk_xxx uv run pytest tests/test_integration.py -v
```

---

## Safety

- **Paper trading by default** — real money requires explicit opt-in
- Live trading requires both `ALPACA_PAPER=false` AND `ALPACA_LIVE_CONFIRM=true`
- 5-second countdown on live trading startup
- All errors formatted cleanly — no tracebacks sent to LLMs
- Rate limiting prevents accidental API abuse
- Structured audit trail for every trade

---

## License

MIT

---

<p align="center">
  Built with care by <a href="https://github.com/vikrambtech2025-png">Vikram</a>
</p>