AlgoVesta Trading
MCP server for 16 crypto exchanges + MetaTrader 5.
От сообщества: Добавлен пользователем или импортирован; проверьте владельца перед подключениемРаботаетБез входаГлобальныйБесплатноТолько чтение
Что умеет
- Get Portfolio Context: Normalized portfolio view of all connected exchange accounts + MT5 + paper. Takes no parameters; returns ONLY the accounts of the user whose key the connection was made with. IM
- Get Market Price: Returns the LIVE price of a crypto or MT5 symbol: last (+ bid/ask if available) + ts + source. Take the price FROM HERE before opening an order — do NOT use your own estimate or stal
- Simulate Order: SIMULATES an order: expected fill, margin impact, policy check result. Sends NO real order. This is a READ operation — do NOT ask the user for confirmation before calling simulate_orde
Какие данные видит
Нужен ли аккаунт
Не нужен: сервер работает без входа
MCP server for 16 crypto exchanges + MetaTrader 5. Crypto and MT5 in one MCP connection: read balances, open and close positions, move stop-loss / take-profit, and audit every action — from Claude, ChatGPT, Cursor, Claude Code, Gemini CLI or any MCP-capable client.
Safety is enforced on the server, outside the model's reach:
- Paper by default. Every new key starts on a $5,000 paper balance. Live trading requires a separate, 2FA-protected approval.
- Risk rules run server-side. Daily loss limits, drawdown caps and position limits are evaluated before an order leaves — the model cannot disable them.
- Stop-loss is mandatory. Orders without a stop-loss are rejected.
- Signed receipts. Every action returns an ed25519-signed receipt you can verify independently.
- Idempotent orders.
place_orderrequires an idempotency key; a repeated key returns the stored response and never opens a second order.
The server is hosted and closed-source — nothing to install or build. Sign in with Google, Apple or e-mail and authorize; no exchange API keys are ever handed to the AI.
Список инструментов сервера (20)
Технические названия из tools/list. Нужны только разработчикам.
| get_portfolio_context | Normalized portfolio view of all connected exchange accounts + MT5 + paper. Takes no parameters; returns ONLY the accounts of the user whose key the connection was made with. IMPORTANT (crypto accounts): "balance"/"equity" is the futures wallet ONLY. The spot wallet balance is in the separate "spot_balance" field (there MAY be money on spot even when futures shows 0 — check spot_balance before telling a user they have no balance). IMPORTANT (forex/MT5 accounts): check the "positions_source" field on each account. "live_ea" means the position list is real data verified by the MetaTrader 5 Expert Advisor (EA) AlgoVesta runs on its managed terminal. "unavailable" means the EA/terminal could not be reached — in that case positions=[] does NOT mean "no open positions", only that it could not be verified. For such an account never tell the user definitively "you have no open positions"; say "this cannot be verified right now, try again or check the terminal". |
| get_market_price | Returns the LIVE price of a crypto or MT5 symbol: last (+ bid/ask if available) + ts + source. Take the price FROM HERE before opening an order — do NOT use your own estimate or stale knowledge. A current price is essential when computing SL/TP/limit levels. Source order: (1) the shared price cache (~1s fresh), (2) if not cached, a single live REST call to the exchange. If the price is older than 10s OR cannot be fetched, that is stated EXPLICITLY — a stale price is never presented as live. If venue is given, that exchange is used; otherwise the user's CONNECTED exchanges are searched. If found on no CEX, a DEX (DexScreener) informational price is returned together with a 'you CANNOT trade this on your connected exchanges' warning. Returns: {ok, venue, symbol, last, bid, ask, ts, source, age_sec} or {ok:false, error,...}. |
| simulate_order | SIMULATES an order: expected fill, margin impact, policy check result. Sends NO real order. This is a READ operation — do NOT ask the user for confirmation before calling simulate_order. Show its result to the user as ONE summary and ask for ONE confirmation; call place_order once confirmed. Ask for all missing fields in ONE message; NEVER invent a value for any field. AMOUNT DISTINCTION (CRITICAL): if the user says 'X dollars' with leverage (e.g. '$20 at 5x') and it is NOT clear whether they mean MARGIN (margin_usd=20 -> a $100 position) or POSITION VALUE (size_usd=20 -> a $20 position), ASK — do not open an order of the wrong size. SIZE FIELD DEPENDS ON MARKET: forex/MT5 -> `lots` (0.05, 0.10... exactly what the customer said); crypto -> EXACTLY ONE of size_usd/margin_usd/risk_pct. Do not send `leverage` for forex. |
| place_order | Places an order. idempotency_key is REQUIRED: if the same (user, key) arrives a second time the stored response is returned and a second order is NEVER opened. scope=paper runs on the paper engine, scope=live runs through live execution. The policy wall runs server-side; a violation means a hard reject + audit entry. CONFIRMATION: if the user has ALREADY confirmed the simulate_order summary once, call place_order DIRECTLY — do not ask again, do not reprint the summary, do not re-ask for information. Ask for all missing fields in ONE message; NEVER invent a value for any field. AMOUNT DISTINCTION (CRITICAL): if 'X dollars' with leverage is ambiguous between MARGIN (margin_usd) and POSITION VALUE (size_usd), ASK — do not open an order of the wrong size. SIZE FIELD DEPENDS ON MARKET: forex/MT5 -> `lots` (exactly the lot size the customer stated, never rounded to a fixed value); crypto -> EXACTLY ONE of size_usd/margin_usd/risk_pct. Do not send `leverage` for forex (the product is unleveraged). ACCOUNT DISTINCTION (CRITICAL): the user may have several accounts in the same market (two MT5 accounts, 'Binance' + 'Binance2'). Pass WHICH account via `account`; if it is not clear, ASK. Opening an order in the wrong account is WORSE than not opening one at all. |
| compile_policy | Compiles natural-language risk rules into a JSON policy and returns a PREVIEW. Activation requires separate approval: from the panel or via POST /api/mcp/policies/{policy_id}/activate. |
| list_open_orders | Lists the user's pending limit orders (order_ref, venue, symbol, side, entry_price, size, created_at). Only PAPER limit orders can rest here: live crypto venues accept market orders only (a live crypto limit order is refused with live_limit_not_supported, never silently converted), so an empty list on a live account means nothing is pending — not that something disappeared. VERIFICATION: call get_portfolio_context / list_open_orders WITHOUT asking for confirmation (they are read operations). Ask the user only ONE confirmation question. |
| cancel_order | Cancels a pending limit order. If order_ref does not belong to the user, NOT_FOUND is returned (no information about another user's order is disclosed). idempotency_key is REQUIRED: calling again with the same key returns the stored response. This is a RISK-REDUCING operation: the policy wall does not block it (except the kill switch). VERIFICATION: call list_open_orders WITHOUT asking for confirmation (it is a read operation), then cancel with ONE confirmation. Never choose an order the user did not name. |
| close_position | Closes an open position fully or partially (fraction (0,1]). Works for crypto and FOREX/MT5. This is a RISK-REDUCING operation: the policy wall NEVER blocks this tool (except the kill switch). idempotency_key is REQUIRED: even 10 calls with the same key perform ONE close. If no position exists, POSITION_NOT_FOUND is returned together with the open positions on that venue. MT5 positions can only be closed IN FULL (no partial close) -> use fraction=1. If several MT5 positions are open on the same symbol, `ticket` becomes REQUIRED; while it is ambiguous, none are closed. VERIFICATION: call get_portfolio_context / list_open_orders WITHOUT asking for confirmation (they are read operations). Ask the user only ONE confirmation question. |
| modify_position | Updates the SL/TP of an open position — works for crypto and FOREX/MT5. AT LEAST ONE of new_sl/new_tp must be given. SL CANNOT BE REMOVED (the mandatory-SL rule stands). Logic: long requires new_sl < mark < new_tp, short the reverse. idempotency_key is REQUIRED. If you send only ONE side, the other keeps the position's CURRENT value — the side you omit is NOT deleted. If several MT5 positions are open on the same symbol, `ticket` becomes REQUIRED; while it is ambiguous, NONE are modified. VERIFICATION: call get_portfolio_context WITHOUT asking for confirmation (it is a read operation), then apply with ONE confirmation. Never change levels the user did not specify. |
| verify_receipt | Verifies an order receipt: ed25519 signature + per-user hash chain. Returns signature_valid + chain_valid (verified = both True). If an earlier receipt in the chain was altered, chain_valid=False (proof of tamper-evidence). Public key: /mcp/receipts/pubkey. Receipts issued before the ed25519 rollout were HMAC-signed and return legacy=True. |
| replay_channel | Answers "what if you had followed this Telegram channel for the last N days under these rules?". Simulates the channel's past signals paper-style; every signal passes the policy wall (rejected ones are not opened). Progress is published as replay_progress events. Results are cached for 24 hours (the same channel + parameters return from cache). Rate limit: 5 replays/hour. Output: {trades:[...], summary:{total_pnl, win_rate, max_drawdown, avg_rr, policy_rejections}}. |
| get_trade_history | Returns the user's CLOSED trades and a performance summary, across crypto exchanges, MetaTrader 5 and the paper account in one list. Each trade carries symbol, side, size, entry/exit price, SL/TP, PnL, venue, source (telegram / webhook / mcp / manual) and timestamps. The summary adds win rate, total PnL, average R-multiple and a per-venue breakdown. HOW TO READ IT HONESTLY - say these out loud instead of smoothing them over: - `avg_rr` is computed only from trades where entry, SL and exit are ALL known; `rr_sample` tells you how many trades that was. A 3-trade average is not evidence. - `total_pnl` is null when several account currencies are mixed (e.g. a EUR MT5 account next to USD crypto). Use `pnl_by_currency` and never add them together. - `fee` is null because commission is not recorded; PnL is therefore GROSS on crypto. - `incomplete_sources` means part of the history could not be read - the summary is then incomplete and you must say so. This is a read tool: call it without asking the user for confirmation. It is history only; it does not tell you what will happen next, and past results do not predict future ones. |
| compare_venues | Compares the user's CONNECTED crypto exchanges for one symbol on measured execution cost: bid/ask spread, taker fee, and — when size_usd is given — the slippage that size would actually pay against the live order book. THIS TOOL DOES NOT CHOOSE AN EXCHANGE AND NEITHER SHOULD YOU. It is advisory only. The user still names the venue in place_order. AlgoVesta could not route around it even in principle: in crypto there is no central clearing, so the user's balance lives on the exchange they funded and cannot be moved to another one to catch a better price. HOW TO READ IT: - `estimated_cost_bps` sums ONLY the components listed in that venue's `cost_components`. A venue with fewer components is not cheaper — it is less measured. Say which components were included. - `cheapest_measured` means lowest measured cost, not lowest true cost. - Fees are the exchange's PUBLIC tier. The user's own VIP tier may be lower; repeat `fee_tier_note` rather than presenting the fee as personal. - `skipped` lists venues removed WITH A REASON (symbol not listed, minimum order value above the request, or recorded equity below it). A venue is never removed just because data was missing — missing data shows as null, not as exclusion. - Still not measured: per-venue latency, transfer fees, funding differences. |
| list_strategies | Lists the user's TradingView strategies with their settings, plan limit and whether real-money execution is currently on. Read `auto_trade` carefully and report it plainly: auto_trade=false means signals are only recorded, NOT traded with real money. auto_trade=true means every accepted signal on that strategy becomes a real order. The webhook URL is NEVER returned - that address is a password: anyone holding it can send signals into the account. The user copies it from the AlgoVesta panel. This is a read tool: call it without asking for confirmation. |
| create_strategy | Creates a new TradingView strategy. It starts with REAL-MONEY EXECUTION OFF (auto_trade=false) and that cannot be changed from here - the user turns it on themselves in the AlgoVesta panel. Creating a strategy therefore never risks money. The strategy's webhook URL is not returned (it is a password); tell the user to copy it from the panel and paste it into their TradingView alert. Fails with a plan-limit error if the account has reached its strategy quota; call list_strategies first to see `plan_limit` and `can_create_more`. idempotency_key is REQUIRED: calling again with the same key returns the stored response instead of creating a SECOND strategy. |
| update_strategy | Changes the settings of an existing strategy (leverage, risk, SL/TP percentages, trailing, allowed symbols, target account, and whether it accepts signals at all). WHAT THIS TOOL CANNOT DO, on purpose: - `auto_trade` (the real-money switch) is REFUSED. A single order is one action; a strategy runs forever, so turning real money on stays a human decision made in the panel. - `ip_allowlist` is REFUSED: it is the second factor that verifies where signals come from, so it must not be weakened from here. - Deleting a strategy is not possible here; that is done in the panel. Fields that were refused come back in `refused_fields` - report them to the user rather than silently claiming success. If you set `reverse_enabled` to true the response contains a `warning`: from then on a BUY signal opens a SHORT and a SELL signal opens a LONG on that strategy. You MUST pass that warning on to the user. Never change a setting the user did not ask for. idempotency_key is REQUIRED. |
| backtest_my_signals | Answers "what would have happened to MY OWN past signals with different settings?" - for example "5x instead of 10x" or "a 2% stop instead of 1%". It replays the signals YOU actually received (your Telegram channels and your TradingView webhooks) against real historical 1-minute price data, twice: once with each signal's original stop-loss, take-profit and leverage, and once with the settings you asked for. The difference is reported under `comparison`. This runs in the background because a full replay can take several minutes. The call returns a `job_ref` immediately; poll `get_job_status(job_ref)` for the result. What the result always tells you, and what you MUST pass on to the user: - `coverage`: how many of their signals could actually be simulated. If some had no historical price data or no stop-loss, the numbers describe only the subset. - `assumptions`: fees, slippage, partial-take-profit behaviour and what is NOT modelled (funding fees). Never present the PnL without these. - Past performance does not guarantee future results. This is not investment advice. |
| simulate_policy | Answers "if I had had this risk rule in place, which of my trades would it have blocked, and what would that have done to my PnL?". It takes a risk policy - written in plain English, passed in already compiled, or your currently active one - and applies it to the trades YOU actually closed. It reports which ones would have been rejected, by which rule, and the PnL difference. Runs in the background: the call returns a `job_ref`, and `get_job_status(job_ref)` returns the result. Two honesty limits are always reported in `assumptions` and MUST be passed on: - Rules that depend on account state at the moment of the order (open position count, daily loss so far, balance) are evaluated with zeros, because that state cannot be reconstructed from closed trades. Those rules are UNDER-counted, never over-counted. - PnL comes from your recorded realised results; it is not re-simulated. If your trades settled in more than one currency, totals are reported per currency and are NOT added together. |
| import_tradingview_backtest | Answers "TradingView says my strategy made X - what would it have made through AlgoVesta?". You export the strategy's trade list from TradingView and this recomputes it with real trading costs: taker fees on entry and exit, and the slippage we actually measure on fills. TradingView's default backtest applies neither unless the strategy author configured them, which is why exported results are usually optimistic. Runs in the background: the call returns a `job_ref`; read the result with `get_job_status(job_ref)`. Deliberate limits, always repeated in the result: - Pine Script is NOT executed or interpreted. Only the trade list you exported is recomputed. Entry and exit prices stay exactly as TradingView reported them. - Funding fees are not modelled. - Rows without a quantity column cannot have fees applied, so their figures stay optimistic; the count of such rows is reported. |
| get_job_status | Returns the state and, once finished, the result of a background job started by backtest_my_signals, simulate_policy or import_tradingview_backtest. Call it with no argument to list your recent jobs. `status` is one of: PENDING (queued), RUNNING (in progress - `progress` is a percentage), DONE (`result` is present), FAILED (a retry is scheduled), DEAD (it will not be retried - `error` says why) or CANCELLED. Jobs run one at a time, so `queue_position` tells the user how many are ahead of theirs. Do not poll faster than about once every 10 seconds, and tell the user what the job is doing rather than repeating raw status codes at them. Storage: only the 20 most recent finished jobs keep their full result. Older ones are reduced to their summary and come back with `result_pruned: true` — the detailed rows are gone and the job has to be run again to regenerate them. Everything is deleted after 30 days. Backtest and policy runs are also written to your account's backtest history, and the result carries the `run_id` they were stored under. |