tradeblocks-mcp 2.2.4 → 2.2.6
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 +22 -1
- package/dist/{chunk-O6FQQRJV.js → chunk-FIKAXL2L.js} +35 -17
- package/dist/chunk-FIKAXL2L.js.map +1 -0
- package/dist/{sync-AAV7BGOE.js → sync-2TUYF36I.js} +6 -2
- package/dist/test-exports.js +1 -1
- package/package.json +1 -1
- package/server/{chunk-TDKK4QFM.js → chunk-IBEPOZZK.js} +35 -17
- package/server/chunk-IBEPOZZK.js.map +1 -0
- package/server/index.js +32 -7
- package/server/index.js.map +1 -1
- package/server/{sync-T6GEBPJ7.js → sync-37YJXJVW.js} +6 -2
- package/dist/chunk-O6FQQRJV.js.map +0 -1
- package/server/chunk-TDKK4QFM.js.map +0 -1
- /package/dist/{sync-AAV7BGOE.js.map → sync-2TUYF36I.js.map} +0 -0
- /package/server/{sync-T6GEBPJ7.js.map → sync-37YJXJVW.js.map} +0 -0
package/README.md
CHANGED
|
@@ -147,8 +147,29 @@ tradeblocks-mcp ~/backtests
|
|
|
147
147
|
# HTTP mode
|
|
148
148
|
tradeblocks-mcp --http ~/backtests
|
|
149
149
|
tradeblocks-mcp --http --port 8080 ~/backtests
|
|
150
|
+
|
|
151
|
+
# Separate CSV blocks from DuckDB storage
|
|
152
|
+
tradeblocks-mcp --directory ./data --blocks-dir ~/backtests
|
|
150
153
|
```
|
|
151
154
|
|
|
155
|
+
### Options
|
|
156
|
+
|
|
157
|
+
| Flag | Description | Default |
|
|
158
|
+
|------|-------------|---------|
|
|
159
|
+
| `--http` | Start HTTP server instead of stdio | stdio |
|
|
160
|
+
| `--port <n>` | HTTP server port | 3100 |
|
|
161
|
+
| `--blocks-dir <path>` | Directory containing CSV block folders | same as data directory |
|
|
162
|
+
| `--market-db <path>` | Path to market.duckdb | `<directory>/market.duckdb` |
|
|
163
|
+
| `--no-auth` | Disable authentication (HTTP mode) | auth enabled |
|
|
164
|
+
|
|
165
|
+
### Environment Variables
|
|
166
|
+
|
|
167
|
+
| Variable | Description |
|
|
168
|
+
|----------|-------------|
|
|
169
|
+
| `BLOCKS_DIRECTORY` | Default data directory if not specified as argument |
|
|
170
|
+
| `TRADEBLOCKS_BLOCKS_DIR` | Directory for CSV block folders (overridden by `--blocks-dir`) |
|
|
171
|
+
| `MARKET_DB_PATH` | Path to market.duckdb (overridden by `--market-db`) |
|
|
172
|
+
|
|
152
173
|
## Docker Deployment
|
|
153
174
|
|
|
154
175
|
Run the MCP server in a container for remote/server deployments.
|
|
@@ -175,7 +196,7 @@ docker build -t tradeblocks-mcp .
|
|
|
175
196
|
docker compose up -d
|
|
176
197
|
```
|
|
177
198
|
|
|
178
|
-
Place your block folders (each containing CSV files) in the `data/` directory. The container runs in HTTP mode on port 3100 by default. See [Authentication](#authentication) below for configuring credentials.
|
|
199
|
+
Place your block folders (each containing CSV files) in the `data/` directory, or use `--blocks-dir` to point at a separate folder. The container runs in HTTP mode on port 3100 by default. See [Authentication](#authentication) below for configuring credentials.
|
|
179
200
|
|
|
180
201
|
Connect any MCP client to `http://<your-host>:3100/mcp`. How you expose this endpoint (reverse proxy, tunnel, VPN, etc.) is up to you.
|
|
181
202
|
|
|
@@ -807,14 +807,18 @@ async function getConnection(dataDir) {
|
|
|
807
807
|
if (isLockError(errorMessage)) {
|
|
808
808
|
const recovered = await tryRecoverLockByTerminatingStaleProcess(errorMessage, dbPath, forceRecovery);
|
|
809
809
|
if (recovered) {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
810
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
811
|
+
await new Promise((r) => setTimeout(r, 500 * (attempt + 1)));
|
|
812
|
+
try {
|
|
813
|
+
return await openReadWriteConnection(dbPath, threads, memoryLimit);
|
|
814
|
+
} catch (retryError) {
|
|
815
|
+
const retryMsg = retryError instanceof Error ? retryError.message : String(retryError);
|
|
816
|
+
if (attempt < 2 && isLockError(retryMsg)) continue;
|
|
817
|
+
resetConnectionState();
|
|
818
|
+
throw new Error(
|
|
819
|
+
`Failed to initialize DuckDB at ${dbPath} after lock recovery: ${retryMsg}`
|
|
820
|
+
);
|
|
821
|
+
}
|
|
818
822
|
}
|
|
819
823
|
}
|
|
820
824
|
}
|
|
@@ -857,8 +861,8 @@ async function closeConnection() {
|
|
|
857
861
|
async function upgradeToReadWrite(dataDir, options) {
|
|
858
862
|
if (connectionMode === "read_write" && connection) return connection;
|
|
859
863
|
await closeConnection();
|
|
860
|
-
const maxRetries =
|
|
861
|
-
const retryDelayMs =
|
|
864
|
+
const maxRetries = 4;
|
|
865
|
+
const retryDelayMs = 1e3;
|
|
862
866
|
let lastError = null;
|
|
863
867
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
864
868
|
try {
|
|
@@ -22612,13 +22616,16 @@ async function detectBlockChanges(conn, baseDir) {
|
|
|
22612
22616
|
const folderNames = /* @__PURE__ */ new Set();
|
|
22613
22617
|
for (const entry of entries) {
|
|
22614
22618
|
if (!entry.isDirectory()) continue;
|
|
22615
|
-
if (entry.name.startsWith(".")) continue;
|
|
22616
|
-
if (entry.name
|
|
22619
|
+
if (entry.name.startsWith(".") || entry.name.startsWith("_")) continue;
|
|
22620
|
+
if (entry.name.includes(".")) continue;
|
|
22617
22621
|
const blockId = entry.name;
|
|
22618
22622
|
folderNames.add(blockId);
|
|
22619
22623
|
const blockPath = path4.join(baseDir, blockId);
|
|
22620
22624
|
if (!syncedBlockIds.has(blockId)) {
|
|
22621
|
-
|
|
22625
|
+
const tradelog = await findTradelogFile(blockPath);
|
|
22626
|
+
if (tradelog) {
|
|
22627
|
+
toSync.push(blockId);
|
|
22628
|
+
}
|
|
22622
22629
|
continue;
|
|
22623
22630
|
}
|
|
22624
22631
|
const tradelogFilename = await findTradelogFile(blockPath);
|
|
@@ -22677,11 +22684,19 @@ async function cleanupDeletedBlocks(conn, deletedBlockIds) {
|
|
|
22677
22684
|
}
|
|
22678
22685
|
|
|
22679
22686
|
// src/sync/index.ts
|
|
22687
|
+
var _blocksDir = null;
|
|
22688
|
+
function setBlocksDir(dir) {
|
|
22689
|
+
_blocksDir = dir;
|
|
22690
|
+
}
|
|
22691
|
+
function getBlocksDir(baseDir) {
|
|
22692
|
+
return _blocksDir ?? baseDir;
|
|
22693
|
+
}
|
|
22680
22694
|
async function syncAllBlocks(baseDir) {
|
|
22681
22695
|
const conn = await getConnection(baseDir);
|
|
22696
|
+
const blocksDir = getBlocksDir(baseDir);
|
|
22682
22697
|
const results = [];
|
|
22683
22698
|
const errors = [];
|
|
22684
|
-
const { toSync, toDelete } = await detectBlockChanges(conn,
|
|
22699
|
+
const { toSync, toDelete } = await detectBlockChanges(conn, blocksDir);
|
|
22685
22700
|
for (const blockId of toDelete) {
|
|
22686
22701
|
try {
|
|
22687
22702
|
await cleanupDeletedBlocks(conn, [blockId]);
|
|
@@ -22692,7 +22707,7 @@ async function syncAllBlocks(baseDir) {
|
|
|
22692
22707
|
}
|
|
22693
22708
|
}
|
|
22694
22709
|
for (const blockId of toSync) {
|
|
22695
|
-
const blockPath = path5.join(
|
|
22710
|
+
const blockPath = path5.join(blocksDir, blockId);
|
|
22696
22711
|
const result = await syncBlockInternal(conn, blockId, blockPath);
|
|
22697
22712
|
results.push(result);
|
|
22698
22713
|
if (result.status === "error" && result.error) {
|
|
@@ -22710,7 +22725,8 @@ async function syncAllBlocks(baseDir) {
|
|
|
22710
22725
|
}
|
|
22711
22726
|
async function syncBlock(blockId, baseDir) {
|
|
22712
22727
|
const conn = await getConnection(baseDir);
|
|
22713
|
-
const
|
|
22728
|
+
const blocksDir = getBlocksDir(baseDir);
|
|
22729
|
+
const blockPath = path5.join(blocksDir, blockId);
|
|
22714
22730
|
try {
|
|
22715
22731
|
await fs6.access(blockPath);
|
|
22716
22732
|
} catch {
|
|
@@ -22756,6 +22772,8 @@ export {
|
|
|
22756
22772
|
normalizeTicker,
|
|
22757
22773
|
resolveTradeTicker,
|
|
22758
22774
|
marketTickerDateKey,
|
|
22775
|
+
setBlocksDir,
|
|
22776
|
+
getBlocksDir,
|
|
22759
22777
|
syncAllBlocks,
|
|
22760
22778
|
syncBlock
|
|
22761
22779
|
};
|
|
@@ -22770,4 +22788,4 @@ decimal.js/decimal.mjs:
|
|
|
22770
22788
|
* MIT Licence
|
|
22771
22789
|
*)
|
|
22772
22790
|
*/
|
|
22773
|
-
//# sourceMappingURL=chunk-
|
|
22791
|
+
//# sourceMappingURL=chunk-FIKAXL2L.js.map
|