Metadata-Version: 2.4
Name: new-tasty-trade-mcp
Version: 0.1.1
Summary: MCP server for the Tastytrade Open API
Author: nzhou
License-Expression: MIT
License-File: LICENSE
Keywords: claude,mcp,model-context-protocol,tastytrade,trading
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: mcp>=1.2
Requires-Dist: python-dotenv>=1.0
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# new-tasty-trade-mcp

An MCP server exposing the [Tastytrade Open API](https://developer.tastytrade.com/) to an
LLM host (Claude Code, Claude Desktop, Cursor, …). Read-only account & market-data tools
plus **guarded** live-trading tools (two-phase orders, size caps, audit log).

Published on [PyPI](https://pypi.org/project/new-tasty-trade-mcp/) — run it anywhere with
`uvx`; no clone or local venv required. (The Python import name is `tastytrade_mcp`.)

## Requirements

- Python 3.10+
- A Tastytrade OAuth app with a **refresh token** and **client secret**. Create it at
  my.tastytrade.com → Manage → My Profile → API → OAuth Applications, and **select the
  `read` and `trade` scopes** when creating the client/grant (without them the API returns
  `403 insufficient scopes`).

## Register with Claude Code

`uvx` fetches the package on demand, so there's nothing to install up front:

```bash
claude mcp add tastytrade \
  -e TASTY_ACCOUNT_NUMBER=... \
  -e TASTY_CLIENT_SECRET=... \
  -e TASTY_REFRESH_TOKEN=... \
  -- uvx new-tasty-trade-mcp
```

Restart Claude Code and the tools appear.

### Other MCP clients (Claude Desktop, Cursor, Cline, …)

Add this to your `mcpServers` config (same shape across clients):

```json
{
  "mcpServers": {
    "tastytrade": {
      "command": "uvx",
      "args": ["new-tasty-trade-mcp"],
      "env": {
        "TASTY_ACCOUNT_NUMBER": "...",
        "TASTY_CLIENT_SECRET": "...",
        "TASTY_REFRESH_TOKEN": "..."
      }
    }
  }
}
```

Optional `env` overrides:
- `TASTY_MAX_ORDER_NOTIONAL_USD` — reject orders above this notional (Limit orders only).
- `TASTY_MAX_QUANTITY` — reject orders above this total leg quantity.
- `TASTY_LOG_FILE` — audit-log path (default `tastytrade-mcp-trades.log` in the working
  directory). Set an absolute path to place it elsewhere.

## Tools

**Account (read):** `get_accounts`, `get_account`, `get_balances`, `get_positions`,
`get_orders`, `get_order`, `get_transactions`, `get_trading_status`, `get_nlv_history`.

**Market (read):** `get_quote`, `get_option_chain`, `get_market_metrics`,
`search_symbols`, `get_equity`.

**Trading (guarded):** `dry_run_order`, `place_order` (two-phase: `execute=false` previews,
`execute=true` submits after the size-cap check), `modify_order`, `cancel_order`.

### Trading guardrails

- **Two-phase:** `place_order` always dry-runs first; it submits only when `execute=true`.
- **Size caps:** `TASTY_MAX_QUANTITY` and `TASTY_MAX_ORDER_NOTIONAL_USD`; orders over a cap
  are rejected *before* submission. Leave unset for no cap.
- **Audit log:** every place/modify/cancel (success or failure) and every dry-run appends a
  JSON line to `TASTY_LOG_FILE`.

## Run directly (stdio)

```bash
uvx new-tasty-trade-mcp          # from anywhere
# or, installed in a venv:
python -m tastytrade_mcp
```

## Development

Editable install from a clone (includes `pytest`, `build`, `twine`):

```bash
venv/bin/pip install -e 'mcp/tastytrade[dev]'
```

Common tasks via the Makefile (run from `mcp/tastytrade/`, or `make -C mcp/tastytrade …`
from the repo root):

```bash
make test       # run the suite (httpx.MockTransport — no network, no live account)
make build      # clean -> test -> build wheel + sdist into dist/
make publish    # build -> twine upload (uses ~/.pypirc)
make install    # editable install with dev extras
make clean      # remove build/ and dist/
```

Re-publishing: bump `version` in `pyproject.toml`, then `make publish` (PyPI won't accept
the same version twice).
