Search / io.github.emidlabs/backtest-mcp
EmidLabs Backtest
R0· no sign-inRun crypto trading strategy backtests through EmidLabs's Backtesting API.
v0.1.0 · active · repository · website · descriptor JSON · versions
Search / io.github.emidlabs/backtest-mcp
R0· no sign-inRun crypto trading strategy backtests through EmidLabs's Backtesting API.
v0.1.0 · active · repository · website · descriptor JSON · versions
{
"mcpServers": {
"backtest-mcp": {
"type": "http",
"url": "https://mcp.backtest.emidlabs.com/mcp"
}
}
}claude mcp add --transport http backtest-mcp https://mcp.backtest.emidlabs.com/mcp[mcp_servers.backtest-mcp]
url = "https://mcp.backtest.emidlabs.com/mcp"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"backtest-mcp": {
"type": "remote",
"url": "https://mcp.backtest.emidlabs.com/mcp",
"enabled": true
}
}
}{
"mcpServers": {
"backtest-mcp": {
"type": "http",
"url": "https://mcp.backtest.emidlabs.com/mcp"
}
},
"deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=backtest-mcp&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vbWNwLmJhY2t0ZXN0LmVtaWRsYWJzLmNvbS9tY3AifQ%3D%3D"
}{
"servers": {
"backtest-mcp": {
"type": "http",
"url": "https://mcp.backtest.emidlabs.com/mcp"
}
}
}{
"mcpServers": {
"backtest-mcp": {
"httpUrl": "https://mcp.backtest.emidlabs.com/mcp"
}
}
}extensions:
"backtest-mcp":
enabled: true
name: "backtest-mcp"
type: streamable_http
uri: "https://mcp.backtest.emidlabs.com/mcp"
timeout: 300
protocol.modernnewest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28protocol.statelessonly applies to 2026-07-28 serversprotocol.transportstreamable HTTPprotocol.list_ttlonly applies to 2026-07-28 serversauth.prm, auth.as_metadata, auth.cimdno remote uses OAuthauth.secret_in_urlno templated URLtools.descriptionsevery tool has a descriptiontools.description_length1 tools have descriptions over 1,024 characters, which crowds the contexttools.schemasevery tool has an object input schematools.annotations9 of 9 tools declare readOnlyHint or destructiveHinttools.directory_hintsevery tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHinttools.token_costabout 8,584 tokens to load every tooltools.api_dumptools are not a one-to-one API dumpstability.changesno tool changes in 30 daysstability.rug_pullno tool changed its meaning under the same namedeps.known_vulns, deps.mcp_sdk_version, deps.resolvableno npm or PyPI packageNo tool definition changes recorded. A server's first observation is its baseline; later probes record what changes.
Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.
+repository +namespace-matches-repo +website +reachable +uptime-100% ~updated-84d-ago
Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.
| remote | auth | reachable | uptime 30d | p50 | protocol | last ok |
|---|---|---|---|---|---|---|
https://mcp.backtest.emidlabs.com/mcp streamable-http | none | yes | 100% | 561 ms | 2025-11-25 | 2026-10-19 |
get_backtest_batch_resultsread-only | Fetches every asset's outcome from a submit_backtest_batch call, paginated. By default (waitForCompletion: true) polls internally until every item in the batch is done — a cheap check, not one that pages through everything — so one call returns the finished page. Each item has the same aggregate metrics and recency fields (recentTradeCount/recentAvgPnlR/recentOutcomes) get_backtest_result returns for a single backtest, plus assetPair/status/error, so the single-result and batch-result shapes never drift apart. totalCount/completedCount/failedCount/pendingCount come back on every page, not just the last, so you can tell the batch is done from a single pageSize=1 call. |
get_backtest_resultread-only | Fetches a submitted backtest by id. By default (waitForCompletion: true) polls internally until it finishes, so one call returns one final answer — no need to poll from the caller's side. Only aggregate metrics are returned here, no trade-by-trade detail — call get_backtest_trades for that (paginated, sortable). Fetching many results from the same submit_backtest_batch call? Use get_backtest_batch_results instead. |
get_backtest_tradesread-only | Fetches the closed-trade list for a completed backtest, paginated and sortable — the trade-by-trade detail get_backtest_result deliberately omits. Only closed trades ever appear; a position still open when the backtest's date range ends isn't represented here or anywhere else. Example: sortBy="exitTime", sortDirection="desc", pageSize=5 for the most recently closed trades. |
get_confirmation_sourceread-only | Fetches a submitted confirmation source by id. By default (waitForCompletion: true) polls internally until it finishes, so one call returns one final answer. No trade-outcome fields here at all (no PnlR/WinRate/...) — a confirmation source never opens a position. Once Completed, its id can be used as a confirmationSources sourceId in submit_backtest; its raw signal timeline is available separately via get_confirmation_source_signals. |
get_confirmation_source_signalsread-only | Fetches a completed confirmation source's raw signal timeline, paginated — the actual data a backtest's confirmationSources requirement is checked against. Can easily run into the thousands for a frequent condition over a long range (every candle-condition match is a row, not just closed trades), which is why this is paginated from the start. Debugging/inspection only — you do NOT need this tool to make confirmationSources work, and should not fetch these rows to reconstruct the gating yourself. To actually gate a backtest by this source, pass its id directly as sourceId in submit_backtest's own confirmationSources array; the backend applies the backward-only state check against this exact timeline automatically, including the higher-timeframe-to-lower-timeframe alignment. Reimplementing that alignment by hand from this raw data is unnecessary and easy to get wrong (e.g. failing to correctly persist a higher-timeframe state across every lower-timeframe candle until the next higher-timeframe close). Use this tool only to sanity-check a source's signal density or diagnose an unexpectedly low ConfirmedSignalsCount after the fact. |
list_available_assetsread-only | Lists every asset pair with real historical data, each with its supported timeframes and the date range actually available. Optional to call — submit_backtest already returns a clear error (with the real available range) when an asset or date range doesn't have data, so this is for up-front exploration or for recovering from an "unknown asset" error, not a required step before every submit_backtest. |
submit_backtest | Submits a strategy for backtesting against historical OHLCV data. Returns immediately with an id and status — call get_backtest_result to fetch the outcome once it finishes. Testing the same strategy against many assets? Use submit_backtest_batch instead — one call per asset here adds up fast. Optionally accepts confirmationSources to only count a candidate Entry/Exit as a real trade once corroborated by a submit_confirmation_source result (multi-timeframe or cross-asset confirmation) — see the confirmationSources argument and submit_confirmation_source's own description. |
submit_backtest_batch | Submits ONE strategy against MANY asset pairs in a single call — the same backtest you'd get from calling submit_backtest once per asset, without needing dozens of round trips. Returns immediately with a batchId (pass it to get_backtest_batch_results to fetch every asset's outcome, paginated) plus the per-asset id/status assigned right away. Best-effort: one bad asset pair (unknown, or its date range outside coverage) shows up with an error in that item only — every other asset in the batch is unaffected. Optionally accepts confirmationSources, applied identically to every asset in the batch — see submit_backtest's own confirmationSources argument for the full semantics. |
submit_confirmation_source | Runs a strategy against historical data purely to produce a signal timeline used to confirm OTHER backtests — not a backtest itself. Walks the same candles and evaluates the same DSL as submit_backtest, but never simulates a position: no trade, no PnL, no WinRate/drawdown, none of that applies here, because this strategy is never meant to be traded on its own. Returns immediately with an id and status — call get_confirmation_source to check completion, then pass that id as a confirmationSources sourceId in submit_backtest (e.g. only count an XRP entry once a BTC-neutral confirmation source agrees). Costs the same capacity as a regular backtest of the same size — the compute is identical, it just skips trade simulation. |
Schemas: list_tools.
{
"name": "io.github.emidlabs/backtest-mcp",
"title": "EmidLabs Backtest",
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"remotes": [
{
"url": "https://mcp.backtest.emidlabs.com/mcp",
"type": "streamable-http"
}
],
"version": "0.1.0",
"repository": {
"id": "1312820736",
"url": "https://github.com/emidlabs/emidlabs-backtest-mcp",
"source": "github"
},
"websiteUrl": "https://emidlabs.com",
"description": "Run crypto trading strategy backtests through EmidLabs's Backtesting API."
}