mt5-mcp

mt5-mcp

Enables AI agents to interact with MetaTrader 5 for market data, live streaming, and trading operations, running locally over stdio.

Category
Visit Server

README

MT5-MCP

MT5-MCP is an MCP (Model Context Protocol) server exposing MetaTrader 5 — market data, live streaming with a durable log, and full order/position lifecycle management — as tools for AI agents (Claude, Cursor, or any MCP-aware client). Runs locally against the MT5 terminal already installed on this machine; MetaTrader 5 is the only backend connector for now.

Current status: Bolts 1–5 shipped. Market data, live streaming, and order/position tools (with a mandatory dry-run-by-default safety layer) are all live. See docs/aidlc/BOLTS.md for what's next (history/audit tools, the auth checkpoint).

Docs

Install

python -m venv .venv
.venv\Scripts\pip install -e ".[dev]"
.venv\Scripts\pytest -q

Copy .env.example to .env and set MT5_PATH to your terminal's terminal64.exe (auto-detection works if the terminal is already running, but an explicit path is more reliable — see diagnostics/FINDINGS.md for why relying on auto-detection is risky).

Run the server

.venv\Scripts\mt5-mcp
# or: .venv\Scripts\python.exe -m mt5_mcp

Default transport is streamable-http, bound to 127.0.0.1:3403 (loopback only, reserved in E:\MyAgent\workflow\ports\REGISTRY.md). This is deliberate — stdio was the original design but was found to hang indefinitely on any tool that calls into MetaTrader5 (root cause never identified despite extensive isolation; see diagnostics/FINDINGS.md). stdio is still available (MT5_MCP_TRANSPORT=stdio) but should not be trusted for anything beyond the ping tool.

Connect an MCP client

Claude Code:

claude mcp add --transport http mt5-mcp http://127.0.0.1:3403/mcp

Claude Desktop / other JSON-config clients, add to the client's MCP server config:

{
  "mcpServers": {
    "mt5-mcp": {
      "url": "http://127.0.0.1:3403/mcp"
    }
  }
}

(Exact key names for HTTP-transport servers vary by client — check that client's docs if this doesn't work as-is.)

The server must already be running (mt5-mcp in a terminal) before the client connects — this project doesn't yet register itself as a background/managed process.

Public access (client on a different machine)

A DEV instance of this server is reverse-proxied at https://mt5-mcp-dev.delena.buzz (nginx + Cloudflare, port 3403 on this host) so a client on another machine can connect without a VPN/SSH tunnel:

claude mcp add --transport http mt5-mcp https://mt5-mcp-dev.delena.buzz/mcp

⚠️ No authentication gate today — explicit, documented decision, not an oversight. Anyone with the URL can call every read-only tool and every execution tool. MT5_MCP_DRY_RUN is a server-side env var on this host, not something a remote caller can flip — but check its current value before relying on it as a safety net: it does not always default to dry-run-on in practice, only in the absence of an explicit override, and this host's .env is not committed (check E:\MyAgent\workflow\ports\REGISTRY.md's :3403 row for the live current status, since it changes and this file doesn't get re-edited on every toggle). When dry-run is on, execution tools always return simulated responses. When it's off, an unauthenticated caller can place/modify/cancel/close a real order on the connected account, bounded only by MT5_MCP_MAX_LOT_SIZE/MT5_MCP_MAX_OPEN_POSITIONS (always enforced regardless of dry-run) and the kill-switch (MT5_MCP_KILL_SWITCH_PATH — create that file to immediately block place_order). Either way, an unauthenticated caller can always read real market data and real open-position state (tickets/volumes/P&L). Full CSS integration is planned but not built — see docs/aidlc/INCEPTION.md's "Auth / security note" and E:\MyAgent\workflow\css\CLIENT-REGISTRY.md's mt5-mcp row (status waived-no-auth) for the reasoning and current status. Treat this URL accordingly until that changes.

If you run your own reverse proxy in front of this server, add its hostname to MT5_MCP_PUBLIC_HOSTNAMES (comma-separated) — FastMCP's built-in DNS-rebinding protection otherwise rejects any Host header besides 127.0.0.1/localhost/::1 with a 421.

Tools

All tools return the standard envelope: {success, error_code, error_message, retryable, request_id, data}.

Market data (read-only)

  • get_historical_ohlcv(symbol, timeframe, from_date?, to_date?, from_bar?, to_bar?, limit?, include_volume?, include_spread?, session_filter?, price_type?, only_completed_bars?)timeframe: M1/M5/M15/M30/H1/H4/D1/W1/MN1. price_type only supports "bid" (or omitted) — ask/mid/last not implemented.
  • get_symbol_info(symbol) — contract size, tick size/value, digits, swaps, margin, current bid/ask.

Live streaming (durable log, not true push — see below)

  • subscribe_live_data(symbol, data_types?)data_types: ["tick"] and/or ["bar"] (fixed M1). Returns a subscription_id.
  • unsubscribe_live_data(subscription_id?, symbol?) — stop by id or all subscriptions for a symbol.
  • get_stream_log(symbol, from_time?, to_time?, data_type?, limit?) — read back logged ticks/bars, including after unsubscribing.

Orders (execution — dry-run by default, see Safety below)

  • place_order(symbol, order_type, side, volume, price?, stop_loss?, take_profit?, comment?, magic_number?, deviation?, client_order_id?)order_type: market/limit/stop. side: buy/sell. price required for limit/stop. client_order_id is logged for traceability only — it does not deduplicate retries.
  • modify_order(ticket, price?, stop_loss?, take_profit?, volume?, expiration?) — modifies a pending order. expiration is not implemented — passing it raises unsupported_parameter.
  • cancel_order(ticket) — cancels a pending order.

Positions

  • get_open_positions(symbol?, magic_number?, comment?) — read-only.
  • modify_position(ticket, stop_loss?, take_profit?) — changes SL/TP on an open position.
  • close_position(ticket, volume?) — full or partial close.
  • close_all_positions(symbol?, side?, magic_number?) — bulk close.

Health

  • ping() — no MT5 connection required, works even if MT5_PATH is wrong.

Not implemented: stop_limit/trailing_stop order types, get_order_history/get_deal_history/get_position_history (Bolt 6), CSS auth (deferred, see INCEPTION.md).

Safety layer (order/position tools)

  • Dry-run is on by default. No real order ever gets placed unless you explicitly set MT5_MCP_DRY_RUN=false in the server's environment. It's an env var, not a tool parameter — an agent can't flip it mid-conversation. Dry-run responses use real current market prices, so they're shaped like a real fill would be.
  • Kill-switch: create a file at MT5_MCP_KILL_SWITCH_PATH (default: <repo root>\MT5_MCP_KILL_SWITCH) and place_order (only — the sole action that creates new exposure) is blocked immediately, independent of the dry-run setting. Delete the file to re-enable. modify_order/cancel_order/modify_position/close_position/close_all_positions are deliberately not blocked by the kill-switch — an emergency stop shouldn't also trap you inside an existing position.
  • Limits: MT5_MCP_MAX_LOT_SIZE (default 0.10) and MT5_MCP_MAX_OPEN_POSITIONS (default 3) — both enforced server-side on place_order, not just documented.
  • Audit log: every order/position attempt — dry-run or real, success or failure — is written to a local SQLite log (MT5_MCP_AUDIT_LOG_DB, default <repo root>\mt5_mcp_audit_log.db), before the tool call returns.
  • Nothing here authorizes a live (non-demo) account. The connector only ever points at whatever MT5_PATH's terminal is logged into — currently OctaFX-Demo. Pointing this at a real account is a distinct, explicit decision this project has not made.

Environment variables

Variable Default Purpose
MT5_PATH auto-detect Path to terminal64.exe
MT5_MCP_TRANSPORT streamable-http stdio | sse | streamable-http — see the stdio warning above
MT5_MCP_HTTP_HOST 127.0.0.1 Bind host for http/sse transports
MT5_MCP_HTTP_PORT 3403 Bind port (reserved in the port registry)
MT5_MCP_PUBLIC_HOSTNAMES (none) Comma-separated extra Host headers to accept from a reverse proxy — required for any public hostname to work, see "Public access" above
MT5_MCP_DRY_RUN true Must be exactly false to allow real order execution; anything else (including unset/typo) stays dry-run
MT5_MCP_KILL_SWITCH_PATH <repo root>\MT5_MCP_KILL_SWITCH If this file exists, place_order is blocked
MT5_MCP_MAX_LOT_SIZE 0.10 Max volume per place_order call
MT5_MCP_MAX_OPEN_POSITIONS 3 Max concurrent open positions before place_order is blocked
MT5_MCP_STREAM_LOG_DB <repo root>\mt5_mcp_stream_log.db SQLite path for subscribe_live_data/get_stream_log
MT5_MCP_AUDIT_LOG_DB <repo root>\mt5_mcp_audit_log.db SQLite path for the order/position audit trail

All .db files are gitignored — they're local runtime state, not source.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured