mt5-httpapi
MetaTrader 5 running inside a real Windows VM (Docker + QEMU/KVM) with REST and MCP APIs slapped on top. No Wine bullshit, no janky compatibility hacks — the real Windows MT5 terminal in portable mode, controllable without clicking through that fucking GUI all day.
Run multiple brokers, accounts, and cloned terminal instances at the same time. Each one gets its own Python API process inside the VM, while nginx puts the whole mess behind one port at http://localhost:8888/<broker>/<account>/....
Contents
- What this fucker does
- Requirements
- Quick start
- Architecture
- Where the fuck is everything documented?
- API at a glance
- Development
- Project layout
- Recommended brokers and prop firms
- License
[!WARNING] This thing can trade real money. If your algo buys the top and detonates your account, that shit is on you. Start with demo accounts and test the fucker properly.
What this fucker does
- Real MT5 on real Windows — no Wine, no pretending, no compatibility-layer roulette.
- As many brokers, accounts, and terminal clones as your machine can stomach — all behind one nginx port.
- The useful MT5 shit over HTTP — terminal state, market data, orders, positions, history, and Strategy Tester jobs.
- Built-in technical analysis — wickworks calculates indicators and SMC primitives server-side without exposing its own port.
- MCP for the robot overlords — one endpoint per terminal or one unified endpoint for the whole pile, plus Claude Code, Codex, and OpenClaw integrations.
- Optional multi-VM fuckery — spread terminals across VMs or NUMA nodes, then reach them through Tailscale or Cloudflare Tunnel if you need to.
Requirements
- Linux with KVM available at
/dev/kvm - Docker with Docker Compose
- About 20 GB of disk for the ISO, VM, and MT5 installations
- Enough RAM for however hard you plan to abuse the Windows VM; the default low-memory setup leans heavily on host swap
MT5 hoards loaded chart history like a greedy little bastard and does not give the memory back. Deep history scraping can blow each terminal up to several gigabytes, so read the actual sizing details before hammering it.
Quick start
git clone https://github.com/psyb0t/mt5-httpapi.git
cd mt5-httpapi
cp config/config.yaml.example config/config.yaml
# Generate a bearer token, then edit config/config.yaml with it, your broker
# login, server, password, and ONE terminal you actually intend to run.
openssl rand -hex 32
# This filename is not decoration: "mybroker" MUST exactly match the
# broker: field of the terminal you configured below.
cp ~/Downloads/mt5setup.exe mt5installers/mt5setup-mybroker.exe
# Start the stack. This starts the VM; it does not mean MT5 is ready yet.
make up
# Wait until this passes before hitting the API.
make status
Before make up, replace the template's sample accounts: and terminals:
blocks — they contain placeholder FTMO and RoboForex entries and will not
magically start your broker. Keep the other template settings, but the three
names below must line up exactly, or Windows installs one terminal and the API
tries to launch another fucking thing:
# config/config.yaml
accounts:
mybroker: # 1. broker key
main: # 2. account key
login: 12345678 # your real account login
server: "Broker-MT5" # your broker's exact MT5 server name
password: "your-password"
terminals:
- broker: mybroker # 1. same broker key
account: main # 2. same account key
port: 5001 # unique per terminal; stays inside Docker
utc_offset: "0" # set this to the broker server's UTC offset
The installer must therefore be named mt5installers/mt5setup-mybroker.exe
(mybroker is 3. the same broker key). Get that executable from the broker;
this repo cannot download it for you. Remove the unused example accounts and
terminals, or configure an installer for every one of them.
The first run downloads tiny11 and installs Windows, Python, and MT5, so give
the fucker roughly ten minutes. make up returning only means Docker and the
VM booted; make status passing means the configured terminal API is actually
alive. Watch the installation through noVNC at http://localhost:8006; the
API lands at http://localhost:8888/mybroker/main/ for the config above.
Architecture
client
├─ REST: /<broker>/<account>[/<instance>]/...
└─ MCP: /mcp or /<broker>/<account>/mcp
│
nginx :8888
│
Windows VM(s) ── one MT5 terminal + Python API process per configured terminal
│
wickworks sidecar for requested technical-analysis calculations
config/config.yaml controls the accounts, terminals, ports, auth, broker UTC offsets, and whether a terminal is for live trading or backtests. Add a real vms.yaml when one Windows VM is not enough; leave it out and the normal single-VM setup keeps working.
Where the fuck is everything documented?
The old README became a massive wall of API shit, so the details now live in separate files where you can actually find them:
API at a glance
Every configured terminal gets one of these routes:
http://localhost:8888/<broker>/<account>/...
http://localhost:8888/<broker>/<account>/<instance>/...
Set api_token in config/config.yaml, shove it into a bearer header, and start poking the thing:
export MT5_API_TOKEN="your-token-here"
export MT5_API_URL="http://localhost:8888/mybroker/main"
curl -H "Authorization: Bearer $MT5_API_TOKEN" "$MT5_API_URL/ping"
curl -H "Authorization: Bearer $MT5_API_TOKEN" "$MT5_API_URL/account"
curl -H "Authorization: Bearer $MT5_API_TOKEN" \
"$MT5_API_URL/symbols/EURUSD/rates?timeframe=H1&count=100"
That is just the hello-world shit. The REST API docs link to every endpoint and response shape.
JSON keys are snake_case everywhere, the same as the MT5 fields the API passes through (time_msc, volume_real). The backtest and TA routes used to answer in camelCase (jobId, startedAt, wickworksStatus), so for now they still send those keys next to the snake_case ones and still accept camelCase in request bodies. The camelCase keys are deprecated and go away in v5.0.0. Move your clients to the snake_case names.
Development
make status # see whether the whole contraption is alive
make test # run all the tests, including integration + Go race
make test-live # test a running stack, set by MT5_LIVE_* (see docs/operations.md)
make lint # lint the PowerShell and shell shit
make format # format the shell scripts
make verify-binaries # check every vendored executable against the manifest
make logs # watch the logs scream
make down # stop only this project's stack
Run make help when you forget the rest. The operations guide explains what the targets actually do.
Vendored binaries
Every executable tracked in this repo is declared in
assets/binaries.lock.json with its SHA-256, size,
upstream URL and the state of its code signature. make verify-binaries — which
make test runs first, so CI enforces it on every pull request — fails the
build on an undeclared binary, on one whose bytes changed, or on a signature
that degrades.
Nobody can read a binary. A reviewer skims thousands of lines of source and
waves through the .exe beside it because there is nothing to skim, and that is
the shape every serious supply-chain compromise has taken. If you need to add
one: verify the download yourself against the vendor's published hash, then
record it in the manifest with where it came from. If it cannot be verified, say
so in its note — the gate will keep warning about it on every run, which is
the point.
Project layout
config/ config and templates for the whole contraption
mt5api/ Python REST + MCP server running beside each terminal
mcpunifier/ one MCP endpoint that fronts every configured terminal
clients/go/ typed Go client so you do not have to hand-roll requests
scripts/ Windows bootstrap and host-side glue
tests/ unit, contract, integration, and race-test shit
docs/ all the details that no longer clog up this README
Recommended brokers and prop firms
- RoboForex
- TeleTrade
- FTMO: prop firm with MT4 and MT5 support. Trading accounts use simulated capital.
License
WTFPL. See CHANGELOG.md for release notes.