MCP server: connect Claude, ChatGPT and AI agents to MetaTrader 5
Connect Claude (claude.ai, Desktop, Code), ChatGPT and other AI agents to your MetaTrader 5 accounts through the fxapis MCP server: sign in, choose read-only or trading per account, revoke any time. Setup per client, the tool reference, and the safety model.
fxapis runs a hosted Model Context Protocol (MCP) server. Add it to an AI app, sign in to fxapis, and the assistant can read your MetaTrader 5 accounts, positions, orders and history. If you allow it, it can also trade.
https://api.fxapis.com/mcpThere is nothing to install. The MT5 terminals run in our EU cloud, as for every fxapis call.
An app you allow to trade trades real money
Connect read-only first, and try trading on a broker demo account. Trading is off unless you turn it on when you sign in. It applies only to the accounts you pick, and it needs two-factor. Claude still asks you before every trade. Read the Safety model before allowing a live account.
How it works
- Sign in, no key to copy. The first time the app uses fxapis, it opens fxapis's sign-in page. You choose what it may do:
- Read access: accounts, positions, orders, deals, figures and quotes. This is always included.
- Trading: off by default. Turn it on per account: everything the app changes — opening, closing, stops, cancelling, bringing online, taking offline — is limited to the accounts you pick. It needs two-factor turned on; your session already proved it at sign-in, so there is no code to enter here. You can also set a maximum order size and a number of orders a day.
- Revoke any time. Every app you connect is listed on the API keys page under Connected apps, with when it was last used. Revoke ends its access on its very next request. Removing someone from the workspace, or changing their role, revokes the apps they connected.
- The same rules as the REST API. A connected app acts through the ordinary
/v1endpoints with exactly what you chose. Workspace isolation, rate limits, plan limits, idempotency and our trading kill switch all apply. Each tool call counts as one or two API calls on your plan. - API keys still work for scripts and unattended agents: send
Authorization: Bearer fx_live_…orX-API-Key. See Agents with an API key. - Deliberately missing: connecting an MT5 account and managing keys. Connecting takes the broker password, which must never pass through an AI model. Do both in the console.
Under the hood:
- the server speaks Streamable HTTP, stateless, in both the 2026-07-28 and the 2025 protocol revisions;
- sign-in is OAuth 2.1 with PKCE, as the MCP authorization spec asks, discovered from
https://api.fxapis.com/.well-known/oauth-protected-resource/mcp; initializeandtools/listanswer without signing in. A tool call without a credential gets401with aWWW-Authenticatechallenge that points the app at the sign-in.
Connect your app
Claude (claude.ai and Claude Desktop)
On any Claude plan:
- Open Customize → Connectors → Add custom connector. On Team and Enterprise, an Owner adds it under Organization settings → Connectors.
- Remote MCP server URL:
https://api.fxapis.com/mcp. Leave the OAuth client fields empty: Claude registers itself. - Click Connect, and sign in to fxapis in the window that opens. Choose read-only or trading, then allow it.
Connectors you add on claude.ai are also in the Claude desktop app.
Claude Code
claude mcp add --transport http fxapis https://api.fxapis.com/mcpThen run /mcp, choose fxapis, and Authenticate: your browser opens fxapis's sign-in.
Or install the fxapis plugin. It adds the server, a safe-trading skill and a hook that confirms every trade:
/plugin marketplace add FXapis/fxapis-claude-plugins
/plugin install fxapis@fxapisChatGPT
In ChatGPT, turn on Settings → Apps → Advanced settings → Developer mode (on the plans OpenAI offers it on). Then Create app:
- MCP server URL:
https://api.fxapis.com/mcp - Authentication: OAuth
Sign in to fxapis when ChatGPT asks.
Cursor, VS Code and other clients
Any client that supports MCP's OAuth sign-in connects with the URL alone. fxapis accepts sign-in return addresses for Claude, ChatGPT, and apps on your own computer (http://localhost and http://127.0.0.1). Clients that return to a custom scheme, such as cursor:// or vscode://, are not accepted yet: use an API key with them.
To test from a terminal with the MCP Inspector:
npx @modelcontextprotocol/inspector https://api.fxapis.com/mcpAgents with an API key
For an agent that runs unattended, create a key just for it, with the fewest scopes that do the job:
| The agent should… | Scopes |
|---|---|
| Report on accounts, positions and history | accounts:read, trading:read, history:read |
| …and bring accounts online or take them offline | add accounts:write |
| …and manage risk: close, move stops, cancel — never open | add trading:reduce |
| …and open new positions | add trading:execute |
Send it as Authorization: Bearer fx_live_…, or as X-API-Key: fx_live_… for clients that only offer that header.
Claude Code, with a key:
claude mcp add --transport http fxapis https://api.fxapis.com/mcp --header "Authorization: Bearer $FXAPIS_KEY"Cursor (~/.cursor/mcp.json):
{ "mcpServers": { "fxapis": { "url": "https://api.fxapis.com/mcp", "headers": { "Authorization": "Bearer ${env:FXAPIS_KEY}" } } } }VS Code (.vscode/mcp.json):
{
"inputs": [{ "type": "promptString", "id": "fxapis-key", "description": "fxapis API key", "password": true }],
"servers": { "fxapis": { "type": "http", "url": "https://api.fxapis.com/mcp", "headers": { "Authorization": "Bearer ${input:fxapis-key}" } } }
}OpenAI API (Responses). Put this in the request's tools:
{ "type": "mcp", "server_label": "fxapis", "server_url": "https://api.fxapis.com/mcp", "authorization": "fx_live_…", "require_approval": "always" }Anthropic API (Messages). Use mcp_servers: [{ "type": "url", "url": "https://api.fxapis.com/mcp", "name": "fxapis", "authorization_token": "fx_live_…" }], with an mcp_toolset tool for fxapis, as Anthropic's MCP connector documentation describes.
Every config is also in fxapis-mcp-examples.
Revoking access
- A connected app: on the API keys page, under Connected apps, choose Revoke.
- Its access ends on its next request, its sign-in can no longer be refreshed, and any sign-in still in progress is cancelled.
- Owners and admins see and revoke everyone's connected apps. Members see their own.
- A key: revoke it on the same page. It is refused from its next request.
Tools
Arguments are snake_case. Account ids are the fxapis UUIDs from list_accounts, not MT5 logins. Volumes and prices are strings ("0.10", "1.08450").
Results are small by design:
- one line for the model, plus the data once as compact JSON;
response_format: "detailed"adds every field the API has;- lists answer
{ items, next_cursor, total }25 at a time; passnext_cursorback ascursor.
Answer a question in one call
| Tool | What it does | Scope |
|---|---|---|
get_account_overview | An account's state, environment, balance, equity, and its largest positions with total P/L | accounts:read, trading:read |
get_symbol_snapshot | A symbol's specification, live quote, whether the market is open, and the margin for a volume | accounts:read, trading:read |
Read-only
| Tool | What it does | Scope |
|---|---|---|
get_workspace | Plan, its limits and features, and whether trading is switched off | accounts:read |
get_usage | This month's usage against the plan | accounts:read |
list_accounts | Accounts with id, login, server, state and environment (demo or live) | accounts:read |
get_account | One account and its last-read balance and equity | accounts:read |
get_account_status | Just the state — poll it after bring_accounts_online | accounts:read |
get_account_figures | Balance, equity, margin and margin level; fresh: true asks the terminal | accounts:read |
list_positions | Open positions as last observed | trading:read |
list_instruments | Markets named once (XAUUSD, US30…) | any |
search_broker_servers | The exact MT5 server for a broker | accounts:read |
list_account_instruments | Each instrument's symbol on an account's broker; query narrows it | accounts:read |
get_market_hours | Whether a market is open now, and when it opens or closes | accounts:read |
get_quotes | Live bid and ask for up to 20 symbols | trading:read |
list_orders | Orders, newest first, by account, state, symbol and time | trading:read |
get_order | One order and the broker's answer; optionally its deals | trading:read |
list_deals | The broker's deal history for an account | history:read |
list_multi_account_orders | Recent multi-account orders | trading:read |
get_multi_account_order | One multi-account order, account by account | trading:read |
calculate | Margin or profit, as the broker computes it; opens nothing | trading:read |
Account lifecycle
| Tool | What it does | Scope |
|---|---|---|
bring_accounts_online | Starts and logs in accounts; poll get_account_status | accounts:write |
take_account_offline | Stops the terminal; positions and stops stay at the broker | accounts:write |
Trading
These are marked destructiveHint: true, so Claude and other careful clients ask before each one. Each requires an idempotency_key: a fresh UUID per action, and the same one only to retry that action. With it, a retried order is never a second order, and a retried close is never an opposite position.
| Tool | What it does | Scope |
|---|---|---|
place_market_order | Opens a position at market | trading:execute |
place_pending_order | A limit, stop or stop-limit order | trading:execute |
close_position | Closes a position in whole or in part | trading:reduce |
modify_position | Moves or removes a stop loss or take profit | trading:reduce |
cancel_order | Cancels a pending order | trading:reduce |
place_multi_account_order | The same trade on many accounts | trading:execute |
cancel_multi_account_order | Calls one off before anything is sent | trading:reduce |
A connected app that was not allowed to trade, and calls a trade tool, gets 403 with WWW-Authenticate: Bearer error="insufficient_scope", scope="… trading:execute". The app then asks you to sign in again, and the sign-in page opens with Trading selected.
Errors
A failure comes back as an MCP tool error (isError: true) whose text starts with the API's
own error code, followed by the message, any details, what to do next and the
request id:
ORDER_UNRESOLVED (HTTP 503): Something went wrong and we do not know yet whether the order was sent. We are confirming it with the broker. Do not resend it.
details: [{"orderId":"5b0e7c1a-2f4d-4a8e-9c3b-1d6f0e2a7b94","state":"unknown","retryable":false}]
Next step: Do NOT resend this order. Its outcome is unknown and it may be live at the broker. Poll get_order with the orderId in details until it leaves `unknown`, and tell the user.
requestId: 3f8a1c92-7b4e-4d81-a2f6-0c5e9b3d7a14The same code, status, message, request id and next step are in the result's _meta under
com.fxapis/error, for programs.
The codes that matter most to an agent:
| Code | Meaning for the agent |
|---|---|
ORDER_UNRESOLVED | The outcome is unknown and the order may be live. Never resend; poll get_order |
SEND_FAILED | Nothing reached the broker. Retry with the same idempotency_key |
ORDER_REJECTED | The broker refused it; nothing was opened. Tell the user the reason |
MISSING_SCOPE | This connection does not allow it. Ask the user; do not look for another way |
KEY_LIMIT_EXCEEDED | A limit chosen for this connection or key refuses it; details say which |
ACCOUNT_NOT_READY / NO_RUNTIME | Bring the account online, wait for ready, then retry |
RATE_LIMITED | Wait retryAfterSeconds, then retry once |
TRADING_DISABLED | Trading is switched off for the account or workspace. Do not retry |
Every code and its next step: error codes in the skill.
Safety model
An agent is a new kind of caller. It can misread a request, act on text planted in a web page, or loop. The protections, from strongest to weakest:
-
What you allowed. Enforced by the API on every call, whatever the model decides:
- a connected app's choices on the sign-in page: read-only, or trading on the accounts you picked, within the size and daily limits you set;
- a key's scopes and limits.
A read-only connection cannot trade. A trading connection cannot change anything on an account you did not pick: it cannot open, close, move stops on or cancel orders there, or bring that account online or take it offline. It can still read every account in the workspace.
-
Two-factor for trading. Letting an app trade needs two-factor turned on; signing in with it already proved it, so nothing more is asked at consent.
-
Demo accounts. fxapis has no simulated market. Broker demo accounts are how you test.
-
Your plan's limits and rate limits. Closing is never refused for billing.
-
Your app's confirmations. Trading tools are marked destructive, so Claude asks before each trade. The Claude Code plugin makes that a rule, and refuses live accounts until you allow them.
-
The tool descriptions and the skill. They tell the model to confirm every trade and never to resend an unresolved order. That shapes behaviour; it does not enforce anything. Points 1 and 2 do.
Every order an agent places is recorded like any other, with the key or connected app that placed it. Tool calls are logged with the tool name, the workspace and the outcome, never the arguments.
Directories
Claude's and ChatGPT's app directories do not list tools that execute financial transactions. So:
- the full server above is added by URL, or through the Claude Code plugin;
- the directories list the read-only connector, which never trades.
Example prompts
- "Which of my MT5 accounts are online, and what positions are open on each?"
- "What was my realised profit on EURUSD this week on the Vantage demo account?"
- "How much margin would 0.5 lots of XAUUSD need on account 2?"
- "Bring all my accounts online, then tell me when they are ready."
- "Move the stop loss on my gold position to break-even." (needs
trading:reduce) - "Close half of every open EURUSD position on the demo account." (needs
trading:reduce) - "Buy 0.01 lots of EURUSD on the demo account with a 20-pip stop." (needs
trading:execute) - "Did anything go wrong with today's orders? Show me any that are still
unknown."
Limits of the MCP server today
- No streaming or notifications. Tools answer once. Follow an account coming online, or a multi-account order settling, by polling, as with the REST API. For your own server, use webhooks.
- Custom-scheme sign-in returns (
cursor://,vscode://) are not accepted yet. Use an API key with those clients. - MetaTrader 5 only. MT4 is not supported.
TradingView alerts to MT5 — no EA, no VPS
Turn TradingView alerts into MetaTrader 5 orders with a secret webhook URL: create a hook in the console or the API, set up the TradingView alert step by step, message formats and placeholders for indicators and strategies, closing, idempotency, the IP allowlist, troubleshooting and limits.
Claude plugin and skill
The fxapis plugin for Claude Code: the MCP server with sign-in, the trading-mt5-safely skill, status and positions commands, and a hook that confirms every trade and refuses live accounts until you allow them. The skill is also a zip for claude.ai.