tradeblocks-mcp 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -216,7 +216,7 @@ backtests/
216
216
  ### Core Tools
217
217
  | Tool | Description |
218
218
  |------|-------------|
219
- | `list_backtests` | List all available blocks with summary stats |
219
+ | `list_blocks` | List all available blocks with summary stats |
220
220
  | `get_block_info` | Detailed info for a specific block |
221
221
  | `get_statistics` | Performance metrics (Sharpe, Sortino, drawdown, etc.) |
222
222
  | `get_strategy_comparison` | Compare strategies within a block |
@@ -19,7 +19,7 @@ Surface key performance metrics and stress test results to help understand a str
19
19
  List available blocks and help the user choose what to analyze.
20
20
 
21
21
  ```
22
- Use list_backtests to show available options.
22
+ Use list_blocks to show available options.
23
23
  ```
24
24
 
25
25
  Ask clarifying questions:
@@ -39,7 +39,7 @@ Ask what the user wants to explore:
39
39
 
40
40
  Ask: "What aspect of your strategy would you like to explore?"
41
41
 
42
- Use `list_backtests` to identify the target block.
42
+ Use `list_blocks` to identify the target block.
43
43
 
44
44
  ### Step 2: Explore Available Fields
45
45
 
@@ -29,7 +29,7 @@ Ask:
29
29
  - "Which strategies would you like to analyze together?"
30
30
  - "What aspect of portfolio composition interests you?"
31
31
 
32
- Use `list_backtests` to show available blocks.
32
+ Use `list_blocks` to show available blocks.
33
33
 
34
34
  ### Step 2: Correlation Analysis
35
35
 
@@ -27,7 +27,7 @@ Risk analysis serves different purposes. Ask what the user wants to understand:
27
27
 
28
28
  Ask: "What aspect of risk would you like to explore?"
29
29
 
30
- Then use `list_backtests` to identify the target block.
30
+ Then use `list_blocks` to identify the target block.
31
31
 
32
32
  ### Step 2: Run Appropriate Analysis
33
33
 
@@ -33,7 +33,7 @@ If OOS performance is close to IS performance, the parameters may be capturing r
33
33
 
34
34
  ### Step 1: Select Strategy
35
35
 
36
- Use `list_backtests` to show available blocks.
36
+ Use `list_blocks` to show available blocks.
37
37
 
38
38
  Ask:
39
39
  - "Which backtest contains the strategy you want to analyze?"
package/manifest.json CHANGED
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "tools": [
33
33
  {
34
- "name": "list_backtests",
34
+ "name": "list_blocks",
35
35
  "description": "List all available trading backtests/blocks in the configured directory"
36
36
  },
37
37
  {
@@ -91,7 +91,7 @@
91
91
  {
92
92
  "name": "getting_started",
93
93
  "description": "How to set up and use TradeBlocks for trading analysis",
94
- "text": "# Getting Started with TradeBlocks\n\n## Setup\nYour trading data should be in your configured Trading Data Directory. Each strategy/backtest is a **block** - a folder containing:\n- `tradelog.csv` (required): Your trade records with columns like Date Opened, Date Closed, P/L, etc.\n- `dailylog.csv` (optional): Daily portfolio values for more accurate drawdown calculations\n\n## Adding New Backtests\nTo add a new backtest for analysis:\n1. Create a new folder in your Trading Data Directory (e.g., `my-strategy-2024`)\n2. Export your trade log CSV from Option Omega (or other backtesting platform)\n3. Save it as `tradelog.csv` in the new folder\n4. The block will appear when you run `list_backtests`\n\n**Folder structure example:**\n```\nTrading Data Directory/\n my-strategy-2024/\n tradelog.csv\n dailylog.csv (optional)\n another-strategy/\n tradelog.csv\n```\n\n## Quick Start\n1. **List your blocks**: Use `list_backtests` to see available strategies\n2. **Get statistics**: Use `get_statistics` with a block ID to see performance metrics\n3. **Run analysis**: Use `run_walk_forward` or `run_monte_carlo` for deeper analysis"
94
+ "text": "# Getting Started with TradeBlocks\n\n## Setup\nYour trading data should be in your configured Trading Data Directory. Each strategy/backtest is a **block** - a folder containing:\n- `tradelog.csv` (required): Your trade records with columns like Date Opened, Date Closed, P/L, etc.\n- `dailylog.csv` (optional): Daily portfolio values for more accurate drawdown calculations\n\n## Adding New Backtests\nTo add a new backtest for analysis:\n1. Create a new folder in your Trading Data Directory (e.g., `my-strategy-2024`)\n2. Export your trade log CSV from Option Omega (or other backtesting platform)\n3. Save it as `tradelog.csv` in the new folder\n4. The block will appear when you run `list_blocks`\n\n**Folder structure example:**\n```\nTrading Data Directory/\n my-strategy-2024/\n tradelog.csv\n dailylog.csv (optional)\n another-strategy/\n tradelog.csv\n```\n\n## Quick Start\n1. **List your blocks**: Use `list_blocks` to see available strategies\n2. **Get statistics**: Use `get_statistics` with a block ID to see performance metrics\n3. **Run analysis**: Use `run_walk_forward` or `run_monte_carlo` for deeper analysis"
95
95
  },
96
96
  {
97
97
  "name": "analyze_strategy",
@@ -104,7 +104,7 @@
104
104
  {
105
105
  "name": "optionomega_guide",
106
106
  "description": "Guide for setting up Option Omega backtests that export clean data for TradeBlocks",
107
- "text": "# Option Omega Backtest Setup for TradeBlocks\n\n## Supported Assets\nSPY, SPX (afternoon expirations only), QQQ, IWM, AAPL, TSLA\n- Historical data from January 1, 2013 through previous trading day\n- Data updates overnight (3-5am ET), available before market open\n\n## Strategy Configuration\n\n### Strike Selection Methods\n- **Delta**: Select strikes by delta value (default)\n- **Percentage OTM**: Target specific out-of-the-money distances\n- **Fixed Premium**: Choose strikes nearest a specified price\n- **Strike Offset**: Position relative to parent legs (for linked legs)\n\n### Option Legs\n- Up to 8 legs per backtest\n- Linked legs for dependent strike selections\n- Round strikes to nearest multiples for liquidity\n\n## Entry Configuration\n\n### Timing\n- Entry window: 9:32am - 3:59pm ET (1-minute intervals)\n- Frequency: Daily, Weekly (specific days), Monthly (specific dates), or Specific Dates\n\n### Entry Filters (Optional)\n- VIX levels (min/max), VIX movement\n- Technical indicators: RSI (14-day), SMA, EMA\n- Opening Range Breakout (ORB)\n- Gap conditions, intraday movement\n- SqueezeMetrics: DIX, GEX, GXV\n\n## Exit Conditions\n\n### Profit/Loss Targets\n- Percentage-based\n- Fixed dollar amount\n- Closing order price\n\n### Stop Loss Options\n- Fixed stop loss\n- Trailing stop (recalculated or fixed)\n- 0-DTE intra-minute stops (SPX/SPY only)\n- Per-leg stop loss\n\n### Time-Based Exits\n- By DTE remaining\n- Days in trade\n- Minutes in trade\n\n### Other Exits\n- Technical indicator triggers\n- Delta-based (position or leg level)\n- Short tested / underlying movement\n\n## Risk Controls (The Punisher)\n- Commission/fee modeling (per contract)\n- Slippage adjustments (entry, exit, stop loss)\n- Bid-ask spread filter (default: 10,000 bps max)\n- Consecutive hits requirement (2 intervals at target/stop)\n- Min/max entry premium filters\n- Blackout days\n- Re-entry delays after exits\n\n## Data Quality Notes\n- Uses mid-price from OPRA bid/ask data\n- 1-minute resolution (open price for signals)\n- RTH only (9:30-4:00 market time)\n- SPX uses standard EOD contracts only (no AM expirations)\n- Calendar days for DTE calculations\n- March 2020 / Spring 2025 show unusual volatility\n\n## Exporting for TradeBlocks\n\n1. Run your backtest in Option Omega\n2. Go to Results -> Trade Log\n3. Click Export/Download CSV\n4. Create a new folder in your Trading Data Directory (e.g., `my-strategy-2024`)\n5. Save the CSV as `tradelog.csv` in that folder\n6. Run `list_backtests` to see your new block\n\nTradeBlocks expects these columns (Option Omega exports them automatically):\n- Date Opened, Time Opened\n- Date Closed, Time Closed\n- P/L, Strategy, Legs\n- No. of Contracts, Premium\n- Opening/Closing Prices\n- Reason For Close\n\n**Note**: The visual context from Option Omega's trade log (replay, charts) is lost in CSV export. TradeBlocks provides its own analysis tools to compensate."
107
+ "text": "# Option Omega Backtest Setup for TradeBlocks\n\n## Supported Assets\nSPY, SPX (afternoon expirations only), QQQ, IWM, AAPL, TSLA\n- Historical data from January 1, 2013 through previous trading day\n- Data updates overnight (3-5am ET), available before market open\n\n## Strategy Configuration\n\n### Strike Selection Methods\n- **Delta**: Select strikes by delta value (default)\n- **Percentage OTM**: Target specific out-of-the-money distances\n- **Fixed Premium**: Choose strikes nearest a specified price\n- **Strike Offset**: Position relative to parent legs (for linked legs)\n\n### Option Legs\n- Up to 8 legs per backtest\n- Linked legs for dependent strike selections\n- Round strikes to nearest multiples for liquidity\n\n## Entry Configuration\n\n### Timing\n- Entry window: 9:32am - 3:59pm ET (1-minute intervals)\n- Frequency: Daily, Weekly (specific days), Monthly (specific dates), or Specific Dates\n\n### Entry Filters (Optional)\n- VIX levels (min/max), VIX movement\n- Technical indicators: RSI (14-day), SMA, EMA\n- Opening Range Breakout (ORB)\n- Gap conditions, intraday movement\n- SqueezeMetrics: DIX, GEX, GXV\n\n## Exit Conditions\n\n### Profit/Loss Targets\n- Percentage-based\n- Fixed dollar amount\n- Closing order price\n\n### Stop Loss Options\n- Fixed stop loss\n- Trailing stop (recalculated or fixed)\n- 0-DTE intra-minute stops (SPX/SPY only)\n- Per-leg stop loss\n\n### Time-Based Exits\n- By DTE remaining\n- Days in trade\n- Minutes in trade\n\n### Other Exits\n- Technical indicator triggers\n- Delta-based (position or leg level)\n- Short tested / underlying movement\n\n## Risk Controls (The Punisher)\n- Commission/fee modeling (per contract)\n- Slippage adjustments (entry, exit, stop loss)\n- Bid-ask spread filter (default: 10,000 bps max)\n- Consecutive hits requirement (2 intervals at target/stop)\n- Min/max entry premium filters\n- Blackout days\n- Re-entry delays after exits\n\n## Data Quality Notes\n- Uses mid-price from OPRA bid/ask data\n- 1-minute resolution (open price for signals)\n- RTH only (9:30-4:00 market time)\n- SPX uses standard EOD contracts only (no AM expirations)\n- Calendar days for DTE calculations\n- March 2020 / Spring 2025 show unusual volatility\n\n## Exporting for TradeBlocks\n\n1. Run your backtest in Option Omega\n2. Go to Results -> Trade Log\n3. Click Export/Download CSV\n4. Create a new folder in your Trading Data Directory (e.g., `my-strategy-2024`)\n5. Save the CSV as `tradelog.csv` in that folder\n6. Run `list_blocks` to see your new block\n\nTradeBlocks expects these columns (Option Omega exports them automatically):\n- Date Opened, Time Opened\n- Date Closed, Time Closed\n- P/L, Strategy, Legs\n- No. of Contracts, Premium\n- Opening/Closing Prices\n- Reason For Close\n\n**Note**: The visual context from Option Omega's trade log (replay, charts) is lost in CSV export. TradeBlocks provides its own analysis tools to compensate."
108
108
  }
109
109
  ],
110
110
  "keywords": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tradeblocks-mcp",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "MCP server for options trade analysis - works with Claude Desktop/Cowork",
5
5
  "author": "David Romeo <davidmromeo@gmail.com>",
6
6
  "type": "module",
@@ -1,27 +1,68 @@
1
1
  import { createServer } from "node:http";
2
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
- import { createMcpExpressApp } from "@modelcontextprotocol/sdk/server/express.js";
4
- async function startHttpServer(server, options) {
3
+ import express from "express";
4
+ async function startHttpServer(serverFactory, options) {
5
5
  const { port, host = "0.0.0.0" } = options;
6
- const app = createMcpExpressApp({ host });
7
- const transport = new StreamableHTTPServerTransport({
8
- sessionIdGenerator: void 0
9
- // Stateless mode
6
+ const app = express();
7
+ app.use(express.json());
8
+ app.get("/", (_req, res) => {
9
+ res.status(200).json({
10
+ name: "tradeblocks-mcp",
11
+ status: "ok",
12
+ mcp_endpoint: "/mcp"
13
+ });
14
+ });
15
+ app.post("/", handleMcpRequest(serverFactory));
16
+ app.post("/mcp", handleMcpRequest(serverFactory));
17
+ app.get("/mcp", (_req, res) => {
18
+ res.status(405).json({
19
+ jsonrpc: "2.0",
20
+ error: { code: -32601, message: "Method not allowed. Use POST for MCP requests." },
21
+ id: null
22
+ });
10
23
  });
11
- app.all("/mcp", async (req, res) => {
12
- await transport.handleRequest(req, res);
24
+ app.delete("/mcp", (_req, res) => {
25
+ res.status(202).send();
13
26
  });
14
- await server.connect(transport);
15
27
  const httpServer = createServer(app);
16
28
  return new Promise((resolve, reject) => {
17
29
  httpServer.on("error", reject);
18
30
  httpServer.listen(port, host, () => {
19
31
  console.error(`TradeBlocks MCP HTTP server listening on http://${host}:${port}/mcp`);
32
+ console.error(`Health check available at http://${host}:${port}/`);
20
33
  console.error(`For web platforms, expose via: ngrok http ${port}`);
21
34
  resolve(httpServer);
22
35
  });
23
36
  });
24
37
  }
38
+ function handleMcpRequest(serverFactory) {
39
+ return async (req, res) => {
40
+ try {
41
+ const server = serverFactory();
42
+ const transport = new StreamableHTTPServerTransport({
43
+ sessionIdGenerator: void 0
44
+ // Stateless mode - no session tracking
45
+ });
46
+ res.on("close", () => {
47
+ transport.close().catch(() => {
48
+ });
49
+ server.close().catch(() => {
50
+ });
51
+ });
52
+ await server.connect(transport);
53
+ await transport.handleRequest(req, res, req.body);
54
+ } catch (error) {
55
+ console.error("MCP request error:", error);
56
+ if (!res.headersSent) {
57
+ res.status(500).json({
58
+ jsonrpc: "2.0",
59
+ error: { code: -32603, message: "Internal server error" },
60
+ id: null
61
+ });
62
+ }
63
+ }
64
+ };
65
+ }
25
66
  export {
26
67
  startHttpServer
27
68
  };
package/server/index.js CHANGED
@@ -43321,9 +43321,9 @@ function calculatePeakExposure(trades, initialCapital) {
43321
43321
  function registerBlockTools(server, baseDir) {
43322
43322
  const calculator = new PortfolioStatsCalculator();
43323
43323
  server.registerTool(
43324
- "list_backtests",
43324
+ "list_blocks",
43325
43325
  {
43326
- description: "List all available backtest blocks with summary stats (trade count, date range, P&L)",
43326
+ description: "START HERE: List all available portfolio blocks. Returns blockId values needed for all other tools (get_statistics, get_block_info, get_performance_charts, etc.). Each block contains trade history and optional daily logs.",
43327
43327
  inputSchema: external_exports.object({
43328
43328
  sortBy: external_exports.enum(["name", "tradeCount", "netPl", "dateRange"]).default("name").describe("Sort results by field (default: name)"),
43329
43329
  sortOrder: external_exports.enum(["asc", "desc"]).default("asc").describe("Sort direction (default: asc)"),
@@ -43412,9 +43412,9 @@ function registerBlockTools(server, baseDir) {
43412
43412
  server.registerTool(
43413
43413
  "get_block_info",
43414
43414
  {
43415
- description: "Get detailed info for a specific block (trade count, date range, strategies, daily log status)",
43415
+ description: "Get detailed metadata for a block including available strategies, date range, and daily log status. Use blockId from list_blocks.",
43416
43416
  inputSchema: external_exports.object({
43417
- blockId: external_exports.string().describe("Block folder name")
43417
+ blockId: external_exports.string().describe("Block ID from list_blocks (e.g., 'main-port')")
43418
43418
  })
43419
43419
  },
43420
43420
  async ({ blockId }) => {
@@ -43458,9 +43458,9 @@ function registerBlockTools(server, baseDir) {
43458
43458
  server.registerTool(
43459
43459
  "get_statistics",
43460
43460
  {
43461
- description: "Get full portfolio statistics with optional strategy, ticker, and date filters",
43461
+ description: "Get comprehensive portfolio statistics: win rate, Sharpe ratio, max drawdown, P&L metrics, and more. Use blockId from list_blocks. Optionally filter by strategy, ticker, or date range.",
43462
43462
  inputSchema: external_exports.object({
43463
- blockId: external_exports.string().describe("Block folder name"),
43463
+ blockId: external_exports.string().describe("Block ID from list_blocks (e.g., 'main-port')"),
43464
43464
  strategy: external_exports.string().optional().describe("Filter by strategy name (case-insensitive)"),
43465
43465
  tickerFilter: external_exports.string().optional().describe("Filter trades by underlying ticker symbol (e.g., 'SPY', 'AAPL')"),
43466
43466
  startDate: external_exports.string().optional().describe("Start date filter (YYYY-MM-DD)"),
@@ -43674,9 +43674,9 @@ function registerBlockTools(server, baseDir) {
43674
43674
  server.registerTool(
43675
43675
  "compare_blocks",
43676
43676
  {
43677
- description: "Compare statistics across multiple blocks (max 5)",
43677
+ description: "Compare performance statistics across multiple portfolios side-by-side. Use blockIds from list_blocks.",
43678
43678
  inputSchema: external_exports.object({
43679
- blockIds: external_exports.array(external_exports.string()).min(1).max(5).describe("Array of block folder names to compare (max 5)"),
43679
+ blockIds: external_exports.array(external_exports.string()).min(1).max(5).describe("Array of block IDs from list_blocks (max 5)"),
43680
43680
  metrics: external_exports.array(
43681
43681
  external_exports.enum([
43682
43682
  "totalTrades",
@@ -45503,7 +45503,14 @@ function registerAnalysisTools(server, baseDir) {
45503
45503
  maxTailDependenceThreshold: external_exports.number().min(0).max(1).default(0.5).describe("Maximum allowed tail dependence between any strategy pair (default: 0.5). Only used if enableTailRiskConstraint is true."),
45504
45504
  tailThreshold: external_exports.number().min(0.01).max(0.5).default(0.1).describe("Percentile threshold for tail definition (default: 0.1 = worst 10%). Only used if enableTailRiskConstraint is true."),
45505
45505
  diversificationNormalization: external_exports.enum(["raw", "margin", "notional"]).default("raw").describe("How to normalize returns for diversification calculations (default: raw)."),
45506
- diversificationDateBasis: external_exports.enum(["opened", "closed"]).default("opened").describe("Which trade date to use for diversification calculations (default: opened).")
45506
+ diversificationDateBasis: external_exports.enum(["opened", "closed"]).default("opened").describe("Which trade date to use for diversification calculations (default: opened)."),
45507
+ // Parameter ranges for position sizing sweeps
45508
+ parameterRanges: external_exports.record(
45509
+ external_exports.string(),
45510
+ external_exports.tuple([external_exports.number(), external_exports.number(), external_exports.number()])
45511
+ ).optional().describe(
45512
+ `Parameter ranges for optimization sweep. Format: {paramName: [min, max, step]}. POSITION SIZING: 'kellyMultiplier' scales P&L by multiplier (e.g., {"kellyMultiplier": [0.25, 1.0, 0.25]} tests quarter/half/3-quarter/full Kelly); 'fixedFractionPct' scales relative to 2% baseline (e.g., [1, 4, 1] tests 1-4%); 'fixedContracts' scales relative to avg contracts (e.g., [1, 5, 1] tests 1-5 contracts). RISK CONSTRAINTS (reject combinations exceeding threshold): 'maxDrawdownPct' max drawdown % (e.g., [15, 25, 5] allows 15-25%); 'maxDailyLossPct' max single-day loss %; 'consecutiveLossLimit' max consecutive losing trades. STRATEGY WEIGHTS: 'strategy:StrategyName' weight multiplier per strategy (e.g., {"strategy:IronCondor": [0, 1, 0.5], "strategy:Straddle": [0, 1, 0.5]} tests include/exclude combinations). Multiple parameters create a grid search across all combinations.`
45513
+ )
45507
45514
  })
45508
45515
  },
45509
45516
  async ({
@@ -45532,7 +45539,8 @@ function registerAnalysisTools(server, baseDir) {
45532
45539
  maxTailDependenceThreshold,
45533
45540
  tailThreshold,
45534
45541
  diversificationNormalization,
45535
- diversificationDateBasis
45542
+ diversificationDateBasis,
45543
+ parameterRanges
45536
45544
  }) => {
45537
45545
  try {
45538
45546
  const block = await loadBlock(baseDir, blockId);
@@ -45622,7 +45630,7 @@ function registerAnalysisTools(server, baseDir) {
45622
45630
  outOfSampleDays,
45623
45631
  stepSizeDays,
45624
45632
  optimizationTarget,
45625
- parameterRanges: {},
45633
+ parameterRanges: parameterRanges ?? {},
45626
45634
  minInSampleTrades,
45627
45635
  minOutOfSampleTrades,
45628
45636
  normalizeTo1Lot,
@@ -45653,7 +45661,8 @@ function registerAnalysisTools(server, baseDir) {
45653
45661
  oosWindowCount,
45654
45662
  minInSampleTrades,
45655
45663
  minOutOfSampleTrades,
45656
- normalizeTo1Lot
45664
+ normalizeTo1Lot,
45665
+ parameterRanges: parameterRanges ?? null
45657
45666
  },
45658
45667
  performanceFloor: hasPerformanceFloor ? {
45659
45668
  minSharpeRatio: minSharpeRatio ?? null,
@@ -46982,9 +46991,9 @@ function registerPerformanceTools(server, baseDir) {
46982
46991
  server.registerTool(
46983
46992
  "get_performance_charts",
46984
46993
  {
46985
- description: "Get data for performance visualizations. Returns multiple chart datasets for equity analysis, return distributions, rolling metrics, and trade patterns.",
46994
+ description: "Get chart data for performance visualizations: equity curves, drawdowns, return distributions, rolling metrics, and trade patterns. Use blockId from list_blocks.",
46986
46995
  inputSchema: external_exports.object({
46987
- blockId: external_exports.string().describe("Block folder name"),
46996
+ blockId: external_exports.string().describe("Block ID from list_blocks (e.g., 'main-port')"),
46988
46997
  strategy: external_exports.string().optional().describe("Filter by strategy name (case-insensitive)"),
46989
46998
  charts: external_exports.array(
46990
46999
  external_exports.enum([
@@ -48872,7 +48881,7 @@ SPY, SPX (afternoon expirations only), QQQ, IWM, AAPL, TSLA
48872
48881
  3. Click Export/Download CSV
48873
48882
  4. Create a new folder in your Trading Data Directory (e.g., \`my-strategy-2024\`)
48874
48883
  5. Save the CSV as \`tradelog.csv\` in that folder
48875
- 6. Run \`list_backtests\` to see your new block
48884
+ 6. Run \`list_blocks\` to see your new block
48876
48885
 
48877
48886
  TradeBlocks expects these columns (Option Omega exports them automatically):
48878
48887
  - Date Opened, Time Opened
@@ -49073,7 +49082,7 @@ async function handleDirectCall(args) {
49073
49082
  console.log(JSON.stringify({
49074
49083
  availableTools: tools,
49075
49084
  usage: "tradeblocks-mcp --call <tool-name> '<json-args>'",
49076
- example: "TRADEBLOCKS_DATA_DIR=~/backtests tradeblocks-mcp --call list_backtests '{}'"
49085
+ example: "TRADEBLOCKS_DATA_DIR=~/backtests tradeblocks-mcp --call list_blocks '{}'"
49077
49086
  }, null, 2));
49078
49087
  process.exit(0);
49079
49088
  }
@@ -49181,7 +49190,7 @@ Skill Command Options:
49181
49190
  --force Reinstall even if skills exist (install only)
49182
49191
 
49183
49192
  Direct Tool Invocation:
49184
- TRADEBLOCKS_DATA_DIR=~/backtests tradeblocks-mcp --call list_backtests '{}'
49193
+ TRADEBLOCKS_DATA_DIR=~/backtests tradeblocks-mcp --call list_blocks '{}'
49185
49194
 
49186
49195
  Examples:
49187
49196
  tradeblocks-mcp ~/backtests
@@ -49334,20 +49343,24 @@ async function main() {
49334
49343
  console.error(`Error: Directory does not exist: ${resolvedDir}`);
49335
49344
  process.exit(1);
49336
49345
  }
49337
- const server = new McpServer(
49338
- { name: "tradeblocks-mcp", version: "0.4.0" },
49339
- { capabilities: { tools: {}, resources: {} } }
49340
- );
49341
- registerBlockTools(server, resolvedDir);
49342
- registerAnalysisTools(server, resolvedDir);
49343
- registerPerformanceTools(server, resolvedDir);
49344
- registerReportTools(server, resolvedDir);
49345
- registerImportTools(server, resolvedDir);
49346
- registerResources(server);
49346
+ const createServer = () => {
49347
+ const server = new McpServer(
49348
+ { name: "tradeblocks-mcp", version: "0.4.1" },
49349
+ { capabilities: { tools: {}, resources: {} } }
49350
+ );
49351
+ registerBlockTools(server, resolvedDir);
49352
+ registerAnalysisTools(server, resolvedDir);
49353
+ registerPerformanceTools(server, resolvedDir);
49354
+ registerReportTools(server, resolvedDir);
49355
+ registerImportTools(server, resolvedDir);
49356
+ registerResources(server);
49357
+ return server;
49358
+ };
49347
49359
  if (http) {
49348
49360
  const { startHttpServer } = await import("./http-server.js");
49349
- await startHttpServer(server, { port });
49361
+ await startHttpServer(createServer, { port });
49350
49362
  } else {
49363
+ const server = createServer();
49351
49364
  const transport = new StdioServerTransport();
49352
49365
  await server.connect(transport);
49353
49366
  console.error(`TradeBlocks MCP ready (stdio). Watching: ${resolvedDir}`);