milele-prime-mcp
OfficialClick on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@milele-prime-mcpshow my account summary"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
milele-mcp
Read-only MCP server for Milele Prime. Lets a verified client connect their own AI (Claude / ChatGPT) to their own trading account and read account data — no order execution in phase 1.
Stack
TypeScript · Node 22 · Express · @modelcontextprotocol/sdk · Zod · Postgres
(Supabase) · opaque revocable tokens · Vitest · Railway.
Related MCP server: hl-read
The core idea: two interfaces are the swap point
Everything in src/ talks to two interfaces, never to a real API:
IdentityProvider(src/providers/interfaces/identity.ts) — Brokeret fills thisTradingDataProvider(src/providers/interfaces/trading.ts) — MT5 Manager API fills this
Trading is real (MT5, verified live). Identity is still mock — see the warning under Deploy.
Run it
npm install
cp .env.example .env # defaults to mock providers, no infra needed
npm run dev # boots on :8080
npm test # 56 tests, fully offline
npm run mt5:test # staged MT5 connectivity probe (needs credentials)
npm run mt5:verify # exercises all 6 read methods against the live serverThe tool surface (6 read tools)
Tool | MT5 command(s) |
|
|
|
|
|
|
|
|
|
|
|
|
There is no get_price_history. This access server's Web API exposes no
OHLC/bars command — CHART_GET, CHART_REQUEST, BAR_GET, RATE_GET,
TICK_HISTORY and ~50 other spellings were all rejected by the live server
while every real command answered (an unknown command drops the socket, which
makes that a reliable negative). Rather than advertise a tool that always
fails, the capability is absent from the interface and the MCP surface.
Restoring it needs a separate feed: the MT5 Gateway/datafeed API, or the
broker's own history service.
The five write tools (place_market_order, place_pending_order,
modify_position, close_position, cancel_order) are still registered but
unimplemented against MT5 — the real adapter throws not wired yet, so they
return internal_error. Phase 2.
How MT5 is wired
The MT5 "Web API" is not HTTP/REST despite the name and the :443 port. It
is a raw TCP socket protocol, and the session is the socket — no cookie, no
bearer token. Framing and the challenge-response handshake live in
src/providers/real/mt5/protocol.ts.
src/providers/real/mt5/connection.ts holds ONE persistent authenticated
manager socket and multiplexes every query over it:
Requests are serialized. The protocol correlates a response to a request by an echoed packet number on a single byte stream, so two in-flight requests would corrupt the framing for both. Concurrent tool calls are safe.
Drops auto-recover. A dead socket loses the session, so a transport failure re-dials, re-authenticates with exponential backoff, and retries the read once. A non-zero
RETCODEis an answer, not an outage, and never triggers a reconnect.Isolation is unchanged. The socket authenticates as the manager and can see every account on the server. It queries only the login the adapter hands it, and the auth gate remains the only thing that decides that login.
Security model (proven by the test suite)
Every tool call goes through AuthGate.resolve() which:
validates the token (exists, not revoked),
confirms via the CRM that the token's login is owned by that client,
confirms the account is KYC-approved and live,
then runs the tool with the login the gate resolved — never a login from the
caller. A client cannot pass a login and read another account.
test/isolation.test.ts proves: own-account read works, cross-account is
blocked, forged/revoked/garbage tokens are rejected, suspended accounts are
blocked.
Deploy (Railway)
⚠️ Identity is still MOCK
This deployment runs IDENTITY_PROVIDER=mock with TRADING_PROVIDER=real.
That means:
Token issuance uses mock fixtures, not real client credentials. Anyone who knows a fixture client id and password (
client_A/portal-pw-A, which are in this repo) can mint a token.That token then reads real money data from the live MT5 server.
This is acceptable only for the owner-testing phase, on accounts the owner
controls. It is NOT safe for real clients. Do not hand the URL to anyone outside
the team, and swap IDENTITY_PROVIDER=real (Brokeret) before onboarding a
single real client.
Mock identity also owns fixture logins (50001–50003) that do not exist on the
MT5 server, so every live read would come back empty. Set MOCK_OWNER_LOGIN to
a real MT5 login to repoint client_A at it for testing.
Railway environment variables
Variable | Value | Notes |
|
| Supabase pooler (transaction mode, port 6543), NOT |
|
| See the warning above |
|
| Live MT5 reads |
|
| Scheme is informational — only host:port is used |
| (manager login) | Secret |
| (manager password) | Secret |
| (read-only test account) | Used by |
| Railway injects this | The app reads it; don't hardcode |
|
| Handed to clients as their |
| (a real MT5 login) | Optional. Repoints |
Secrets live only in Railway environment variables. .env is gitignored and
has never been committed — verify with git log --all -- .env (empty).
Outbound network — the thing most likely to break
Railway must reach 91.243.178.145:443 over raw TCP. This is not an HTTPS
request, so anything that assumes HTTP (proxies, L7 egress filtering) will not
work.
If the MT5 side enforces an IP allowlist, Railway's egress IP must be whitelisted. Railway egress IPs are not stable on the free/hobby tiers — a static egress IP generally needs a paid plan or an outbound proxy. Confirm this with the MT5 admin before assuming it works.
An allowlist that drops packets (the common case) does not produce a
connection-refused error; it looks like a silent timeout. /health reports both
the same way, with an explicit hint.
Health check
GET /health:
{
"ok": true,
"identity": "mock",
"trading": "real",
"mt5": {
"configured": true,
"endpoint": "91.243.178.145:443",
"state": "connected",
"transport": "plain-tcp",
"lastConnectedAt": "2026-07-31T08:14:33.304Z"
}
}mt5.state is one of connected, disconnected (was up, socket since
dropped — normal when idle, the next call re-dials), never_connected, or
error. On failure, mt5.lastError carries the reason:
{
"configured": true,
"endpoint": "198.51.100.99:443",
"state": "error",
"lastError": "could not establish an authenticated MT5 session to 198.51.100.99:443 after 5 attempts: Error: socket idle timeout after 3000ms — the MT5 access server refused, dropped or ignored the TCP connection. Check outbound egress from this host, and if the access server enforces an IP allowlist, this host's egress IP must be whitelisted."
}Two deliberate choices:
okreflects this service, not the broker. A refused MT5 socket must not fail Railway's health check and trigger a restart loop — the server is healthy and serving; the upstream is not. Point Railway's health check at/healthand readmt5.stateseparately./healthnever dials. It reports the last observed state, so the check stays cheap and cannot hang on a dead broker. UseGET /health?probe=1to force a live dial attempt when diagnosing egress.
The MT5 socket is opened in the background at boot, so /health has a real
answer within a second or two of startup without waiting for the first tool
call. A broker that is unreachable at boot never stops the server from
starting — the failure is recorded and surfaced, not fatal.
Deploy checklist
Set every variable in the table above in Railway.
Run
db/migrations/001_init.sqlagainst Supabase (npm run migrate).Deploy. Confirm the boot log shows
mt5_boot_statewith"state":"connected".curl https://<app>.up.railway.app/health→mt5.stateshould beconnected(ordisconnectedif it has been idle — that is fine).If
stateiserror, readlastError. A timeout almost always means egress or an IP allowlist, not a bug.Mint a token via
POST /connect/initiateand callget_account_summary.
Build sequence (status)
Server skeleton + config + factory (swap point)
Two provider interfaces
Mock implementations of both
Token service (Postgres-backed; falls back to in-memory without
DATABASE_URL)Authorization gate + audit log + tool runner
Cross-account isolation test passing
All 6 read tools
MCP SDK streamable-HTTP transport
CRM "Connect AI Assistant" portal flow —
POST /connect/initiate|revoke,GET /connect/activityReal MT5 trading adapter (read side), verified live
Real Brokeret identity adapter ← the blocker for real clients
Write/execution tools against MT5 (phase 2, needs compliance sign-off)
Price history — needs a datafeed the Web API doesn't provide
Adding a tool
Add the method to
TradingDataProvider+ both mock and real impls.Add a tool function in
src/tools/index.tsusingrunTool(...)(gate + audit are automatic).Register it in
buildMcpServerinsrc/server.ts.Add an isolation assertion for it in
test/isolation.test.ts.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceA read-only MCP server that provides access to Charles Schwab account data and market information, including portfolio positions, real-time quotes, options chains, price history, and account balances through AI assistants.9MIT
- Alicense-qualityBmaintenanceA read-only MCP server for Hyperliquid that provides public market data (prices, order books, funding) and any wallet's positions, orders, and fills via MCP tools, without requiring a private key.MIT
- Flicense-qualityBmaintenanceA read-only MCP server that exposes controlled SSH tools to inventory, document, and prepare operations on WealthTech servers for AI assistants like ChatGPT and Codex.
- Flicense-qualityCmaintenanceRead-only MCP server that connects a Broker trading account to AI clients, providing account data, positions, orders, and market data via 21 tools, with a mock sandbox mode for evaluation.
Related MCP Connectors
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
Read-only Remote MCP for externally grounded AI agent trust receipts.
Read-only MCP server for Robinhood Chain token discovery, research, and due diligence via GMGN.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/milelecars/milele-prime-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server