MT5 MCP Server
# MT5 MCP Server
[](LICENSE)
[](pyproject.toml)
[](#requirements)
[](.github/workflows/test.yml)
**Let your AI assistant trade MetaTrader 5 — safely.**
An [MCP](https://modelcontextprotocol.io) server that gives AI assistants (Claude Desktop, Claude Code, ZCode, Cursor, ...) full access to a MetaTrader 5 terminal: market data, indicators, order placement, position management and trade history — with a **dry-run safety mode that is ON by default**.
```
You: "What's my account status?"
AI: Balance $10,000 · Equity $10,050 · 1 open XAUUSD position (+$12.40)
You: "Buy 0.1 lots XAUUSD with stop loss at 2390"
AI: ✓ Validated: volume 0.1 ✓ Filling mode FOK ✓ Within MT5_MAX_VOLUME
⚠ Dry-run mode is ON — no real order sent. Set MT5_DRY_RUN=false to trade.
```
## Highlights
- 🔒 **Dry-run by default** — every order tool validates and previews without sending. Real trading is one env var away, never an accident.
- 🛡 **Guard rails** — volume rounded to the symbol's lot step, capped by `MT5_MAX_VOLUME`, human-readable error messages for every MT5 return code (no more mystery retcode 10016).
- 📊 **Built-in indicators** — SMA, EMA, RSI, ATR computed from candles, no extra dependencies.
- ⚖️ **Risk-based lot sizing** — `calculate_lot_size` tells you exactly how many lots to risk 1% of your account.
- 🔌 **Two connection modes** — attach to your already-running terminal, or log in via environment variables.
- ✅ **Tested** — 30+ tests run against a simulated MT5 terminal, so the whole suite passes even without MT5 installed.
## Requirements
- **Windows** (the MetaTrader5 Python package is Windows-only) + a MetaTrader 5 terminal installed and logged in
- **"Algo Trading" enabled** in the MT5 terminal (button in the toolbar)
- Python 3.10+
## Quick start
### 1. Install
```bash
pip install mt5-mcp-server
```
Or with [uv](https://docs.astral.sh/uv/):
```bash
uvx mt5-mcp-server
```
### 2. Add to your MCP client
**Claude Desktop** — `%APPDATA%\Claude\claude_desktop_config.json` (full example in [examples/](examples/)):
```json
{
"mcpServers": {
"mt5": {
"command": "mt5-mcp-server",
"env": {
"MT5_DRY_RUN": "true",
"MT5_LOGIN": "12345678",
"MT5_PASSWORD": "your-password",
"MT5_SERVER": "YourBroker-Server"
}
}
}
}
```
**Claude Code / ZCode:**
```bash
claude mcp add mt5 --env MT5_DRY_RUN=true -- mt5-mcp-server
```
> Leave `MT5_LOGIN` out to attach to whichever account is already logged in
> inside the running terminal.
### 3. Try it (safe — dry-run is on)
Ask your assistant: *"What's my account balance?"* then *"Buy 0.1 lots XAUUSD"*. You will get a validated **preview**, not a real order.
### 4. Enable real trading
Set `"MT5_DRY_RUN": "false"` in the config. **Test on a demo account first.**
## Configuration
| Variable | Default | Meaning |
|---|---|---|
| `MT5_DRY_RUN` | `true` | **Order tools only preview, never send.** Set to `false` for real trading. |
| `MT5_MAX_VOLUME` | `10` | Hard cap on order volume in lots (safety net). |
| `MT5_LOGIN` | — | Account number. Without it, the server uses the terminal's logged-in account. |
| `MT5_PASSWORD` | — | Account password (only with `MT5_LOGIN`). |
| `MT5_SERVER` | — | Broker server name, e.g. `MetaQuotes-Demo`. |
| `MT5_PATH` | — | Path to `terminal64.exe` if the terminal is not running or not in the default location. |
| `MT5_DEVIATION` | `20` | Max slippage in points for market orders. |
| `MT5_MAGIC` | `0` | Magic number attached to orders placed by the AI. |
## Tools
**Account** — `get_account_info` · `get_terminal_info`
**Market data** — `search_symbols` · `get_symbol_info` · `get_tick` · `get_candles` (M1→MN1) · `get_indicator` (SMA / EMA / RSI / ATR)
**Portfolio** — `get_positions` (live P/L) · `get_pending_orders` · `get_history` (net profit, wins/losses per symbol)
**Orders** — `place_market_order` · `place_pending_order` (limit/stop) · `close_position` (full or partial) · `modify_position` (SL/TP) · `modify_pending_order` · `cancel_pending_order`
**Risk** — `calculate_lot_size` (position size from risk % + stop loss)
## Safety model
1. **Dry-run first**: `MT5_DRY_RUN=true` (default) validates the order against symbol rules and returns exactly what *would* be sent.
2. **Volume guard**: lots are rounded down to the symbol's step and capped by `MT5_MAX_VOLUME`; volumes below the symbol minimum are rejected.
3. **Clear errors**: every broker rejection is translated into plain language (retcode 10016 → *"SL/TP is too close to the price or on the wrong side"*).
4. **No keys in code**: credentials go in MCP client env config, never in the repository.
⚠️ **Trading involves risk.** This software is provided as-is, with no warranty. Always test on a **demo account** first. The authors are not responsible for trading losses.
## Example session
> **User:** What's my exposure right now?
>
> **AI:** *(calls `get_positions`)* You have 2 open positions: 0.10 XAUUSD buy (+$12.40) and 0.05 EURUSD sell (−$3.10). Floating P/L: **+$9.30**.
>
> **User:** Close half of the gold position.
>
> **AI:** *(calls `close_position` ticket=X, volume=0.05)* ✓ Closed 0.05 lots at 2401.10. Remaining: 0.05 lots.
## Development
```bash
git clone https://github.com/Erfangit23/mt5-mcp-server
cd mt5-mcp-server
pip install -e ".[dev]"
pytest -v
```
Tests run against a simulated MT5 terminal ([tests/fake_mt5.py](tests/fake_mt5.py)) — no MT5 installation needed. To verify the MCP handshake with a real terminal, run `python scripts/smoke_test.py`.
## راهنمای سریع (فارسی)
۱. نصب: `pip install mt5-mcp-server`
۲. در کلود دسکتاپ، فایل `claude_desktop_config.json` را مثل بالا تنظیم کنید.
۳. حالت **Dry-Run** بهصورت پیشفرض روشن است؛ هیچ معامله واقعی انجام نمیشود.
۴. برای معامله واقعی: `MT5_DRY_RUN` را `false` کنید — اول روی حساب **دمو** تست کنید.
۵. دکمه **Algo Trading** در ترمینال MT5 باید فعال باشد.
## Roadmap
- [ ] Streaming tick prices (MCP subscriptions)
- [ ] Chart screenshots via terminal
- [ ] MACD / Bollinger Bands indicators
- [ ] Linux support via Wine bridge
## License
[MIT](LICENSE) — use it, fork it, ship it.
TDQS
Scored across 17 tools
Most tools have clearly distinct roles (market data, order management, account info), but get_tick duplicates the bid/ask already present in get_symbol_info, creating a minor overlap. Other pairs like get_positions/get_pending_orders and modify_position/modify_pending_order are well separated by their descriptions.
All tools use consistent snake_case with a clear verb_noun pattern (get_, search_, place_, close_, modify_, cancel_, calculate_). No mixing of conventions or vague verbs.
With 17 tools, the set is slightly above the ideal 3–15 range, but each tool covers a distinct MT5 operation (terminal/account info, symbol data, candles, indicators, positions, pending orders, trade execution, risk sizing). The count is borderline but justified for a trading server.
The surface covers account/terminal info, symbol lookup, market data, indicators, full position/order lifecycle (place, modify, close, cancel), history, and lot sizing. Minor gaps like trailing stops or margin requirement checks exist, but the core trading workflow is complete.