# fxapis — MetaTrader 5

> Let AI agents trade and read MetaTrader 5 accounts. Hosted — no terminal for you to run.

- name: com.fxapis/mt5
- version: 1.0.0
- connection class: R1 (autonomous)
- trust: 82/100 flags: no-repository
- quality: 90/100 (strong)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/com.fxapis%2Fmt5
- tools: https://api.protogrid.dev/v1/servers/com.fxapis%2Fmt5/tools

**An agent can connect on its own if it already holds `MT5_TOKEN`.** Remote endpoint behind a static API key or header. The registry never sees the value; the agent fills the placeholder.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "mt5": {
      "type": "http",
      "url": "https://api.fxapis.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MT5_TOKEN}"
      }
    }
  }
}
```

Placeholders to fill: `${MT5_TOKEN}`.

## Trust

- hygiene: 80
- liveness: 99
- freshness: 100
- provenance: 55
- drivers: +dns-namespace +website +reachable +uptime-97% +updated-19d-ago -no-repository
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 90/100 (strong)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 93 (weight 30)

- pass `tools.descriptions`: every tool has a description
- pass `tools.description_length`: descriptions are concise
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 29 of 29 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- warn `tools.token_cost`: about 10,396 tokens to load every tool
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: n/a (weight 15)

- n/a `stability.changes`, `stability.rug_pull`: tool history recorded for 3 of the 7 days needed

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 29, about 10,396 tokens to load them all
- tool set hash: e7841dda6b371f207f444312465befe0
- badge: [![protogrid quality](https://protogrid.dev/badge/com.fxapis/mt5.svg)](https://protogrid.dev/servers/com.fxapis/mt5)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

_No tool definition changes recorded._

## Remotes

- https://api.fxapis.com/mcp (streamable-http, auth api_key ${MT5_TOKEN}, reachable true, uptime30d 0.9736842)

## Packages

_none_

## Tools (29)

- `bring_accounts_online`: Starts each account's MT5 terminal in the cloud and logs it in; poll get_account_status until `ready`. Places no trades and is safe to repeat. Example: {"account_ids": ["<id>"]}
- `calculate`: The margin an order would need, or its profit between two prices, as the broker computes it; opens nothing. The account must be online. Example: {"account_id": "<id>", "kind": "margin", "symbol": "EURUSD", "side": "buy", "volume": "0.10", "price": "1.08450"}
- `cancel_multi_account_order`: Calls off a multi-account order on the user's real broker accounts (or demo) before anything is sent. Once orders went out, close the positions instead. Example: {"multi_account_order_id": "<id>", "idempotency_key": "<new uuid>"}
- `cancel_order`: Cancels a pending order on the user's real broker account (or demo) that has not triggered. If it triggered there is a position to close instead. Example: {"order_id": "<id>", "idempotency_key": "<new uuid>"}
- `close_position`: Closes a position on the user's real broker account (or demo), whole or by volume. Sent twice it opens the opposite position, so reuse an idempotency_key only to retry the same close. Example: {"account_id": "<id>", "position_id": "<brokerPositionId>", "idempotency_key": "<new uuid>"}
- `get_account`: One account: login, broker, state, environment, and its last-read balance, equity and free margin. Example: {"account_id": "<id from list_accounts>"}
- `get_account_figures`: Balance, equity, margin, free margin and margin level as decimal strings in the account currency, read every 15 s while online. Set fresh to ask the terminal now (the account must be `ready`). Example: {"account_id": "<id>", "fresh": true}
- `get_account_overview`: One account in one call: state, environment, balance and equity, and its largest open positions with their total P/L. Start here when asked how an account is doing. Example: {"account_id": "<id>"}
- `get_account_status`: Just an account's state, cheap enough to poll every few seconds after bring_accounts_online until `ready`. States invalid_credentials, needs_2fa, needs_certificate and trading_disabled need the user, so stop polling. Example: {"account_id": "<id>"}
- `get_market_hours`: Whether a market is open now on this account's broker, and when it next opens or closes, in UTC. A broker holiday missing from its schedule still refuses orders. Example: {"account_id": "<id>", "instrument": "XAUUSD"}
- `get_multi_account_order`: One multi-account order and each account's result; poll it after placing one. An account left `unresolved` must not be resent, so poll its order instead. Example: {"multi_account_order_id": "<id>"}
- `get_order`: The authoritative record of one order: what was asked, the broker's answer, fill volume and price. Poll it after ORDER_UNRESOLVED until it leaves `unknown`. Example: {"order_id": "<id>", "include_deals": true}
- `get_quotes`: Live bid and ask for up to 20 symbols or instruments from this account's broker; a closed market answers its last price with marketOpen false. The account must be online. Example: {"account_id": "<id>", "instruments": ["EURUSD"]}
- `get_symbol_snapshot`: One symbol on one account in one call: its specification, live quote, whether the market is open, and the margin for a volume. Use it before proposing a trade. Example: {"account_id": "<id>", "instrument": "XAUUSD", "volume": "0.10", "side": "buy"}
- `get_usage`: This month's usage against the plan, and its cost so far in minor units (9900 is $99.00). Over quota opening is refused, closing never is. Example: {}
- `get_workspace`: This connection's workspace: its plan, the plan's limits and features, and whether trading is switched off. Call it first when unsure what the user can do. Example: {}
- `list_account_instruments`: Each instrument's symbol on this account's broker: mapped, ambiguous (with candidates) or missing. Trade the mapped symbol. Example: {"account_id": "<id>", "query": "XAU"}
- `list_accounts`: The workspace's MT5 accounts with id, login, server, state and environment (demo or live); use the id, not the login, everywhere else. Only `ready` accounts trade, so bring the others online first. Example: {"limit": 25}
- `list_deals`: An account's deal history as the broker recorded it, newest first, including stops that fired, swaps and manual trades. Realised profit is here. Example: {"account_id": "<id>", "since": "2026-10-01T00:00:00Z"}
- `list_instruments`: Markets named once (XAUUSD, US30, BTCUSD) whatever each broker calls them. list_account_instruments gives one account's own symbol for each. Example: {"category": "metals"}
- `list_multi_account_orders`: Recent multi-account orders (one trade on many accounts), each with its per-account result. Pages with limit and cursor. Example: {}
- `list_orders`: Orders placed through fxapis, newest first, for one account or all; state `unknown` means still being confirmed, so never resend those. Pages with cursor. Example: {"state": "unknown"}
- `list_positions`: Open positions on one account as last observed; brokerPositionId is what close_position and modify_position take. Pages with limit and cursor. Example: {"account_id": "<id>"}
- `modify_position`: Moves a position's stop loss or take profit on the user's real broker account (or demo); null removes a level. Remove a stop loss only when the user asks. Example: {"account_id": "<id>", "position_id": "<brokerPositionId>", "stop_loss": "1.08000", "idempotency_key": "<new uuid>"}
- `place_market_order`: Opens a position at market on the user's real broker account (or demo) and waits for the broker; confirm account, symbol, side and volume with the user first. On ORDER_UNRESOLVED never resend, poll get_order. Example: {"account_id": "<id>", "symbol": "EURUSD", "side": "buy", "volume": "0.10", "idempotency_key": "<new uuid>"}
- `place_multi_account_order`: Places the same market order on many of the user's real broker accounts (or demo) at once and returns at once; follow it with get_multi_account_order. Confirm the accounts, symbol, side and volume with the user first. Example: {"account_ids": ["<id>", "<id>"], "instrument": "XAUUSD", "side": "buy", "volume": "0.01", "idempotency_key": "<new uuid>"}
- `place_pending_order`: Places a limit or stop order on the user's real broker account (or demo) that waits at the broker; success means working, not filled. Confirm it with the user first. Example: {"account_id": "<id>", "symbol": "EURUSD", "side": "buy", "kind": "limit", "volume": "0.10", "price": "1.08000", "idempotency_key": "<new uuid>"}
- `search_broker_servers`: MT5 broker servers matching a broker or server name, servers seen working on fxapis first. A server not listed can still be used. Example: {"query": "icmarkets"}
- `take_account_offline`: Stops an account's terminal; open positions and their stops stay at the broker. Refused while an order is in flight. Example: {"account_id": "<id>"}
