Give an AI agent access to your MT5 account safely

8 min readMetaKit

"Look at my trading account and tell me how last week went." People are typing that into Claude, ChatGPT, and Cursor right now, and the honest answer from the model is that it can't see anything. So the next step is usually the bad one: paste the MT5 login, the master password, and the server name into the chat.

Now an AI agent has full trading access to a live account, the credentials are sitting in a conversation log, and the password is the one that can also change itself. There's a version of that idea that doesn't keep you up at night, and it takes about ten minutes to set up.

The terminal's MCP is not an application integration

MetaTrader 5 build 6060 added native MCP to the terminal, and it's genuinely good for what it is: an assistant sitting inside your running terminal, on your desktop, answering "what's my gold exposure?" while you're at the desk. The build 6060 post covers what shipped.

It is not the thing you need when the question is "have an agent check my accounts every Monday" or "give my Cursor project a way to read trades". The terminal MCP lives and dies with a desktop session. It covers one account per terminal. It has no notion of an API key you can revoke, and the security settings are per-terminal toggles rather than per-credential permissions. An agent that runs in a container, a CI job, or someone else's laptop can't reach it at all.

What an agent needs is an HTTP endpoint it can call from anywhere, a credential that can be scoped and revoked without touching the trading account, and a reference it can read so it doesn't invent the API.

What an agent actually needs

Two things, and both are boring.

An HTTP API. Every coding agent can make HTTP requests. None of them can drive a Windows terminal. If the account is reachable as GET https://api.metakit.cloud/v1/accounts/2/performance, the agent already knows how to use it.

A machine-readable reference. Agents are excellent at using APIs they've read and terrible at using APIs they've guessed. We publish llms.txt: the complete public API in one file, every endpoint, field, error code, and constraint, written for a model rather than a person. Fetching https://app.metakit.cloud/docs with Accept: text/markdown returns the same file, for agents that go to the docs URL first.

There is also a skill file at https://metakit.cloud/.well-known/agent-skills/metakit-api/SKILL.md. It's a short front-loaded summary in the format agent frameworks discover automatically: essentials, gotchas, and a pointer to llms.txt for the rest. Claude Code and similar tools can pick it up as a skill; everything else can just read it.

The safety model, in order

Do these in sequence. Each layer is independent, so if one is skipped the others still hold.

1. Connect the account with the investor password

MT5 accounts have two passwords. The master password can trade, change passwords, and on many brokers touch funds. The investor password can only look. Connect the account to MetaKit with the investor password and type: "readonly", and the account itself is incapable of trading, no matter what sits on top of it. The investor password post explains the split; the short version is that for an agent that reads, there is no reason the master password should ever leave your password manager.

A read-only slot is $5 a month, and it's the right slot for this.

2. Give the agent a readonly API key with an expiry

API keys carry a scope. A readonly key can make GET requests and nothing else; a POST, PATCH, PUT, or DELETE comes back as a 403 with the code insufficient_scope. That means the agent can't connect new accounts, can't delete the ones you have, can't create a copier, can't buy a slot with your saved card. It reads.

Keys can also carry an expiry date, after which every request fails with key_expired. Give the agent's key a two-week expiry. If the experiment turns into something permanent, create a new one. If the key leaks, it's dead by the time anyone finds it. The key scopes post goes deeper on why this is the right default.

3. Never put the key in the prompt

The key belongs in an environment variable or a secret store. The agent's code reads it from process.env.METAKIT_KEY or os.environ["METAKIT_KEY"], and the value never appears in a chat message, a transcript, a screenshot, or a repo. Set it once in the shell the agent runs in, or in a .env file that's in .gitignore:

export METAKIT_KEY="stk_live_..."

Then tell the agent "the API key is in METAKIT_KEY" and nothing more.

4. The order endpoints are exactly why steps 1 to 3 matter

/v1 can place trades: POST /v1/accounts/{id}/orders, plus endpoints to move stops, close, and cancel. Every one of them refuses a readonly key and refuses an account connected on a readonly slot, before anything reaches the terminal. So the two cheap decisions above, investor password and read-only key, are not belt and braces. They are the thing standing between an agent's bad afternoon and a market order. Keep them, and the worst case for an over-curious agent is a wrong summary. Give it a full key on a full account only when you actually want it executing, and then insist it sends an Idempotency-Key on every order so a retry can never fill twice.

A concrete walkthrough

Assume an account is connected with an investor password, METAKIT_KEY is a read-only key in the environment, and you're in Claude Code, Cursor, or any agent with a shell and HTTP. The prompt that works looks like this:

Read https://metakit.cloud/llms.txt before doing anything else and treat it
as the only API reference. The API key is in the METAKIT_KEY environment
variable; never print it.
 
List my accounts, then for each one that is connected give me a summary of
the last 7 days: net P/L, number of closed trades, win rate, and the worst
single day. Use the sessions series from the performance endpoint, not the
timeline. Report dates in UTC.

The agent lists GET /v1/accounts, filters on status === "connected", calls GET /v1/accounts/{id}/performance?range=1m for each, and reads the last seven entries of sessions. The net and drawdown per session give the daily figures. closed_trades and win_rate at the top level cover the whole range, not the week, so a careful agent pulls GET /v1/accounts/{id}/deals?from=... for the last seven days and counts trades by grouping on positionId. Nothing gets invented, because every field it needs is in the file it was told to read.

The second question people ask is the useful one for anybody running several prop-firm accounts:

Which of my accounts is closest to its drawdown limit right now?
Use GET /v1/monitors: for each monitor with metric "drawdown", compare
last_value to threshold and rank by remaining room. Include the account
name and last_checked_at.

Each equity monitor exposes threshold, last_value, status, and last_checked_at, so the ranking is one request and a subtraction. If you don't have monitors, the agent can fall back to max_drawdown_pct from /performance against a limit you state in the prompt, though that's drawdown over the range rather than drawdown right now, and a good agent will say so.

For a recurring version, put the prompt in a scheduled job. The key is read from the environment on each run, so rotating it is a one-line change.

What agents get wrong

Handing a model a trading API surfaces the same four mistakes every time, which is most of the reason llms.txt exists.

Counting deals as trades. A round-trip trade is two deals sharing a positionId, so an agent that counts rows in /deals reports double the trades and averages profit across entry rows that carry zero. The orders, deals and positions post has the full explanation. The cheap fix: point the agent at /performance, which already groups by position.

Ignoring server time. Models have read a lot of MQL5 forum posts and will happily assume timestamps are in broker time, or attach your local timezone to a naive value. MetaKit returns every timestamp as ISO 8601 UTC, and the reference says so. Tell the agent to report in UTC and to compute daily figures on UTC days unless you say otherwise.

Hallucinated endpoints. Left to guess, an agent will call /v1/trades, /v1/deals?account_id=2, /docs/accounts, or /performance?range=1w. None exist. The account is always a path segment, the ranges are 1m, 3m, 6m, 12m, and all, and there are no per-topic docs pages. A model that has actually read llms.txt doesn't do this; a model that was told "the docs are at app.metakit.cloud" does.

Treating starting as failure, and polling too hard. A freshly connected account passes through provisioning and starting before connected, and data endpoints return 502 until then. Agents love to retry in a tight loop. Deal history is cached for about a minute server-side, so polling faster than that returns the same numbers with more load.

None of these are model failures so much as documentation failures. An agent with the complete reference in context, a key that can only read, and an account that can only be looked at is a very safe thing to have poking around your trading history.

Create the read-only key with an expiry, export it, and paste the first prompt above. You'll have the weekly summary before you've finished reading the full reference yourself.