Skip to main content
Glama
mt5-mcp

mt5-mcp

by ramanthind02

mt5-mcp

CI Python 3.11+ License: MIT codecov

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 snapshot

The 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 terminal64.exe can appear twice when two logins share an install.

A broker, saved once

capture_profile writes every symbol: the full symbol_info record and the weekday sessions. Compare two profiles on spread, swap, stops, contract size, filling mode, and hours.

History you can actually keep

Bars and ticks land in CSV (or Parquet). history_coverage reads the earliest M1 bar already on disk. extend_history with kind=m1 downloads older months until the broker stops.

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.exe is 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_terminal attaches 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_backtest accepts an ini whose only sections are [Tester] and [TesterInputs], with ShutdownTerminal=1. A junction, an already-open terminal, or the same program launched from another path is refused.

  • stop_backtest stops a tester process this server started.

Prerequisites

  1. Windows, with the MetaTrader 5 terminal installed. The server has to run on that machine.

  2. Python 3.11+ and uv.

  3. An account that is already logged in in the terminal you want to use. Demo or live.

  4. 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-mcp

MetaTrader5 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-mcp

Parquet 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 = true

The 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:

  1. compile returns MetaEditor errors and warnings as structured lines.

  2. smoke_test runs 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.

  3. read_inputs and write_tester_config build a headless ini. ShutdownTerminal is 1 and Visual is 0. Models are every_tick, ohlc, open_prices, or real_ticks.

  4. run_backtest copies the EA sources and the ini into a snapshot, launches terminal64.exe /config, and waits.

  5. read_report turns the HTML into a summary, every closed trade, and a long/short breakdown.

  6. compare_reports diffs two of those reports. list_snapshots and read_snapshot show 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

list_terminals

The registry. include_discovered=true also lists installs that are not registered yet.

add_terminal

Adds an id, path, login, and server to the registry. It does not copy terminal files.

remove_terminal

Removes that registry entry. It does not delete the install.

launch_terminal

Starts any install, registered or not. Does nothing if that terminal64.exe is already running.

use_terminal

Attaches to the account already open in that window.

terminal_status

Build, company, server clock, timezone offset, login, and demo or real.

disconnect

Drops the Python API connection. The terminal window stays open.

Account

Tool

What you get

account_health

Balance, equity, margin, free margin, margin level, floating profit, trade_allowed, positions, and pending orders.

positions

Open positions.

orders

Pending orders.

Broker profile

Tool

What you get

capture_profile

Every symbol from symbols_get(), with symbol_info and weekday sessions, in profiles/<id>.json.

read_profile

The summary, or one symbol.

list_profiles

Saved profiles and how many symbols each one holds.

compare_profiles

A diff of two or more profiles. Unchanged symbols are counted and left out.

Market data

Tool

What you get

list_symbols

Symbol names on the active terminal. limit=0 returns every name.

symbol_info

The full symbol_info record, the latest tick, and weekday sessions.

symbol_tick

Latest bid, ask, last, and time.

select_symbol

Adds or removes a symbol in Market Watch so history can download.

copy_rates

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.

probe_history

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 data/<terminal>/rates/D1/<SYMBOL>.csv with a survey.json index. This does not measure M1.

history_coverage

Earliest and latest M1 bar already stored in the yearly .hcc files, plus cached bar years and tick months. Does not download.

extend_history

Downloads older history one chunk at a time. kind=m1 is one UTC month of minute bars and stops when a month has no bars inside it. kind=d1 is one UTC year. kind=ticks is one UTC month of ticks. max_steps caps one call.

copy_ticks

Ticks to a file for a date range. all_history=true is required when dates are omitted. A start date before the cached .tkc months blocks while the terminal downloads the gap.

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

list_experts

.mq5 sources and .ex5 binaries under the active terminal's Experts folder.

compile

MetaEditor errors and warnings for one .mq5 file.

smoke_test

Compile, run one day, scan the journal. date is both FromDate and ToDate. Timeout defaults to 180 seconds.

read_inputs

input declarations parsed from an EA source file.

write_tester_config

A headless tester.ini. Pass source to seed inputs from the EA, or pass an inputs map.

run_backtest

terminal64.exe /config on that ini. Stores a source snapshot first. Default timeout is 1800 seconds.

read_report

Summary, every closed trade, and a long/short breakdown. Omit the path to use the newest report.

list_snapshots

Snapshots written by run_backtest, newest first.

read_snapshot

One manifest: EA sources, tester inputs, and the report path.

compare_reports

Two HTML reports, field by field.

tail_log

Tester journal or terminal journal. mode is tester or journal.

stop_backtest

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

mt5://getting_started

Find a terminal, attach, then read data or run a backtest

mt5://terminals

Registry, launch, and attach

mt5://market_data_guide

Symbols, profiles, bars, the history probe, and ticks

mt5://account_guide

Balance, positions, and pending orders

mt5://backtest_guide

Compile an existing EA and run the Strategy Tester

mt5://timeframes

Bar-size names and the integer codes the terminal stores

mt5://tester_models

Tick models for write_tester_config

Prompt

What it asks the agent to do

connect_terminal

List, launch if needed, and use_terminal. It does not ask for a password.

analyze_market_data

Export bars for one symbol and summarize the file, the range, and the latest tick.

review_account

Read health, positions, and orders.

backtest_expert

Smoke-test, write a headless ini, run it, and read the report.

compare_backtests

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.toml

Development

uv sync --extra dev
uv run pre-commit install
uv run pytest
uv run ruff check src tests
uv run ruff format --check src tests

The 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 tools
account_healthA
Read-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_profilesA
Read-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_reportsC
Read-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_coverageA
Read-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_expertsA
Read-only

List .mq5 sources and .ex5 binaries under the active terminal Experts folder.

Inputs: no named parameters.

list_profilesA
Read-only

List saved broker profiles and how many symbols each one contains.

Inputs: no named parameters.

list_snapshotsB
Read-only

List source snapshots written by run_backtest, newest first.

Inputs: limit.

list_symbolsB
Read-only

List symbol names on the active terminal. limit=0 returns every name.

Inputs: group, limit.

list_terminalsA
Read-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.

ordersB
Read-only

List pending orders on the active account. Read-only.

Inputs: no named parameters.

positionsA
Read-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_inputsC
Read-only

Parse input declarations from an Expert Advisor source file.

Inputs: source (required).

read_profileB
Read-only

Read a saved broker profile. Without symbol, return the summary. With symbol, return that instrument.

Inputs: symbol, terminal_id.

read_reportA
Read-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_snapshotB
Read-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_backtestA
Destructive

Stop a Strategy Tester process this server started.

Inputs: no named parameters.

symbol_infoB
Read-only

Return the full symbol_info record, the latest tick, and weekday sessions.

Inputs: symbol (required).

symbol_tickB
Read-only

Return the latest bid, ask, last, and time for one symbol.

Inputs: symbol (required).

tail_logC
Read-only

Tail the tester journal or the terminal journal. mode is tester or journal.

Inputs: date, mode, lines, structured.

terminal_statusA
Read-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

    B3.2/5.0

    Scored across 35 tools

    Disambiguation3/5

    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.

    Naming Consistency4/5

    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.

    Tool Count2/5

    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.

    Completeness4/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables 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 PyPI
      1
      MIT
    • A
      license
      Not graded
      quality
      A
      maintenance
      Exposes 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 PyPI
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Connects Claude to a MetaTrader 5 terminal for read-only market data, account info, performance analysis, and order planning (no live trading).
      18
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables 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
      -