Skip to main content
Glama
Aaditya2502

TradeMCP

by Aaditya2502
README.md
# TradeMCP

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that exposes trading analytics — technical indicators, portfolio state, risk metrics, and backtest results — as tools an LLM agent can call. Built to demonstrate protocol-level MCP understanding, not just API wrapping.

The defining design choice: **read operations are open; write operations (placing trades) sit behind a human-in-the-loop approval gate.** Phase 1 (this repo) ships the read-only surface and the architecture that makes the read/write split clean.

---

## Why this exists

Most MCP portfolio projects wrap a public API in a decorator. This one is built around the questions that actually come up when you put an agent in front of something that can move money:

- What happens when the model sends a hallucinated symbol or malformed arguments?
- How do you stop an agent from doing something irreversible?
- How do you keep tool outputs small enough to not blow the context window?
- How do you swap simulated data for a live brokerage without rewriting the tools?

See **[DESIGN.md](./DESIGN.md)** for the full decision record.

---

## Architecture

```
┌──────────────┐   MCP (stdio / streamable HTTP)   ┌────────────────────┐
│  LLM client  │ ───────────────────────────────►  │   TradeMCP server  │
│ (Claude etc.)│ ◄───────────────────────────────  │     (server.py)    │
└──────────────┘        tool calls / results        └─────────┬──────────┘
                                                               │ depends on interface
                                                               ▼
                                              ┌──────────────────────────────┐
                                              │   MarketDataProvider (ABC)    │
                                              ├──────────────────────────────┤
                                              │ SimulatedProvider  (default)  │
                                              │ KiteProvider       (Phase 2)  │  ← live AutoTrade Bot
                                              └──────────────────────────────┘
```

| Module | Responsibility |
|---|---|
| `server.py` | Protocol/tool layer: validate input → call provider → format output |
| `data_provider.py` | Data layer behind an abstract interface (the swap point for live data) |
| `models.py` | Pydantic input schemas — the first line of defense against bad LLM input |
| `formatting.py` | Shared markdown/JSON formatting (context-efficient output) |
| `errors.py` | Centralized, *actionable* error messages |

The tool layer depends on the `MarketDataProvider` **interface**, never on a concrete data source. That dependency-inversion boundary is what lets the same server run on simulated data in CI and live data in production.

---

## Tools (Phase 1 — all read-only)

| Tool | Purpose |
|---|---|
| `trade_get_indicators` | Latest RSI / EMA / MACD / ATR + signal for a symbol |
| `trade_get_portfolio` | Holdings, cash, equity, unrealized P&L |
| `trade_get_portfolio_risk` | Concentration, beta, VaR, Sharpe, drawdown, circuit breakers |
| `trade_list_backtests` | Paginated list of backtest runs (discover run IDs) |
| `trade_get_backtest` | Full metrics for one run |

Every tool is annotated `readOnlyHint: true` and supports both `markdown` (default, human-readable) and `json` (structured) output.

---

## Quickstart

```bash
# 1. Install
pip install -e ".[dev]"

# 2. Run the test suite
pytest

# 3. Run the server (stdio transport, the default)
python -m trade_mcp.server

# Or over HTTP for remote clients:
TRADE_MCP_TRANSPORT=streamable_http TRADE_MCP_PORT=8000 python -m trade_mcp.server
```

### Inspect with the MCP Inspector

```bash
npx @modelcontextprotocol/inspector python -m trade_mcp.server
```

### Wire into Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "trade-mcp": {
      "command": "python",
      "args": ["-m", "trade_mcp.server"],
      "cwd": "/absolute/path/to/trade-mcp/src"
    }
  }
}
```

Then ask: *"What's the RSI on Reliance, and how concentrated is my portfolio?"*

---

## Data is simulated (by design)

The default `SimulatedMarketDataProvider` returns deterministic data derived from a hash of each input, so demos and tests are fully reproducible with zero credentials. Wiring in the live [AutoTrade Bot](#) backend means implementing the five `MarketDataProvider` methods in a new class and changing one line in `server.py`.

---

## Roadmap

- [x] **Phase 1** — Read-only analytics surface, provider abstraction, tests
- [ ] **Phase 2** — `trade_place_order` behind a human approval gate (Telegram confirmation + audit log)
- [ ] **Phase 3** — Rate limiting, response caching, retries
- [ ] **Phase 4** — Multi-server client demonstrating tool discovery/orchestration
- [ ] **Phase 5** — Live `KiteMarketDataProvider` wrapping the real trading bot

---

## License

MIT

TDQS

A4.6/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct area: backtest details, indicators, portfolio snapshot, portfolio risk, and backtest listing. No overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern prefixed with 'trade_' (e.g., trade_get_backtest, trade_list_backtests).

Tool Count5/5

5 tools cover the core analytical needs of a trading server: portfolio overview, risk assessment, indicators, and backtesting. Well-scoped.

Completeness4/5

The server focuses on read-only analytics; missing order placement or historical price data, but core portfolio, risk, indicators, and backtest coverage is solid.

Maintenance

ActivityInactive
ResponsivenessNo issues