Vale Monitor
Enables AI analysis using OpenAI models, providing market commentary, performance comparisons, and strategy reviews.
Click 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., "@Vale MonitorShow me my open positions and balance for each account"
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.
Vale Monitor
A self-hosted dashboard for watching Bybit trading accounts. It aggregates positions, balances and realised P&L across several accounts, reads candles, watches price alerts, stores strategy definitions, and exposes all of it to AI agents over MCP.
The dashboard is read-only against the exchange — it never places, modifies or cancels orders. Use read-only API keys.
This repository also contains
backend-setup/, a separate Python trading bot that does place real leveraged orders. It is an independent system with its own setup, config and credentials — nothing in the dashboard imports it. Its setup and every config key are documented below.
Local SQLite — no database to provision. First boot creates the file.
Multi-account — aggregates any number of Bybit accounts.
Candles and prices — work with no exchange keys at all.
Alerts — price thresholds, evaluated on a background poll.
Strategies — stored definitions with free-form JSON rules.
AI analysis — optional, provider-agnostic (Claude or OpenAI).
MCP server — lets Claude Code read candles and manage alerts/strategies.
Contents — Quick start · Using the dashboard · Configuration · Claude Code / MCP · AI layer · Trading backend · Scripts · Architecture · Security
Quick start
Requires Node.js 20+ (tested on 24).
git clone <your-fork-url> vale-monitor
cd vale-monitor
npm install
npm run devOpen http://127.0.0.1:5000. There is no configuration step and no login — the
SQLite database is created at ./data/vale.db on first boot.
Copy .env.example to .env when you want to connect an exchange account or
enable the AI layer. Nothing in it is required.
Verify a running instance end to end:
npm run smokeThere is no authentication. Anything that can reach the port can read your exchange balances and add or delete accounts.
HOSTdefaults to127.0.0.1so the server is reachable only from your own machine — see Security notes before changing that.
Related MCP server: Bybit MCP Server
Using the dashboard
The app is a single page with five tabs:
Tab | What it does |
Positions (default) | Open positions across every configured account, with live P&L, and a TradingView chart |
Dashboard | Weekly highlights, trading reports by timeframe, and a per-account balance card (equity, 7-day and week-to-date performance, per-symbol breakdown, 1–5% position sizing) |
Accounts | Add, test and remove exchange accounts |
Streaming | Live wallet balances pushed over the WebSocket |
Calculator | Compound growth projection across multiple accounts |
Positions, Dashboard and Streaming stay empty until you connect an account — they read credentialed exchange endpoints. Candles, prices and market hours work immediately.
Alerts and strategies are API- and MCP-first: they have full REST and MCP coverage but no dedicated tab yet. Drive them from Claude Code (below), or directly over HTTP — see docs/API.md.
Configuration
Every setting lives in .env; see .env.example for the
annotated list. Nothing is required — the app runs with no .env at all.
Variable | Default | Purpose |
|
| Only change |
|
| Where the SQLite file lives |
|
| How often active alerts are re-checked |
| — | Single-account fallback; prefer the Accounts tab |
Connecting exchange accounts
Candles, prices and market hours need no credentials. Positions, balances and realised P&L do.
Add accounts in the Accounts tab so you can track several at once. Credentials are stored in the local database and are never returned by the
API — account responses only report whether credentials are present. The
BYBIT_API_KEY environment pair is a single-account fallback, used only when no
accounts are configured.
Using it from Claude Code
The MCP server exposes 22 tools — candles, prices, positions, balances, trading reports, and full CRUD for alerts and strategies. No credential is needed.
1. Point Claude Code at it:
cp .mcp.json.example .mcp.json{
"mcpServers": {
"vale-monitor": {
"command": "npx",
"args": ["tsx", "server/mcp/index.ts"],
"env": { "VALE_API_URL": "http://127.0.0.1:5000" }
}
}
}2. Start the app (npm run dev) — the MCP server talks to it over HTTP, so
it must be running. Then ask Claude Code things like:
Read the last 200 hourly BTCUSDT candles and tell me where support is sitting.
Set an alert for ETHUSDT below 3000, and list what's already active.
Save a strategy for SOLUSDT on the 4h with these rules, then review it.
Available tools: server_status, get_candles, get_price, get_market_hours,
get_positions, get_account_balances, get_trading_report,
get_weekly_highlights, list_accounts, list_alerts, create_alert,
cancel_alert, delete_alert, list_strategies, get_strategy,
create_strategy, update_strategy, delete_strategy, ai_config,
analyze_market, analyze_performance, review_strategy.
The HTTP API is equally open — no headers required:
curl "http://127.0.0.1:5000/api/market/candles?symbol=BTCUSDT&interval=60&limit=5"The AI layer
Optional. Without a provider key, the AI endpoints return 503 and everything
else works normally.
Three analyses are available — market commentary over a candle window,
performance comparison across accounts, and strategy review — via
POST /api/ai/market, /api/ai/performance and
/api/ai/strategies/:id/review, and via the matching MCP tools.
Switching models
Two environment variables:
AI_PROVIDER=anthropic # anthropic | openai
AI_MODEL=claude-opus-5 # any id in the registry
AI_EFFORT=medium # low | medium | high | xhigh | max
ANTHROPIC_API_KEY=sk-ant-...Registered by default:
Model | Provider | Context | $/Mtok in | $/Mtok out |
| Anthropic | 1M | 5 | 25 |
| Anthropic | 1M | 3 | 15 |
| Anthropic | 200K | 1 | 5 |
| Anthropic | 1M | 5 | 25 |
| OpenAI | 400K | 1.25 / 0.25 | 10 / 2 |
GET /api/ai/config returns the registry with an available flag per model
based on which keys are set. Each response reports the model that answered, the
token counts and an estimated cost.
The OpenAI ids and pricing are best-effort and move quickly — check https://platform.openai.com/docs/models before relying on them.
Adding a model or provider
Nothing outside server/ai/ hardcodes a model id.
A new model on an existing provider — add an entry to MODELS in
server/ai/config.ts:
"claude-sonnet-4-6": {
id: "claude-sonnet-4-6",
provider: "anthropic",
label: "Claude Sonnet 4.6",
contextWindow: 1_000_000,
maxOutputTokens: 128_000,
pricing: { inputPerMTok: 3, outputPerMTok: 15 },
supportsEffort: true,
},Then set AI_MODEL=claude-sonnet-4-6.
A new provider — add its name to ProviderName, implement the Provider
interface (a single complete() method) under server/ai/providers/, and wire
it into the switch in createProvider. The switch is exhaustively typed, so
TypeScript will point at anything you miss.
Note the request interface deliberately has no temperature: current Claude
models reject temperature/top_p/top_k with a 400. Reasoning depth is
expressed as effort and each provider maps it onto its own knob.
Prompts live in server/ai/analyze.ts — one
system prompt plus one builder per analysis.
The trading backend (backend-setup/)
A separate Python system that runs a signal strategy across several Bybit accounts, manages take-profit ladders and trailing stops, and reports over Telegram.
WARNING: this one places real orders
Everything above is read-only.
backend-setup/opens and closes leveraged positions with real money and needs API keys with trade permission. A wrongposition_usdtorleveragemis-sizes trades on every enabled account at once. Run on testnet first, and enable live accounts one at a time.It has no automated tests. Nothing in the dashboard imports it, and the two share no configuration.
Setup
Requires Python 3.10+ (developed on 3.12).
cd backend-setup
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/bin/activate # macOS / Linux
pip install -r requirements.txt
cp .env.example .env
cp accounts_config.example.json accounts_config.json
cp trading_config.example.json trading_config.jsonAll three copies are gitignored. Fill in .env with testnet keys and leave
USE_TESTNET=true. Then check credentials before anything trades:
python account_balance_report.pyRun every script from inside backend-setup/. They open their config by
relative path, so launching from the repository root fails to find it.
Configuration
Three files, split deliberately: credentials only in .env, account identity and
sizing in accounts_config.json, strategy behaviour in trading_config.json.
accounts_config.json - who trades, and how big
{
"accounts": [
{
"name": "testnet",
"api_key_env": "BYBIT_TESTNET_API_KEY",
"api_secret_env": "BYBIT_TESTNET_API_SECRET",
"enabled": true,
"position_usdt": 5,
"leverage": 10
}
],
"trading_symbol": "BTCUSDT",
"parallel_execution": true
}Field | Meaning |
| Names of |
|
|
| Margin committed per trade, in USDT |
| Leverage applied to that margin |
| Submit to all accounts at once rather than in sequence |
How size is computed - qty = (position_usdt * leverage) / price. So
position_usdt is the margin and the notional is position_usdt x leverage:
10 at 40x is a 400 USDT position, not 10. Raising leverage multiplies
exposure on every enabled account simultaneously.
If accounts_config.json is absent, trade_manager.py falls back to
single-account mode using the BYBIT_API_KEY pair from .env.
trading_config.json - how positions are managed
Key | Meaning |
|
|
|
|
| Ladders of |
| ROI at which the trailing stop activates |
| How far price may retrace before it fires |
| Poll interval for the trailing logic |
| Minimum signal score to act on |
|
|
| Permit entries against the higher-timeframe trend |
| Require agreement from the top timeframe |
| Ignore new signals while a position is open (no stacking) |
| Symbols the strategy watches |
| Per-symbol |
size_pct values are portions of the position and need not total 100 - whatever
is left rides to the stop.
The backend's AI model
s1.py can ask an LLM to comment on a signal before acting. Optional: with no key
set, that step is skipped and the strategy still runs. The model is not
hardcoded.
Setting | Effect |
| Model id to use ( |
(neither set) | Falls back to |
| Routed via |
| Goes to OpenAI using |
AI_MODEL=gpt-5-mini # OpenAI - bare ids
OPENAI_API_KEY=sk-...
AI_MODEL=anthropic/claude-sonnet-5 # or OpenRouter - "vendor/model" ids
OPENROUTER_API_KEY=sk-or-...An unknown id fails at call time, not startup. This is separate from the
dashboard's AI layer above - each has its own AI_MODEL, so you can run
different models in each.
Running it
Script | Role |
| Multi-timeframe EMA-cross strategy; emits signals from Bybit WebSocket data |
| Opens and manages positions - the main trading loop |
| Fans one decision out to every enabled account, sizing each |
| Take-profit / stop-loss monitor and trailing stops |
| Martingale ladder state |
| Telegram bot - pushes signals, accepts commands |
| Supervises the other processes and restarts them |
| Balance / PnL / position-sizing report |
| Stochastic Momentum Index |
| Keeps local time aligned with the exchange |
cd backend-setup
python s1.py # strategy / signals
python tpsl.py # TP/SL monitor
python tele.py # Telegram bot
python trading_watchdog.py # supervisor
python account_balance_report.py # one-off reportRead the top of a script first - several assume others are already running.
Before enabling a live account
USE_TESTNET=truewith testnet keys until the behaviour is understood.auto_mode: falseso nothing acts unattended.One account
enabled: true, the restfalse.Smallest
position_usdtand lowestleveragethe exchange accepts.Confirm
position_usdt x leverageis the notional you actually intend.Watch a full open -> TP -> close cycle before adding a second account.
What it writes (all gitignored)
accounts_config.json, trading_config.json, .env, plus runtime state
(all_trade_signals.json, pending_signals.json, session_state.json,
tpsl.json, martingale_log.json, trading_decision_history.json,
stream_data.json, pnl_history.json), the logs, and backups/. Deleting the
state files resets it; the bot recreates what it needs - but not while running.
Deeper reference, including per-script detail:
backend-setup/README.md.
Scripts
Command | What it does |
| API + Vite dev server on one port |
| Client to |
| Run the production build |
| TypeScript, no emit — the project's only static gate |
| End-to-end HTTP check against a running server |
| Run the MCP server directly (normally launched by the client) |
| Push |
There is no test runner or linter configured; npm run check and npm run smoke
are the checks.
Architecture
One Express process serves both the API and the client. In development Vite runs
as middleware inside it, so there is a single port and no separate dev server; in
production the built assets are served statically. Vite owns the catch-all route
and is registered last, so new routes must be added inside registerRoutes().
server/
index.ts Bootstrap: schema init, middleware, listen
routes.ts All HTTP routes
storage.ts Every database query
db.ts SQLite connection and schema bootstrap
trading.ts Multi-account aggregation and analytics
bybit-api.ts Authenticated exchange reads
market.ts Public market data (candles, prices)
market-hours.ts Exchange open/closed calculation
alerts.ts Background alert evaluation
websocket.ts Session-authenticated /ws stream
vite.ts Dev middleware / static serving, logger
ai/ Model registry, providers, analysis prompts
mcp/ MCP server for agents
shared/schema.ts Drizzle tables, Zod schemas, shared types
client/src/ React + Vite front end
scripts/ smoke test CLI
docs/API.md HTTP and WebSocket reference
backend-setup/ Separate Python trading bot — places real orders, own READMEThree tables: accounts, alerts, strategies. There are no users.
Two conventions run through the analytics:
ROI is margin-based, not notional. A trade's committed capital is
cumEntryValue / leverage, so a 10x position reports return on the margin actually put up.Weeks run Monday 00:00:00 UTC to Sunday 23:59:59.999 UTC, independent of the server's timezone.
Ratios are null rather than Infinity when there are no losses to divide by.
No authentication
Every route is open, and the WebSocket at /ws accepts any connection. There are
no users, sessions, passwords or tokens in the codebase.
This is deliberate for a single-user tool bound to loopback. It also means the
only thing standing between the internet and your exchange credentials is the
HOST binding — see below.
Full endpoint and WebSocket reference: docs/API.md.
Security notes
There is no authentication. Any process or person who can reach the port can read your balances and positions, and add or delete exchange accounts.
HOSTdefaults to127.0.0.1, which is the control that makes the above acceptable — the server is reachable only from your own machine. The app logs a warning if you bind it anywhere else. Before exposing it, put a reverse proxy with TLS and access control in front; do not simply setHOST=0.0.0.0.Use read-only exchange API keys. Nothing here needs trade permissions, and a leaked read-only key cannot move funds.
Exchange credentials are stored unencrypted in the local SQLite file. Protect the file; it is as sensitive as the keys themselves.
.env,data/and.mcp.jsonare gitignored. Keep it that way.
License
MIT — see LICENSE.
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
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enables AI coding tools like Claude Code and Cursor to interact with Bybit's trading platform for market data retrieval, account management, and trading operations.111713MIT
- FlicenseBqualityDmaintenanceA comprehensive MCP server providing full access to Bybit's v5 API for real-time market data, trading operations, and account management. It enables AI assistants to execute trades, manage positions, and monitor wallet balances with built-in safety controls for both testnet and production environments.226
- AlicenseCqualityDmaintenanceMCP server for Bybit exchange enabling 246 tools for trading, market data, account management, and more via natural language.1002MIT
- Alicense-qualityBmaintenanceAn MCP server that enables AI agents to scan the market, manage positions, and retrieve trading metrics for Bybit through natural language commands.1AGPL 3.0
Related MCP Connectors
MCP server for Gainium — manage trading bots, deals, and balances via AI assistants
Open-source MCP server for Zerodha Kite Connect. Portfolio, market data, backtesting, alerts.
Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.
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/VW3st/crypto-monitor'
If you have feedback or need assistance with the MCP directory API, please join our Discord server