mt5-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mt5-mcp Attach to my open MT5 terminal and export EURUSD daily bars to CSV"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mt5-mcp
A research desk for MetaTrader 5, driven in plain language.
Tell Cursor, Claude, or Codex to attach to the terminal you already have open, save the broker, export the history, and backtest an Expert Advisor that is already on disk. The server runs on Windows, next to MetaTrader, and speaks Model Context Protocol over stdio.
"Attach to the demo account that is already open."
"Save every symbol on this broker, then tell me how Darwinex differs from the other profile."
"How far back does EURUSD go, and write the daily bars to a file."
"Smoke-test this EA on one day. If the journal is clean, run 2024 and read the drawdown."
Live orders stay in the MetaTrader window. You log in there. The agent gets the research.
You → Cursor / Claude / Codex → mt5-mcp → the terminal that is already open
│
├─ profiles/<id>.json
├─ data/.../rates and ticks
└─ Strategy Tester report + source snapshotThe coverage badge fills in after this repository is connected to Codecov and CODECOV_TOKEN is set. Until then, the CI job summary is the coverage record.
Contents
Related MCP server: Meta-Trader-MCP
What it will do for you
Several terminals, one registry | Demo and live, or two brokers, listed by id. The same |
A broker, saved once |
|
History you can actually keep | Bars and ticks land in CSV (or Parquet). |
Headless Strategy Tester | Compile, smoke-test one day, write a tester ini, run it, parse the HTML report, and diff two runs. Each run keeps a snapshot of the EA sources. |
Account, read in place | Balance, equity, margin, floating profit, open positions, pending orders. |
Agents that already know the workflow | Resources and prompts ship with the server, so the model reads the guide before it improvises. |
Who it is for
Researchers who want a broker's symbol list and session hours in a file, then a summary in chat.
EA authors who want compile errors, a one-day smoke test, and a headless 2024 run without clicking through the tester.
People with more than one terminal who are tired of telling an agent which
terminal64.exeis which.Anyone who wants an agent on their market data and still wants the trade button to require their hands.
Guardrails
This is research software. A backtest is a simulation on stored ticks and bars. It is not a forecast, and it is not a live fill.
The tool list has no place, modify, or close order call.
Login happens in the MetaTrader window.
use_terminalattaches to that session. A mismatched login stops and asks you to switch accounts in the window.Passwords live in
%USERPROFILE%\.mt5-mcp\secrets.env. They are never tool arguments and never come back in a tool result.run_backtestaccepts an ini whose only sections are[Tester]and[TesterInputs], withShutdownTerminal=1. A junction, an already-open terminal, or the same program launched from another path is refused.stop_backteststops a tester process this server started.
Prerequisites
Windows, with the MetaTrader 5 terminal installed. The server has to run on that machine.
Python 3.11+ and uv.
An account that is already logged in in the terminal you want to use. Demo or live.
An MCP client: Cursor, Claude Code, Claude Desktop, or Codex.
Quick start
1. Install
No checkout required:
uvx --from git+https://github.com/ramanthind02/mt5-mcp mt5-mcpMetaTrader5 installs automatically on Windows. History files default to CSV.
To work on the source:
git clone https://github.com/ramanthind02/mt5-mcp.git
cd mt5-mcp
uv sync
uv run mt5-mcpParquet output needs a checkout: uv sync --extra parquet.
2. Name your terminals
Config lives in %USERPROFILE%\.mt5-mcp\ (override with MT5_MCP_HOME). Copy examples/terminals.toml there and edit the paths, logins, and servers.
[terminals.darwinex-demo]
path = 'C:\Program Files\Darwinex MetaTrader 5\terminal64.exe'
login = 12345678
server = "Darwinex-Demo"
role = "demo"
enabled = true
[terminals.darwinex-live]
path = 'C:\Program Files\Darwinex MetaTrader 5\terminal64.exe'
login = 87654321
server = "Darwinex-Live"
role = "live"
enabled = trueThe id in brackets is what you say to the agent. Passwords do not go in this file. If you want one available to the server, put it in secrets.env using examples/secrets.env.example. The name is the id, uppercased, with a _PASSWORD suffix: darwinex-demo becomes DARWINEX_DEMO_PASSWORD. Leave the line out and the server will simply require the account to be logged in already.
3. Log in from the MetaTrader window
Open the terminal, log in, and leave it up. Then ask the agent to attach. launch_terminal starts an install that is not running yet, and skips one whose terminal64.exe is already up.
4. Connect the agent
Cursor. ~/.cursor/mcp.json or .cursor/mcp.json in the project. The same JSON works for Claude Code in .mcp.json, and for Claude Desktop in %APPDATA%\Claude\claude_desktop_config.json.
{
"mcpServers": {
"mt5": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/ramanthind02/mt5-mcp",
"mt5-mcp"
],
"env": { "MT5_MCP_HOME": "C:\\Users\\you\\.mt5-mcp" }
}
}
}Restart the client, then try: "List my terminals and attach to darwinex-demo."
Codex. Add this to ~/.codex/config.toml. The full snippet is examples/codex.toml.
[mcp_servers.mt5]
command = "uvx"
args = ["--from", "git+https://github.com/ramanthind02/mt5-mcp", "mt5-mcp"]
[mcp_servers.mt5.env]
MT5_MCP_HOME = "C:\\Users\\you\\.mt5-mcp"A full session
These are the words. The agent calls the tools. You read the files it writes.
Attach
List my terminals. If darwinex-demo is not running, launch it. Attach, then tell me the login, server, and whether the account is demo or real.
Behind that: list_terminals → launch_terminal if needed → use_terminal → terminal_status.
Learn the broker, then pull history
Capture the broker profile. Then probe daily history for EURUSD and the other majors, and summarize how far back each one goes.
capture_profile writes profiles/<id>.json with every symbol. probe_history writes daily bars to data/<terminal>/rates/D1/<SYMBOL>.csv and an index at survey.json. Ask for one symbol's file when you want the bars themselves:
Export H1 EURUSD from 2024-01-01 through 2024-12-31 and quote the first and last bars.
copy_rates pages until the terminal runs out when you omit the dates. A date window keeps only bars inside that window. It is not a depth probe: a request before cached history comes back as the oldest bar the terminal already has, and that bar is discarded.
Two calls answer how far M1 goes. history_coverage reads the earliest minute already in the yearly .hcc files and does not download. extend_history with kind=m1 downloads one UTC month at a time until a month contains no bars. That empty month is the broker limit. max_steps caps one call. Call it again when reached_broker_limit is false.
Ticks cannot be probed with a position index. CopyTicks / copy_ticks_from start at the date you pass in. A request for one tick from a date before the local cache still makes the terminal download the gap, and the call does not return until that download finishes. history_coverage reads the .tkc months already on disk and does not discover older months. extend_history with kind=ticks downloads one UTC month at a time from the oldest cached month backward and stops when a month comes back empty. That empty month is the broker limit. One month of XAUUSD on Darwinex-Demo was about 10 million ticks and about two and a half minutes.
Backtest an EA you already wrote
Compile Experts\MyEA.mq5. Smoke-test it on EURUSD H1 for 2024.01.02. If the journal is clean, run 2024.01.01 to 2024.12.31 with the OHLC model and read the report. Then compare it to the report from last week.
The path looks like this:
compilereturns MetaEditor errors and warnings as structured lines.smoke_testruns that single day and scans the tester journal. Init failures, missing history, tester rejects, and runtime errors stop the session. A history-sync miss is retried once.read_inputsandwrite_tester_configbuild a headless ini.ShutdownTerminalis 1 andVisualis 0. Models areevery_tick,ohlc,open_prices, orreal_ticks.run_backtestcopies the EA sources and the ini into a snapshot, launchesterminal64.exe /config, and waits.read_reportturns the HTML into a summary, every closed trade, and a long/short breakdown.compare_reportsdiffs two of those reports.list_snapshotsandread_snapshotshow which sources produced a run.
tail_log follows the tester journal if a run is still going. stop_backtest cancels one this server started.
Check the account in between
Read account health, then list open positions and pending orders.
account_health returns balance, equity, margin, free margin, margin level, floating profit, and whether trading is allowed. positions and orders return the lists on their own.
Tools
Terminals
Tool | What you get |
| The registry. |
| Adds an id, path, login, and server to the registry. It does not copy terminal files. |
| Removes that registry entry. It does not delete the install. |
| Starts any install, registered or not. Does nothing if that |
| Attaches to the account already open in that window. |
| Build, company, server clock, timezone offset, login, and demo or real. |
| Drops the Python API connection. The terminal window stays open. |
Account
Tool | What you get |
| Balance, equity, margin, free margin, margin level, floating profit, |
| Open positions. |
| Pending orders. |
Broker profile
Tool | What you get |
| Every symbol from |
| The summary, or one symbol. |
| Saved profiles and how many symbols each one holds. |
| A diff of two or more profiles. Unchanged symbols are counted and left out. |
Market data
Tool | What you get |
| Symbol names on the active terminal. |
| The full |
| Latest bid, ask, last, and time. |
| Adds or removes a symbol in Market Watch so history can download. |
| Bars, paged until the terminal runs out, written to CSV or Parquet. Omit both dates for every bar the terminal still serves. A date window keeps only bars inside it. The result is a path, a count, a range, and a short preview. |
| How far back daily, weekly, or monthly bars already go. Omit the symbol to survey every symbol, or pass a group mask. Daily bars go to |
| Earliest and latest M1 bar already stored in the yearly |
| Downloads older history one chunk at a time. |
| Ticks to a file for a date range. |
Bar sizes for copy_rates, probe_history, and the tester: M1 M2 M3 M4 M5 M6 M10 M12 M15 M20 M30 H1 H2 H3 H4 H6 H8 H12 D1 W1 MN1. The integer codes the terminal stores are in the mt5://timeframes resource.
Backtests
Tool | What you get |
|
|
| MetaEditor errors and warnings for one |
| Compile, run one day, scan the journal. |
|
|
| A headless |
|
|
| Summary, every closed trade, and a long/short breakdown. Omit the path to use the newest report. |
| Snapshots written by |
| One manifest: EA sources, tester inputs, and the report path. |
| Two HTML reports, field by field. |
| Tester journal or terminal journal. |
| Stops a Strategy Tester process this server started. |
Resources and prompts
Agents can read a resource without calling a tool. A prompt is a ready-made task.
Resource | What it covers |
| Find a terminal, attach, then read data or run a backtest |
| Registry, launch, and attach |
| Symbols, profiles, bars, the history probe, and ticks |
| Balance, positions, and pending orders |
| Compile an existing EA and run the Strategy Tester |
| Bar-size names and the integer codes the terminal stores |
| Tick models for |
Prompt | What it asks the agent to do |
| List, launch if needed, and |
| Export bars for one symbol and summarize the file, the range, and the latest tick. |
| Read health, positions, and orders. |
| Smoke-test, write a headless ini, run it, and read the report. |
| Diff two HTML reports, leading with net profit, profit factor, drawdown, and trade count. |
Where your files go
Everything the server writes stays under the home directory. None of it belongs in git.
%USERPROFILE%\.mt5-mcp\
├── terminals.toml
├── secrets.env
├── profiles\
│ └── darwinex-demo.json
└── data\
├── <terminal>\rates\D1\
│ ├── EURUSD.csv
│ └── survey.json
└── snapshots\<terminal>\<stamp>\Set MT5_MCP_HOME when you want that tree somewhere else.
Project layout
mt5-mcp/
├── src/mt5_mcp/ # server, tools, guides
│ ├── server.py # tool registration
│ ├── guides.py # resources and prompts
│ ├── registry.py # terminal discovery and the registry
│ ├── connection.py # attach to an open terminal
│ ├── account.py
│ ├── market.py # symbols, bars, ticks, history probe
│ ├── profile.py
│ ├── tester.py # compile, smoke test, Strategy Tester
│ ├── snapshot.py
│ └── parsers.py # compile log and HTML report
├── tests/ # mocked unit tests
├── examples/ # mcp.json, codex.toml, terminals.toml
├── .github/ # CI, Dependabot, issue templates
├── AGENTS.md # how later changes keep this repo in shape
├── CONTRIBUTING.md
├── CHANGELOG.md
└── pyproject.tomlDevelopment
uv sync --extra dev
uv run pre-commit install
uv run pytest
uv run ruff check src tests
uv run ruff format --check src testsThe tests mock the MetaTrader API. They do not open a terminal. Coverage of src/mt5_mcp stays at or above 67%. CI on GitHub runs Ruff, pytest on Ubuntu for Python 3.11 and 3.13, the full suite on Windows, and a package build. The Windows job is what runs the junction guardrails. Pull requests also check the title and, for a feat or fix under src/mt5_mcp/, a changelog line.
Branches, commit messages, and the pull request checklist are in CONTRIBUTING.md. Notable changes go in CHANGELOG.md. Vulnerability reports follow SECURITY.md.
Acknowledgements
Terminal discovery, the compile-log parser, and the report parser are adapted from PHUICMT/mcp-mt5 (MIT). See NOTICE.
MetaTrader 5 is a product of MetaQuotes.
License
MIT. Use it, fork it, and if it saves you an afternoon in the Strategy Tester, star the repository so the next person can find it.
Available Tools
35 toolsaccount_healthARead-only
Read account health for the active terminal.
Returns balance, equity, margin, free margin, margin level, floating profit, whether trading is allowed, open positions, and pending orders. This does not place, modify, or close anything.
Inputs: no named parameters.
add_terminalA
Add a discovered terminal, or a path, to the registry.
This writes terminals.toml. It does not copy or create an install. name becomes the registry id when it is set. A junction to an install is refused. Register the real directory.
Inputs: name, path, role, login, +3 more.
capture_profileA
Write a JSON profile of the active broker: clock, account mode, and every symbol.
Each symbol stores the full symbol_info record plus weekday sessions. The tool result is a summary and a file path, not the whole symbol list.
Inputs: no named parameters.
compare_profilesARead-only
Diff saved broker profiles on the fields that decide whether a backtest can transfer.
Pass at least two ids from list_profiles. Symbol names must match exactly. Compared fields are spread, the floating-spread flag, swap, swap mode, stops level, contract size, filling mode, and session hours. Unchanged symbols are counted and omitted.
Inputs: terminal_ids (required), symbols.
compare_reportsCRead-only
Diff two tester reports field by field.
Inputs: baseline (required), candidate (required).
compileC
Compile one .mq5 file with MetaEditor and return structured errors and warnings.
Inputs: source (required), timeout_sec.
copy_ratesA
Download bars, paging until the terminal runs out, and write CSV or Parquet.
Omit both dates to request every bar the terminal still serves. Pass both dates for one window. Bars outside that window are dropped, including the older bar the terminal returns when the window is before cached history. This is not how far back M1 goes. Use history_coverage for bars already on disk and extend_history with kind=m1 to download older months. The result is a file path, a count, a time range, and a short preview.
Inputs: symbol (required), format, date_to, save_to, +2 more.
copy_ticksB
Download ticks to a file. Set all_history=true when dates are omitted.
Unbounded tick history is large, so all_history is required for that case.
Inputs: symbol (required), format, date_to, save_to, +2 more.
disconnectA
Drop the Python API connection. The terminal window stays open.
Inputs: no named parameters.
extend_historyA
Download older history one chunk at a time and stop at the first empty chunk.
kind=d1 walks one UTC year backward from the oldest cached year. kind=m1 walks one UTC month backward from the month before the earliest cached M1 bar. A bar outside that month does not count. The first month with no bars inside it is the broker limit. max_steps is the number of months in one call. Call again when reached_broker_limit is false. kind=ticks walks one UTC month backward from the oldest cached tick month.
Inputs: symbol (required), kind, max_steps.
history_coverageARead-only
Report stored bar and tick depth for one symbol without downloading a gap.
m1.time_from is the earliest minute bar already in the yearly .hcc files. A missing earlier year has not been fetched. A year file the terminal has open is read back with one request bounded to that year. This call does not request an earlier year. Bar years and tick months come from the same cache. When verify is true, one bounded UTC request is made inside that cache for daily bars and for ticks.
Inputs: symbol (required), verify.
launch_terminalA
Start a MetaTrader terminal. Pass a registry id, a discovered id, or any terminal path.
If that terminal64.exe is already running, this leaves it alone. A junction is refused, because MetaTrader would open a second data folder.
Inputs: path, terminal_id.
list_expertsARead-only
List .mq5 sources and .ex5 binaries under the active terminal Experts folder.
Inputs: no named parameters.
list_profilesARead-only
List saved broker profiles and how many symbols each one contains.
Inputs: no named parameters.
list_snapshotsBRead-only
List source snapshots written by run_backtest, newest first.
Inputs: limit.
list_symbolsBRead-only
List symbol names on the active terminal. limit=0 returns every name.
Inputs: group, limit.
list_terminalsARead-only
List terminals in the registry.
Pass include_discovered=true to also list installs found under %APPDATA%\MetaQuotes\Terminal that are not in the registry yet. Password values are not included.
Inputs: include_discovered.
ordersBRead-only
List pending orders on the active account. Read-only.
Inputs: no named parameters.
positionsARead-only
List open positions on the active account. Read-only.
Inputs: no named parameters.
probe_historyA
Probe how far back daily, weekly, or monthly bars already go, and save that series by default.
Omit symbol to survey every symbol, or pass a group mask. Daily bars are stored as data//rates/D1/.csv with a survey.json index. The tool result is the summary, not the bars. This does not measure M1. history_coverage reads the earliest M1 bar already on disk. extend_history with kind=m1 downloads older months until one comes back empty.
Inputs: save, group, limit, symbol, +1 more.
read_inputsCRead-only
Parse input declarations from an Expert Advisor source file.
Inputs: source (required).
read_profileBRead-only
Read a saved broker profile. Without symbol, return the summary. With symbol, return that instrument.
Inputs: symbol, terminal_id.
read_reportARead-only
Parse a tester HTML report into a summary, every closed trade, and a breakdown.
Omit path to use the newest report for the active terminal. Each trade has entry and exit time, side, volume, prices, profit, and comment. The breakdown splits long and short expectancy, holding time, and entry hour on the report clock.
Inputs: path.
read_snapshotBRead-only
Read one snapshot manifest: EA sources, tester inputs, and the report path.
Inputs: path (required).
remove_terminalB
Remove a terminal from the registry. The install and data folder stay on disk.
Inputs: terminal_id (required).
run_backtestA
Run terminal64.exe /config on a tester ini and wait until it exits.
The ini must contain only [Tester] and [TesterInputs], with ShutdownTerminal=1. The launch path is used as written. A junction, an already-open terminal, or the same program running from another path is refused. The report is the file named by Report in the ini. Before the launch, the EA sources and the ini are copied into a snapshot. The manifest is updated with the report path.
Inputs: config (required), timeout_sec.
select_symbolC
Add or remove a symbol in Market Watch so history can download.
Inputs: symbol (required), visible.
smoke_testB
Compile an EA, run that one day, and scan the tester journal.
date is both FromDate and ToDate. timeout_sec defaults to 180. Blocking lines are init failures, history not synchronized, tester rejects, and runtime errors. A history-sync miss is retried once. This does not place a live order.
Inputs: source (required), symbol (required), date, model, +2 more.
stop_backtestADestructive
Stop a Strategy Tester process this server started.
Inputs: no named parameters.
symbol_infoBRead-only
Return the full symbol_info record, the latest tick, and weekday sessions.
Inputs: symbol (required).
symbol_tickBRead-only
Return the latest bid, ask, last, and time for one symbol.
Inputs: symbol (required).
tail_logCRead-only
Tail the tester journal or the terminal journal. mode is tester or journal.
Inputs: date, mode, lines, structured.
terminal_statusARead-only
Report the active terminal: build, company, server clock, timezone offset, login, and demo or real.
Inputs: no named parameters.
use_terminalA
Attach the API to a terminal that is already logged in.
This never sends a login or password. If the open account is not the one named in the registry, log in from the terminal window.
Inputs: terminal_id (required).
write_tester_configB
Write a headless tester.ini. ShutdownTerminal is always 1 and Visual is always 0.
model is every_tick, ohlc, open_prices, or real_ticks. Pass source to seed TesterInputs from the EA, or pass inputs as a name-to-value map.
Inputs: expert (required), symbol (required), path, model, +9 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 35 tools
Most tools target distinct resources or actions, but the history family (copy_rates, probe_history, history_coverage, extend_history, copy_ticks) overlaps enough that an agent must read descriptions carefully to choose correctly. Other groups, such as terminal launch/use/status and profile capture/read/compare, are more clearly separated.
The set mostly follows a predictable verb_noun pattern, with readable names throughout. A few read-only or status tools use noun-only names such as positions, orders, terminal_status, account_health, symbol_info, and history_coverage, but there is no chaotic style mixing.
With 35 tools, the server is well above the reasonable 3–15 range and past the 25+ threshold for being heavy. The domain is broad, but packaging terminal management, history, symbols, compilation, and backtesting into one server makes the surface large and costly to navigate.
The tool surface covers terminal lifecycle, account inspection, symbols, history, EA compilation, snapshots, and backtesting with few dead ends. Gaps such as no live order placement/modification/close and no explicit report-listing tool appear intentional or minor, and agents can work around them.
Maintenance
Related MCP Connectors
Read-only access to your MetaTrader 4 and 5 accounts for AI agents: balances, open positions, trade history with win rate, live quotes, symbol specs and candles. It cannot place, modify or close orders.
Let AI agents trade and read MetaTrader 5 accounts. Hosted — no terminal for you to run.
Connect any MCP client to MetaTrader 4/5 to read prices, manage positions, and place trades.
Manage MetaTrader 4 and 5 trade copying from your AI agent: list your connected accounts, set up copiers, add followers with their own rules, pause and resume copying, and read what the copier did. Tool calls need an Algo Trader Tools API key in the X-API-Key header, and a key lists only the tools its scopes allow.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables comprehensive access to the MetaTrader 5 trading platform for retrieving market data, managing accounts, and executing trading operations. It provides 32 specialized tools for interacting with MT5 functionalities, including historical OHLCV data access, real-time position monitoring, and automated order management.29 PyPI1MIT
- AlicenseNot gradedqualityAmaintenanceExposes a unified AI interface to MetaTrader 5 over the Model Context Protocol, enabling live quotes, historical data, technical indicators, order execution, position management, and headless backtests.109 PyPIMIT
- AlicenseAqualityBmaintenanceConnects Claude to a MetaTrader 5 terminal for read-only market data, account info, performance analysis, and order planning (no live trading).18MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants and traders to connect to a local MetaTrader 5 terminal, fetch historical market data, run strategy backtests, monitor account status, and manage demo trades via natural language, with an interactive web GUI.2-