provetrade-mcp

provetrade-mcp

An MCP server for the ProveTrade trade-audit stack that lets models validate CSVs, run paid audit runs, and check service health/deploy status via typed tools.

Category
访问服务器

README

provetrade-mcp

An MCP server for the ProveTrade trade-audit stack: it gives a model typed access to the audit pipeline — check a CSV before spending anything on it, run an audit and get structured metrics back, and see whether the services are awake and which commit is live.

Six tools, two dependencies, stdio only, nothing written to disk.


Install

git clone https://github.com/vuzl-dev/provetrade-mcp
cd provetrade-mcp
npm ci --ignore-scripts
npm run build
npm run selftest      # verifies configuration and probes both services

--ignore-scripts is not decoration: a lifecycle script from any transitive package would run with your permissions, and nothing here needs one.

Connect it

Ready to paste. Replace the path with wherever you cloned it.

{
  "mcpServers": {
    "provetrade": {
      "command": "node",
      "args": ["/absolute/path/to/provetrade-mcp/dist/src/index.js"],
      "env": {
        "PROVETRADE_ALLOWED_ROOT": "/absolute/path/to/your/csv/folder",
        "PROVETRADE_AUDIT_MAX_RUNS": "5"
      }
    }
  }
}

Where that block goes:

Client File
Claude Code, one project .mcp.json in the project root
Claude Code, everywhere ~/.claude.json — or just run claude mcp add provetrade -- node /absolute/path/to/provetrade-mcp/dist/src/index.js
Claude Desktop, macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Desktop, Windows %APPDATA%\Claude\claude_desktop_config.json

Set PROVETRADE_ALLOWED_ROOT to the folder holding the CSVs you want audited. Every path a tool accepts is confined to it, and the default — the process working directory — is rarely what you want.

The tools

Tool What it does Read-only Costs money
provetrade_validate_csv Grades a trade CSV locally: which exchange adapter the engine would pick, row and closed-trade counts, and every issue that would break or silently degrade the audit. No network. yes no
provetrade_health Probes both services' /health, distinguishing sleeping (spun-down free tier, recoverable) from down. yes no
provetrade_deploy_status Compares the gateway's live build sha against local git HEAD, and how many commits behind the deploy is. yes no
provetrade_warm_engine Wakes the Go analyzer and waits for it with a time budget. Honestly reports still_sleeping when it does not come up. no — starts a service no (burns free hosting hours)
provetrade_metrics The gateway's request counters and latency percentiles from /metrics-lite. yes no
provetrade_audit_csv The flagship. Uploads a CSV, reads the SSE stream, returns a typed analytical object: winrate, net P&L, expectancy, payoff ratio, Sharpe, Sortino, max drawdown, maker share, behavioural flags with the trade ids behind them, and breakdowns by symbol/hour/weekday/holding time. no YES — one LLM call per run

Run provetrade_validate_csv before provetrade_audit_csv, always. The first is free and local; the second is not.

Failures carry a stable code — ENGINE_SLEEPING, GATEWAY_SLEEPING, UPSTREAM_ERROR, TIMEOUT, BAD_INPUT, PATH_DENIED, FILE_TOO_LARGE, NOT_CSV, TOKEN_MISSING, RATE_LIMITED, BUDGET_EXCEEDED, GIT_ERROR — so a model can branch on the code instead of pattern-matching prose.

Environment

Every value is read from the environment only. No tool accepts a URL, a host or a token as a parameter — see SECURITY.md for why that matters.

Variable Default What happens if you leave it unset
PROVETRADE_ALLOWED_ROOT the working directory Paths resolve against the working directory. Files elsewhere are refused with PATH_DENIED.
METRICS_TOKEN (empty) provetrade_metrics returns TOKEN_MISSING. Everything else works normally.
PROVETRADE_AUDIT_MAX_RUNS 5 At most 5 audits per server process; the 6th is refused with BUDGET_EXCEEDED before any request is sent.
PROVETRADE_GATEWAY_URL the production gateway Uses production. Must be https and on the host allowlist, or the process exits 2 at startup.
PROVETRADE_ANALYZER_URL the production analyzer Same.
PROVETRADE_HEALTH_TIMEOUT_MS 12000 12 s per /health probe.
PROVETRADE_AUDIT_IDLE_TIMEOUT_MS 150000 The audit stream is abandoned after 150 s of silence — not of total duration.
PROVETRADE_AUDIT_MAX_DURATION_MS 540000 Hard ceiling on one audit, kept under the gateway's own 600 s stream limit.
PROVETRADE_MAX_BODY_BYTES 8388608 Cap on a streamed audit body. Exceeding it is an error, never a truncated parse.
PROVETRADE_LIVE_TESTS (off) The one live test in the suite is skipped.

INTERNAL_TOKEN — the gateway↔analyzer shared secret — is not used by this server at all, because it never calls the analyzer's /analyze. If it is set in your environment, the server says so on stderr and suggests unsetting it for this process.

Why MCP, and not a wrapper around a CLI

This is the whole argument, so it gets a worked example rather than an assertion.

As a shell wrapper, the model gets a command line and a blob of text:

$ provetrade audit --file trades.csv --balance 5000 --tz 0
Reading trades.csv... ok
Winrate: 50.0%
Net P&L: -1053.16 USDT
Max drawdown: 1301.50 USDT (n/a%)
Sharpe: -0.62   Sortino: n/a
...

To use any of that, the model has to guess the flag names (--tz? --utc? --offset?), then parse prose. And the parsing is where it goes wrong quietly: n/a% becomes 0, so "drawdown percentage could not be computed without a starting balance" turns into "drawdown was 0%" — a confident, wrong number that reads exactly like a real one. Nothing in the text says which fields are computable, which are missing, or what the units are. Change one label upstream and every consumer breaks silently.

As an MCP tool, both directions are typed. The input schema publishes the parameter names, their types, their ranges and their defaults, so there is nothing to guess — an unknown model id or an out-of-range UTC offset is refused at the boundary with a message naming the field, before any request is sent. The output schema declares that sortino_ratio is number | null, and the server returns exactly that:

{
  "metrics": {
    "winrate_percent": 50,
    "net_pnl_usdt": -1053.16,
    "max_drawdown_usdt": 1301.5,
    "max_drawdown_percent": null,
    "sharpe_ratio": -0.62,
    "sortino_ratio": null
  },
  "narrative_status": "not_requested",
  "runs_remaining": 4
}

null means "the engine could not compute this", and it is impossible to mistake for zero. There is no text to parse, no unit to infer, and no field whose absence is indistinguishable from a value.

The schema is also what lets the server say things the wrapper cannot express: readOnlyHint: false on the audit tool marks it as consequential, the description says in words that it costs money, and the run budget makes that enforceable. A CLI wrapper hands the model a shell and hopes.

See examples/smoke-output.txt for a real recorded run of all six tools, structured output included.

Examples

examples/ holds two generated CSVs that differ in exactly one respect: the second appends USDT to the Amount, Fee and Realized Profit columns.

That pair demonstrates the reason provetrade_validate_csv exists. The first file audits cleanly. The second returns "no valid trades parsed from CSV" — because Realized Profit is parsed as a bare number, so every row is skipped, while Fee handles the same suffix correctly and Amount silently substitutes Price × Quantity. The failure reads like a wrong export or a bad date range and is neither. validate_csv names the actual column.

Both files are synthetic, generated from a fixed seed by scripts/make-fixtures.mjs. No third party's trades are in this repository.

Security

Read SECURITY.md. The short version: two hosts on a source-level allowlist, no shell, no port, no disk writes, one optional secret that never appears in output, and every path confined to an allowed root with Windows-correct comparison.

Before you audit someone else's export: the ProveTrade gateway forwards a skeleton of each upload — the header plus a masked shape of the first row, no trade values — to a private Telegram chat, to collect each exchange's file format. Running a client's file through production therefore transmits the structure of their data to a third party. Decide that before the upload.

Limitations, honestly

  • Free-tier hosting. Both services spin down after ~15 minutes idle. A first request after that waits for a cold start; the gateway absorbs up to 120 s of the analyzer's boot inside the request.
  • Server-side probes do not reliably wake the analyzer. Measured on production: 72 s of /health probing at 4-second intervals produced no entry in the analyzer's own log, while a browser request started it and it was up in ~38 s. provetrade_warm_engine therefore reports still_sleeping honestly rather than pretending. The reliable fallback is opening https://provetrade.com/app in a browser — the page pings the analyzer from the client side for exactly this reason.
  • A cold start can present as a timeout, not just as a 429. Seen while recording the smoke run: the analyzer's /health hung past an 8-second deadline and answered 4 seconds after a warm-up probe. health now reports that state as ambiguous and points at warm_engine instead of at the deploy, and the default deadline is 12 s.
  • provetrade_metrics has never been exercised against the live endpoint. The token lives in the hosting dashboard and was not available while this was built. It is fully implemented and tested against a fake client — success, missing token, the 404-means-rejected-token case, a sleeping gateway, and the no-leak assertion — but the live path is unverified.
  • estimated_closed_trades is an estimate, and only for Binance fills exports; it is null for every other format. The real count comes from position reconstruction, which lives in the Go engine, and reimplementing that here would create a second source of truth for trading math.
  • 94 packages in the production tree, all pulled in by the official SDK for transports this server does not use. Two direct dependencies; see SECURITY.md.
  • No HTTP transport. Not an oversight — see below.

If HTTP is ever needed

stdio was chosen because it opens no port, has no network surface, and ties the process lifetime to the client. If a remote transport becomes necessary, all four of these are required, not optional:

  1. Bind to 127.0.0.1 only — never 0.0.0.0.
  2. Validate the Origin header against an allowlist. Without it a web page can drive a local server via DNS rebinding.
  3. Require a bearer token, compared in constant time.
  4. Keep the existing body caps, per-request timeouts and concurrency limits; they matter more once the endpoint is reachable by something other than a parent process.

Development

npm test          # build, then node:test over the compiled output
npm run fixtures  # regenerate examples/ (deterministic — a diff means a real change)
npm run smoke     # drive all six tools over stdio; writes examples/smoke-output.txt
npm run selftest  # config check + health probe, non-zero exit on a real problem

npm run smoke makes one real audit and therefore one LLM call. Set PROVETRADE_SMOKE_SKIP_AUDIT=1 to rerun it for free.

Repository documents: CONTRACT.md records the ProveTrade wire contract this server depends on, read out of the sources rather than from documentation. DECISIONS.md records the forks taken and why. SECURITY.md is the security review. PROGRESS.md is the build log.

License

MIT. Author: Vuzl (@vuzl.dev).

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选