Metadata-Version: 2.4
Name: mt5-mcp
Version: 0.6.3
Summary: Read-only MCP server for MetaTrader 5, built on the FastMCP v3 framework with server-decided TOON output encoding for tabular LLM payloads.
Author: Cloudmeru
License-Expression: MIT
Project-URL: Homepage, https://github.com/Cloudmeru/Metatrader-5-MCP-Server
Project-URL: Repository, https://github.com/Cloudmeru/Metatrader-5-MCP-Server
Project-URL: Changelog, https://github.com/Cloudmeru/Metatrader-5-MCP-Server/blob/main/CHANGELOG.md
Project-URL: Documentation, https://github.com/Cloudmeru/Metatrader-5-MCP-Server/blob/main/USAGE.md
Keywords: metatrader,mt5,mcp,trading,forex,llm,ai,model-context-protocol,fastmcp
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: Operating System :: Microsoft :: Windows
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 :: Investment
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastmcp-slim[server]<4,>=3.4
Requires-Dist: MetaTrader5>=5.0.0; sys_platform == "win32"
Requires-Dist: pandas>=2.0.0
Requires-Dist: matplotlib>=3.7.0
Requires-Dist: ta>=0.11.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: prophet>=1.0.0
Requires-Dist: xgboost>=2.0.0
Requires-Dist: scikit-learn>=1.3.0
Requires-Dist: scipy>=1.10.0
Requires-Dist: uvicorn>=0.27.0
Requires-Dist: starlette>=0.36.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: anyio>=4.0
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Requires-Dist: pytest-asyncio>=0.23; extra == "test"
Requires-Dist: ruff>=0.8; extra == "test"
Requires-Dist: tiktoken>=0.7; extra == "test"
Requires-Dist: tabulate>=0.9; extra == "test"
Dynamic: license-file

# MetaTrader 5 MCP Server

MetaTrader 5 integration for Model Context Protocol (MCP). Provides read-only access to MT5 market data through Python commands, built on the [FastMCP v3](https://gofastmcp.com) framework. Optionally encodes responses in [TOON](https://github.com/toon-format/toon) for LLM token savings.

## ⚡ What's New in v0.6.3

- **Production packaging fix** – The wheel now depends on `fastmcp-slim[server]>=3.4,<4` directly instead of the empty `fastmcp` meta-package. This bypasses a [known FastMCP v3 packaging hazard](https://github.com/PrefectHQ/fastmcp/issues/4207) that could leave the `fastmcp` namespace empty after a pip upgrade. Also: `MetaTrader5` is now platform-gated to Windows, so the wheel installs cleanly on Linux/macOS too (with a runtime guard that explains why the tools can't run there).

## ⚡ What's New in v0.6.2

- **TOON output encoding** – tabular tool responses (50-bar `copy_rates_from_pos`, etc.) are automatically encoded in [TOON](https://github.com/toon-format/toon) format when it would save ≥10 % of tokens over compact JSON. The LLM never has to ask for it; the server detects the shape. Install with `pip install "mt5-mcp[toon]"`.

## ⚡ What's New in v0.6.0

- **FastMCP v3** – Pinned `fastmcp>=3.0,<4`. The framework derives JSON schemas from your Python type annotations; no more string-encoded JSON parameters.
- **No more Gradio** – the experimental `gradio_server.py` and the `[ui]` extra are gone. This release is FastMCP-only.
- **Three transports in one process** – `stdio` for Claude Desktop / VS Code, Streamable HTTP on `/mcp`, and legacy SSE. `--transport all` runs them concurrently.
- **ASGI deployment** – `--asgi` emits an `app:app` for `uvicorn`, `gunicorn`, or `hypercorn`.
- **First-class middleware** – rate limiting (per-IP sliding window) and request logging live in FastMCP middleware, not in function bodies.
- **CI** – `lint` (ruff) + cross-platform `pytest` jobs on every push.
- **61 tests** – unit + integration via `fastmcp.Client`; CI runs them on Windows + Linux.

```powershell
# Default: stdio (Claude Desktop, VS Code, etc.)
python -m mt5_mcp
# or:
mt5-mcp

# Streamable HTTP with rate limiting
python -m mt5_mcp --transport http --host 0.0.0.0 --port 8000 --rate-limit 30

# All transports at once
python -m mt5_mcp --transport all --port 8000

# ASGI app for production (mount behind Uvicorn / Gunicorn / Hypercorn)
python -m mt5_mcp --asgi
```

**📖 Documentation:**
- **[USAGE.md](USAGE.md)** — Comprehensive instructions, tool reference, troubleshooting.
- **[CHANGELOG.md](CHANGELOG.md)** — Release history and migration notes from v0.5.x.
- **[docs/v0.6.0-architecture.md](docs/v0.6.0-architecture.md)** — Architecture rationale.

## Key Capabilities

- **Read-only MT5 bridge** — Safe namespace exposes only data-retrieval APIs and blocks all trading calls.
- **Transaction history access** — `history_deals_get`, `history_orders_get`, `positions_get`.
- **Multiple interaction models** — Write Python (`mt5_execute`), submit structured MT5 queries (`mt5_query`), or run full analyses with indicators, charts, and forecasts (`mt5_analyze`).
- **Technical analysis toolkit** — `ta`, `numpy`, `matplotlib` ship in the namespace for RSI, MACD, Bollinger Bands, multi-panel charts, and more.
- **Forecasting + ML signals** — Prophet forecasting and optional XGBoost buy/sell predictions with confidence scoring.
- **LLM-friendly guardrails** — Clear tool descriptions, runtime validation, and result-assignment reminders keep assistant output predictable.

## Available Tools

### `mt5_query`

Structured JSON interface that maps directly to MT5 read-only operations with automatic validation, timeframe conversion, and friendly error messages.

```json
{
  "operation": "copy_rates_from_pos",
  "symbol": "BTCUSD",
  "parameters": {"timeframe": "H1", "count": 100}
}
```

> **Tip**: `parameters` is a real JSON object in v0.6.0 — no more string-encoded JSON like the v0.5.x `"parameters": "{\"timeframe\":\"H1\"}"` form.

### `mt5_analyze`

Pipeline tool that chains a query → optional indicators → charts and/or Prophet forecasts (with optional ML signals) in one request.

```json
{
  "query": {
    "operation": "copy_rates_from_pos",
    "symbol": "BTCUSD",
    "parameters": {"timeframe": "D1", "count": 180}
  },
  "indicators": [
    {"function": "ta.trend.sma_indicator", "params": {"window": 50}},
    {"function": "ta.momentum.rsi", "params": {"window": 14}}
  ],
  "forecast": {"periods": 30, "plot": true, "enable_ml_prediction": true}
}
```

### `mt5_execute`

Free-form Python execution inside a curated namespace. Ideal for quick calculations, prototyping, and bespoke formatting.

```python
rates = mt5.copy_rates_from_pos('BTCUSD', mt5.TIMEFRAME_H1, 0, 100)
df = pd.DataFrame(rates)
df['RSI'] = ta.momentum.rsi(df['close'], window=14)
result = df[['time', 'close', 'RSI']].tail(10)
```

## Prerequisites

- **Windows OS** (MetaTrader5 library is Windows-only)
- **MetaTrader 5 terminal** installed and running
- **Python 3.10+**

## Installation

```powershell
git clone <repository-url>
cd MT5-MCP
pip install -e .
```

Optional extras:

```powershell
# Everything
pip install -e .[all]
```

The TOON token-efficient output encoder is **not bundled in this release** — the upstream `toon-format/toon-python` package has no PyPI wheel, and PyPI rejects direct-URL dependencies. The TOON heuristic in `mt5_mcp.toon_output` silently falls back to JSON when the encoder isn't installed. Vendoring the encoder is tracked for v0.6.4.

This installs:

- `fastmcp` — MCP server framework (built on the official `mcp` SDK)
- `MetaTrader5` — official MT5 Python library
- `pandas`, `numpy`, `matplotlib`, `ta` — data + charting
- `prophet`, `xgboost`, `scikit-learn` — forecasting + ML signals
- `uvicorn`, `starlette`, `httpx` — HTTP transport
- `pydantic` — request/response validation

## Configuration

### Claude Desktop (stdio)

Add to your Claude Desktop configuration file at `%APPDATA%\Claude\claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "mt5": {
      "command": "python",
      "args": ["-m", "mt5_mcp"]
    }
  }
}
```

Or, if `mt5-mcp` is on your PATH:

```json
{
  "mcpServers": {
    "mt5": {
      "command": "mt5-mcp",
      "args": []
    }
  }
}
```

For logging:

```json
{
  "mcpServers": {
    "mt5": {
      "command": "python",
      "args": ["-m", "mt5_mcp", "--log-file", "C:\\path\\to\\mt5_mcp.log"]
    }
  }
}
```

### HTTP MCP Clients

```json
{
  "mcpServers": {
    "mt5-http": {
      "url": "http://localhost:8000/mcp/"
    }
  }
}
```

Works with MCP Inspector, Claude Desktop (HTTP mode), VS Code extensions, and any remote deployment.

### ASGI / Production

```bash
python -m mt5_mcp --asgi          # prints "app:app" hint
uvicorn mt5_mcp.__main__:app --host 0.0.0.0 --port 8000 --workers 2
```

The lifespan context is wired in, so FastMCP startup/shutdown runs correctly under multi-worker Uvicorn.

## CLI

```
python -m mt5_mcp [--transport stdio|http|sse|all] [--host HOST] [--port PORT]
                  [--path PATH] [--rate-limit N]
                  [--log-level LEVEL] [--log-file FILE]
                  [--asgi]
```

| Flag | Default | Description |
|---|---|---|
| `--transport` | `stdio` | One of `stdio`, `http`, `sse`, `all` |
| `--host` | `127.0.0.1` | Host for HTTP/SSE transports |
| `--port` | `8000` | Port for HTTP/SSE transports |
| `--path` | `/mcp` | URL path for the HTTP endpoint |
| `--rate-limit` | `10` | Requests per IP per minute (`0` disables) |
| `--log-level` | `INFO` | One of `DEBUG`, `INFO`, `WARNING`, `ERROR` |
| `--log-file` | — | Write logs to this file in addition to stderr |
| `--asgi` | — | Emit ASGI app handle (don't actually run the server) |

## TOON Output Encoding (Token-Efficient for LLMs) — *experimental*

> **Status:** the shape-detection heuristic and the `format_response()`
> entry point ship in this release, but the upstream
> `toon-format/toon-python` encoder has no PyPI wheel, so PyPI rejects
> our `Requires-Dist: toon_format @ https://...` reference. The
> heuristic silently falls back to JSON until the encoder is vendored
> (tracked for v0.6.4). The code, tests, and savings measurement below
> are the design target.

The server is designed to automatically encode tabular tool responses in [TOON](https://github.com/toon-format/toon) — a line-oriented, indentation-based format designed for LLM contexts. TOON declares array shapes once (`[N]` count + `{field1,field2,...}` column list) and uses indentation instead of braces, so tabular payloads (MT5 rate bars, indicator values, transaction history) are 20–40 % smaller than compact JSON.

**The LLM doesn't choose. The server detects the shape and applies TOON only when it helps.** There is no `output_format` or `wire_format` parameter on any tool.

### Enable TOON

```powershell
pip install "mt5-mcp[toon]"
```

This installs [`toon-format/toon-python`](https://github.com/toon-format/toon-python) — the canonical Python implementation of the TOON spec. The package's PyPI distribution is a stub; the `[toon]` extra pulls the real release directly from GitHub.

### What the LLM sees

When the response contains a uniform array of ≥5 dicts in the `data` field AND encoding it as TOON saves ≥10 % of tokens vs. compact JSON, the server replaces that array with a TOON string and adds a sibling marker:

```json
{
  "operation": "copy_rates_from_pos",
  "success": true,
  "metadata": {"symbol": "BTCUSD", "timeframe": "H1", "count": 50},
  "data_format": "toon",
  "data": "data[50]{time,close,vol}:\n  1700000000,63000.0,0\n  1700003600,63010.0,100\n  ..."
}
```

The `"data_format": "toon"` marker tells the LLM the `data` field is a TOON document (decode with any TOON library, or call back through `mt5_query` to round-trip).

When the heuristic doesn't fire — single dicts, small arrays, heterogeneous rows, error envelopes, non-tabular shapes — the response is unchanged compact JSON. No surprises.

`mt5_execute` is intentionally excluded from the TOON heuristic: its output is already a pre-formatted text string (markdown tables, JSON snippets, plain text) that is more universally parseable than TOON.

### Measured savings (o200k_base tokens)

| Response shape | JSON | TOON | Saved |
|---|---:|---:|---:|
| `copy_rates` 50 bars (embedded as TOON) | 3,171 | 2,391 | **24.6 %** |
| `copy_rates` 200 bars (embedded as TOON) | 12,585 | 9,405 | **25.3 %** |
| `mt5_analyze` 20 rows + indicators | 956 | 673 | **29.6 %** |
| `mt5_execute` 30 rows | 709 | 564 | **20.5 %** |
| **Representative total** | **17,656** | **13,295** | **24.7 %** |

Tiny responses (`symbol_info` lookups, error envelopes) cost 1–3 extra tokens because TOON's `[N]` array header is overhead on objects with one or two keys. The heuristic keeps those as JSON automatically.

## Architecture & Compliance

- Built on FastMCP v3 (a thin wrapper around the official `mcp` Python SDK).
- Safe execution namespace exposes vetted objects (`mt5`, `datetime`, `pd`, `ta`, `numpy`, `matplotlib`) while blocking trading calls and disallowed modules.
- Runtime validation catches `mt5.initialize()` / `mt5.shutdown()` attempts and highlights the correct workflow.
- Thread-safe MT5 connection management plus IP-scoped rate limiting (HTTP/SSE only).
- Three concerns live in dedicated layers:
  - **`mcp_server.py`** — the `FastMCP` instance and middleware wiring
  - **`mcp_tools.py`** — the three tool functions
  - **`middleware.py`** — cross-cutting rate-limit + logging

## Troubleshooting

### FastMCP Install Hazard (`cannot import name 'FastMCP' from 'fastmcp'`)

If you see `ImportError: cannot import name 'FastMCP' from 'fastmcp' (unknown location)`
when running `mt5-mcp`, the underlying `fastmcp` package directory is empty. This is a
[known packaging hazard in FastMCP v3](https://github.com/PrefectHQ/fastmcp/issues/4207)
caused by pip's install/upgrade sequence — the `fastmcp` meta-package can wipe
files written by its companion `fastmcp-slim` package, leaving an empty namespace.

Recovery (one-time):

```powershell
pip uninstall -y fastmcp fastmcp-slim
pip install mt5-mcp
```

Or, if you prefer to keep using the legacy `pip install --upgrade mcp` workflow
that triggered the issue:

```powershell
pip install --force-reinstall fastmcp-slim==3.4.7
```

`mt5-mcp` v0.6.3+ depends directly on `fastmcp-slim[server]>=3.4,<4`, so fresh
installs skip this path entirely.

### MT5 Connection Issues

1. **Ensure MT5 terminal is running** before starting the MCP server.
2. **Enable algo trading** in MT5: *Tools → Options → Expert Advisors → Allow automated trading*.
3. **Check MT5 terminal logs** for any errors.

### Enable Logging

```powershell
python -m mt5_mcp --log-file mt5_debug.log
```

Or configure it in the Claude Desktop config (see *Configuration* above).

### Common Errors

**"MT5 connection error: initialize() failed"**
- MT5 terminal is not running.
- MT5 is not installed.
- Algo trading is disabled in MT5.

**"Symbol not found"**
- Check symbol name spelling (case-sensitive).
- Symbol may not be available in your MT5 account.
- Use `mt5_query` with `operation: symbols_get` to list available symbols.

**"No data returned"**
- Symbol may not have historical data for the requested period.
- Check date range validity.
- Some symbols may have limited history.

**"Rate limit exceeded"**
- HTTP/SSE transport only. Increase `--rate-limit`, or set `0` to disable.
- Stdio transport is single-process and is never rate-limited.

## Security

This server provides **read-only** access to MT5 data. Trading functions are explicitly excluded from the safe namespace:

### Blocked Functions

- `order_send()` — Place orders
- `order_check()` — Check order
- `positions_get()` — Get positions (read-only but blocked to prevent confusion)
- `positions_total()` — Position count
- All order/position modification functions

Only market data and information retrieval functions are available.

## License

MIT License

## Contributing

Contributions are welcome! Please ensure:

1. All code follows the read-only philosophy
2. Tests pass (`pytest -q`)
3. Documentation is updated
4. CI lint passes (`ruff check src tests`)
