bitbank-lab-mcp 0.1.0

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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +388 -0
  3. package/assets/lightweight-charts.standalone.js +7 -0
  4. package/bin/bitbank-lab-mcp.js +20 -0
  5. package/lib/cache.ts +70 -0
  6. package/lib/candle-utils.ts +48 -0
  7. package/lib/candle-validate.ts +434 -0
  8. package/lib/conversions.ts +25 -0
  9. package/lib/datetime.ts +157 -0
  10. package/lib/depth-analysis.ts +51 -0
  11. package/lib/error.ts +15 -0
  12. package/lib/formatter.ts +296 -0
  13. package/lib/get-depth.ts +111 -0
  14. package/lib/http.ts +132 -0
  15. package/lib/indicator-config.ts +39 -0
  16. package/lib/indicator_buffer.ts +41 -0
  17. package/lib/indicators.ts +579 -0
  18. package/lib/logger.ts +120 -0
  19. package/lib/ma-snapshot-utils.ts +277 -0
  20. package/lib/math.ts +89 -0
  21. package/lib/pattern-diagrams.ts +562 -0
  22. package/lib/result.ts +104 -0
  23. package/lib/validate.ts +154 -0
  24. package/lib/volatility.ts +132 -0
  25. package/package.json +79 -0
  26. package/src/env.ts +4 -0
  27. package/src/handlers/analyzeCandlePatternsHandler.ts +383 -0
  28. package/src/handlers/analyzeFibonacciHandler.ts +54 -0
  29. package/src/handlers/analyzeIndicatorsHandler.ts +682 -0
  30. package/src/handlers/analyzeMarketSignalHandler.ts +272 -0
  31. package/src/handlers/analyzeMyPortfolioHandler.ts +800 -0
  32. package/src/handlers/detectPatternsHandler.ts +77 -0
  33. package/src/handlers/detectPatternsViewsHandler.ts +518 -0
  34. package/src/handlers/getTickersJpyHandler.ts +145 -0
  35. package/src/handlers/getVolatilityMetricsHandler.ts +234 -0
  36. package/src/handlers/portfolio/calc.ts +549 -0
  37. package/src/handlers/portfolio/fetch.ts +318 -0
  38. package/src/handlers/portfolio/types.ts +170 -0
  39. package/src/handlers/renderChartSvgHandler.ts +69 -0
  40. package/src/handlers/runBacktestHandler.ts +70 -0
  41. package/src/http.ts +107 -0
  42. package/src/private/auth.ts +104 -0
  43. package/src/private/client.ts +298 -0
  44. package/src/private/config.ts +25 -0
  45. package/src/private/confirmation.ts +185 -0
  46. package/src/private/schemas.ts +866 -0
  47. package/src/prompts.ts +2296 -0
  48. package/src/resources/app-resources.ts +79 -0
  49. package/src/schema/analysis.ts +942 -0
  50. package/src/schema/backtest.ts +100 -0
  51. package/src/schema/base.ts +88 -0
  52. package/src/schema/candle-validate.ts +135 -0
  53. package/src/schema/chart.ts +399 -0
  54. package/src/schema/index.ts +11 -0
  55. package/src/schema/indicators.ts +125 -0
  56. package/src/schema/market-data.ts +298 -0
  57. package/src/schema/patterns.ts +382 -0
  58. package/src/schema/types.ts +97 -0
  59. package/src/schemas.d.ts +37 -0
  60. package/src/schemas.ts +7 -0
  61. package/src/server.ts +405 -0
  62. package/src/tool-definition.ts +44 -0
  63. package/src/tool-registry.ts +174 -0
  64. package/src/types/express-shim.d.ts +9 -0
  65. package/src/types/schemas.generated.d.ts +23 -0
  66. package/tools/analyze_bb_snapshot.ts +385 -0
  67. package/tools/analyze_candle_patterns.ts +810 -0
  68. package/tools/analyze_currency_strength.ts +273 -0
  69. package/tools/analyze_ema_snapshot.ts +183 -0
  70. package/tools/analyze_fibonacci.ts +530 -0
  71. package/tools/analyze_ichimoku_snapshot.ts +606 -0
  72. package/tools/analyze_indicators.ts +691 -0
  73. package/tools/analyze_market_signal.ts +665 -0
  74. package/tools/analyze_mtf_fibonacci.ts +273 -0
  75. package/tools/analyze_mtf_sma.ts +175 -0
  76. package/tools/analyze_sma_snapshot.ts +146 -0
  77. package/tools/analyze_stoch_snapshot.ts +276 -0
  78. package/tools/analyze_support_resistance.ts +817 -0
  79. package/tools/analyze_volume_profile.ts +546 -0
  80. package/tools/chart/ichimoku-cloud.ts +113 -0
  81. package/tools/chart/render-depth.ts +139 -0
  82. package/tools/chart/render-sub-panels.ts +208 -0
  83. package/tools/chart/svg-utils.ts +102 -0
  84. package/tools/detect_macd_cross.ts +691 -0
  85. package/tools/detect_patterns.ts +424 -0
  86. package/tools/detect_whale_events.ts +181 -0
  87. package/tools/get_candles.ts +487 -0
  88. package/tools/get_flow_metrics.ts +596 -0
  89. package/tools/get_orderbook.ts +540 -0
  90. package/tools/get_ticker.ts +132 -0
  91. package/tools/get_tickers_jpy.ts +240 -0
  92. package/tools/get_transactions.ts +209 -0
  93. package/tools/get_volatility_metrics.ts +302 -0
  94. package/tools/patterns/aftermath.ts +212 -0
  95. package/tools/patterns/config.ts +151 -0
  96. package/tools/patterns/detect_doubles.ts +650 -0
  97. package/tools/patterns/detect_hs.ts +635 -0
  98. package/tools/patterns/detect_pennants.ts +373 -0
  99. package/tools/patterns/detect_triangles.ts +820 -0
  100. package/tools/patterns/detect_triples.ts +633 -0
  101. package/tools/patterns/detect_wedges.ts +1072 -0
  102. package/tools/patterns/helpers.ts +517 -0
  103. package/tools/patterns/index.ts +40 -0
  104. package/tools/patterns/regression.ts +153 -0
  105. package/tools/patterns/smoothing.ts +168 -0
  106. package/tools/patterns/swing.ts +91 -0
  107. package/tools/patterns/types.ts +193 -0
  108. package/tools/prepare_chart_data.ts +294 -0
  109. package/tools/prepare_depth_data.ts +189 -0
  110. package/tools/private/analyze_my_portfolio.ts +21 -0
  111. package/tools/private/cancel_order.ts +127 -0
  112. package/tools/private/cancel_orders.ts +121 -0
  113. package/tools/private/create_order.ts +236 -0
  114. package/tools/private/get_margin_positions.ts +134 -0
  115. package/tools/private/get_margin_status.ts +155 -0
  116. package/tools/private/get_margin_trade_history.ts +156 -0
  117. package/tools/private/get_my_assets.ts +207 -0
  118. package/tools/private/get_my_deposit_withdrawal.ts +500 -0
  119. package/tools/private/get_my_orders.ts +157 -0
  120. package/tools/private/get_my_trade_history.ts +229 -0
  121. package/tools/private/get_order.ts +95 -0
  122. package/tools/private/get_orders_info.ts +90 -0
  123. package/tools/private/preview_cancel_order.ts +172 -0
  124. package/tools/private/preview_cancel_orders.ts +137 -0
  125. package/tools/private/preview_order.ts +292 -0
  126. package/tools/render_candle_pattern_diagram.ts +389 -0
  127. package/tools/render_chart_svg.ts +799 -0
  128. package/tools/render_depth_svg.ts +274 -0
  129. package/tools/trading_process/index.ts +7 -0
  130. package/tools/trading_process/lib/backtest_engine.ts +252 -0
  131. package/tools/trading_process/lib/equity.ts +131 -0
  132. package/tools/trading_process/lib/fetch_candles.ts +181 -0
  133. package/tools/trading_process/lib/sma.ts +62 -0
  134. package/tools/trading_process/lib/strategies/bb_breakout.ts +141 -0
  135. package/tools/trading_process/lib/strategies/index.ts +52 -0
  136. package/tools/trading_process/lib/strategies/macd_cross.ts +256 -0
  137. package/tools/trading_process/lib/strategies/rsi.ts +133 -0
  138. package/tools/trading_process/lib/strategies/sma_cross.ts +214 -0
  139. package/tools/trading_process/lib/strategies/types.ts +118 -0
  140. package/tools/trading_process/lib/svg_to_png.ts +64 -0
  141. package/tools/trading_process/render_backtest_chart_generic.ts +729 -0
  142. package/tools/trading_process/run_backtest.ts +243 -0
  143. package/tools/trading_process/types.ts +85 -0
  144. package/tools/validate_candle_data.ts +260 -0
  145. package/tsconfig.json +17 -0
  146. package/ui/cancel-confirm/dist/cancel-confirm.html +99 -0
  147. package/ui/order-confirm/dist/order-confirm.html +99 -0
@@ -0,0 +1,154 @@
1
+ import type { Pair } from '../src/schemas.js';
2
+ import { nowIso } from './datetime.js';
3
+
4
+ // bitbank 公式ペアリスト(アクティブなもののみ)
5
+ // 参考: https://github.com/bitbankinc/bitbank-api-docs/blob/master/pairs.md
6
+ export const ALLOWED_PAIRS: Set<Pair> = new Set([
7
+ // 主要ペア
8
+ 'btc_jpy',
9
+ 'eth_jpy',
10
+ 'xrp_jpy',
11
+ 'ltc_jpy',
12
+ 'bcc_jpy',
13
+ // アルトコイン
14
+ 'mona_jpy',
15
+ 'xlm_jpy',
16
+ 'qtum_jpy',
17
+ 'bat_jpy',
18
+ 'omg_jpy',
19
+ 'xym_jpy',
20
+ 'link_jpy',
21
+ 'boba_jpy',
22
+ 'enj_jpy',
23
+ 'dot_jpy',
24
+ 'doge_jpy',
25
+ 'astr_jpy',
26
+ 'ada_jpy',
27
+ 'avax_jpy',
28
+ 'axs_jpy',
29
+ 'flr_jpy',
30
+ 'sand_jpy',
31
+ 'gala_jpy',
32
+ 'ape_jpy',
33
+ 'chz_jpy',
34
+ 'oas_jpy',
35
+ 'mana_jpy',
36
+ 'grt_jpy',
37
+ 'bnb_jpy',
38
+ 'dai_jpy',
39
+ 'op_jpy',
40
+ 'arb_jpy',
41
+ 'klay_jpy',
42
+ 'imx_jpy',
43
+ 'mask_jpy',
44
+ 'pol_jpy', // 旧 matic_jpy
45
+ 'sol_jpy',
46
+ 'cyber_jpy',
47
+ 'render_jpy', // 旧 rndr_jpy
48
+ 'trx_jpy',
49
+ 'lpt_jpy',
50
+ 'atom_jpy',
51
+ 'sui_jpy',
52
+ 'sky_jpy', // 旧 mkr_jpy
53
+ ]);
54
+
55
+ export function normalizePair(raw: unknown): Pair | null {
56
+ if (!raw) return null;
57
+ const s = String(raw).trim().toLowerCase();
58
+ // Zodバリデーション済みの場合、形式変換(BTC/JPY → btc_jpy)は不要
59
+ // 正規形式(xxx_yyy)以外は null を返す
60
+ if (!/^[a-z0-9]+_[a-z0-9]+$/.test(s)) return null;
61
+ return s as Pair;
62
+ }
63
+
64
+ export function ensurePair(
65
+ pair: unknown,
66
+ ): { ok: true; pair: Pair } | { ok: false; error: { type: 'user' | 'internal'; message: string } } {
67
+ const norm = normalizePair(pair);
68
+ if (!norm) {
69
+ return {
70
+ ok: false,
71
+ error: { type: 'user', message: `pair '${String(pair)}' が不正です(例: btc_jpy)` },
72
+ };
73
+ }
74
+ if (!ALLOWED_PAIRS.has(norm)) {
75
+ return {
76
+ ok: false,
77
+ error: {
78
+ type: 'user',
79
+ message: `未対応のpair: '${norm}'(対応例: ${[...ALLOWED_PAIRS].slice(0, 5).join(', ')}...)`,
80
+ },
81
+ };
82
+ }
83
+ return { ok: true, pair: norm };
84
+ }
85
+
86
+ export function validateLimit(
87
+ limit: unknown,
88
+ min = 1,
89
+ max = 1000,
90
+ paramName = 'limit',
91
+ ): { ok: true; value: number } | { ok: false; error: { type: 'user' | 'internal'; message: string } } {
92
+ const num = Number(limit);
93
+ if (!Number.isInteger(num) || num < min || num > max) {
94
+ return {
95
+ ok: false,
96
+ error: {
97
+ type: 'user',
98
+ message: `${paramName} は ${min}〜${max} の整数で指定してください(指定値: ${String(limit)})`,
99
+ },
100
+ };
101
+ }
102
+ return { ok: true, value: num };
103
+ }
104
+
105
+ export function validateDate(
106
+ date: string,
107
+ type: string | null = null,
108
+ ): { ok: true; value: string } | { ok: false; error: { type: 'user' | 'internal'; message: string } } {
109
+ if (type) {
110
+ // YYYYMMDD が必要なタイプ(分足~1時間足)
111
+ const TYPES_REQUIRE_YYYYMMDD = new Set(['1min', '5min', '15min', '30min', '1hour']);
112
+
113
+ if (TYPES_REQUIRE_YYYYMMDD.has(type)) {
114
+ if (!/^\d{8}$/.test(date)) {
115
+ return {
116
+ ok: false,
117
+ error: {
118
+ type: 'user',
119
+ message: `${type} の場合、date は YYYYMMDD 形式で指定してください(指定値: ${date})`,
120
+ },
121
+ };
122
+ }
123
+ return { ok: true, value: date };
124
+ } else {
125
+ // 4hour/8hour/12hour 以上は YYYY 単位で取得(公式仕様)
126
+ if (!/^\d{4,8}$/.test(date)) {
127
+ return {
128
+ ok: false,
129
+ error: { type: 'user', message: `date は YYYY または YYYYMMDD 形式で指定してください(指定値: ${date})` },
130
+ };
131
+ }
132
+ return { ok: true, value: String(date).substring(0, 4) };
133
+ }
134
+ }
135
+
136
+ if (!/^\d{4,8}$/.test(date)) {
137
+ return {
138
+ ok: false,
139
+ error: { type: 'user', message: `date は YYYY または YYYYMMDD 形式で指定してください(指定値: ${date})` },
140
+ };
141
+ }
142
+ return { ok: true, value: date };
143
+ }
144
+
145
+ export function createMeta(
146
+ pair: Pair,
147
+ additional: Record<string, unknown> = {},
148
+ ): Record<string, unknown> & { pair: Pair; fetchedAt: string } {
149
+ return {
150
+ pair,
151
+ fetchedAt: nowIso(),
152
+ ...additional,
153
+ };
154
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * lib/volatility.ts - ボラティリティ推定量の共通計算モジュール
3
+ *
4
+ * OHLC ベースのボラティリティ推定量(Parkinson, Garman-Klass, Rogers-Satchell)と
5
+ * リターンベースの計算を提供。
6
+ *
7
+ * 【共通仕様】
8
+ * - 入力: number[](古い順)
9
+ * - 出力: number[](各キャンドルごとのコンポーネント値)
10
+ * - 丸め処理なし(呼び出し元で必要に応じて丸める)
11
+ * - safeLog を使用し、ゼロ / 負値入力に対して安全
12
+ */
13
+
14
+ function safeLog(x: number): number {
15
+ return Math.log(Math.max(x, 1e-12));
16
+ }
17
+
18
+ /**
19
+ * 対数リターン系列
20
+ *
21
+ * ret[i] = ln(close[i] / close[i-1]) (useLog=true の場合)
22
+ * ret[i] = (close[i] - close[i-1]) / close[i-1] (useLog=false の場合)
23
+ *
24
+ * @param closes 終値配列(古い順)
25
+ * @param useLog true で対数リターン、false で単純リターン(デフォルト true)
26
+ * @returns リターン配列(長さ = closes.length - 1)
27
+ */
28
+ export function logReturns(closes: number[], useLog: boolean = true): number[] {
29
+ const result: number[] = [];
30
+ for (let i = 1; i < closes.length; i++) {
31
+ const prev = closes[i - 1];
32
+ const curr = closes[i];
33
+ if (prev > 0 && curr > 0) {
34
+ result.push(useLog ? safeLog(curr / prev) : (curr - prev) / prev);
35
+ } else {
36
+ result.push(0);
37
+ }
38
+ }
39
+ return result;
40
+ }
41
+
42
+ /**
43
+ * Parkinson ボラティリティのコンポーネント系列
44
+ *
45
+ * pk[i] = (ln(H/L))^2
46
+ * 集約: σ_parkinson = sqrt(mean(pk) / (4 * ln(2)))
47
+ *
48
+ * @param highs 高値配列(古い順)
49
+ * @param lows 安値配列(古い順)
50
+ * @returns per-candle コンポーネント配列
51
+ */
52
+ export function parkinsonComponents(highs: number[], lows: number[]): number[] {
53
+ const n = Math.min(highs.length, lows.length);
54
+ const result: number[] = [];
55
+ for (let i = 0; i < n; i++) {
56
+ const logHL = safeLog(highs[i] / Math.max(lows[i], 1e-12));
57
+ result.push(logHL * logHL);
58
+ }
59
+ return result;
60
+ }
61
+
62
+ /**
63
+ * Garman-Klass ボラティリティのコンポーネント系列
64
+ *
65
+ * gk[i] = 0.5 * (ln(H/L))^2 - (2*ln(2) - 1) * (ln(C/O))^2
66
+ * 集約: σ_gk = sqrt(mean(gk))
67
+ *
68
+ * @param opens 始値配列
69
+ * @param highs 高値配列
70
+ * @param lows 安値配列
71
+ * @param closes 終値配列
72
+ * @returns per-candle コンポーネント配列
73
+ */
74
+ export function garmanKlassComponents(opens: number[], highs: number[], lows: number[], closes: number[]): number[] {
75
+ const n = Math.min(opens.length, highs.length, lows.length, closes.length);
76
+ const result: number[] = [];
77
+ for (let i = 0; i < n; i++) {
78
+ const logHL = safeLog(highs[i] / Math.max(lows[i], 1e-12));
79
+ const logCO = safeLog(closes[i] / Math.max(opens[i], 1e-12));
80
+ const pk = logHL * logHL;
81
+ result.push(0.5 * pk - (2 * Math.log(2) - 1) * (logCO * logCO));
82
+ }
83
+ return result;
84
+ }
85
+
86
+ /**
87
+ * Rogers-Satchell ボラティリティのコンポーネント系列
88
+ *
89
+ * rs[i] = ln(H/C)*ln(H/O) + ln(L/C)*ln(L/O)
90
+ * 集約: σ_rs = sqrt(mean(rs))
91
+ *
92
+ * @param opens 始値配列
93
+ * @param highs 高値配列
94
+ * @param lows 安値配列
95
+ * @param closes 終値配列
96
+ * @returns per-candle コンポーネント配列
97
+ */
98
+ export function rogersSatchellComponents(opens: number[], highs: number[], lows: number[], closes: number[]): number[] {
99
+ const n = Math.min(opens.length, highs.length, lows.length, closes.length);
100
+ const result: number[] = [];
101
+ for (let i = 0; i < n; i++) {
102
+ const h = highs[i];
103
+ const l = lows[i];
104
+ const c = closes[i];
105
+ const o = opens[i];
106
+ const rs =
107
+ safeLog(h / Math.max(c, 1e-12)) * safeLog(h / Math.max(o, 1e-12)) +
108
+ safeLog(l / Math.max(c, 1e-12)) * safeLog(l / Math.max(o, 1e-12));
109
+ result.push(rs);
110
+ }
111
+ return result;
112
+ }
113
+
114
+ /**
115
+ * コンポーネント平均からボラティリティ値に変換
116
+ *
117
+ * @param componentMean コンポーネント系列の平均値
118
+ * @param type 推定量タイプ
119
+ * @returns ボラティリティ値(σ)
120
+ */
121
+ export function componentMeanToVol(
122
+ componentMean: number,
123
+ type: 'parkinson' | 'garmanKlass' | 'rogersSatchell',
124
+ ): number {
125
+ switch (type) {
126
+ case 'parkinson':
127
+ return Math.sqrt(Math.max(0, componentMean / (4 * Math.log(2))));
128
+ case 'garmanKlass':
129
+ case 'rogersSatchell':
130
+ return Math.sqrt(Math.max(0, componentMean));
131
+ }
132
+ }
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "bitbank-lab-mcp",
3
+ "version": "0.1.0",
4
+ "description": "Experimental MCP server for bitbank — botters lab community edition. Market data, technical analysis, charting, and Private API trading tools.",
5
+ "type": "module",
6
+ "bin": {
7
+ "bitbank-lab-mcp": "bin/bitbank-lab-mcp.js"
8
+ },
9
+ "license": "MIT",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/tjackiet/bitbank-genesis-mcp-server.git"
13
+ },
14
+ "files": [
15
+ "bin/",
16
+ "src/",
17
+ "tools/",
18
+ "lib/",
19
+ "assets/lightweight-charts.standalone.js",
20
+ "ui/order-confirm/dist/",
21
+ "ui/cancel-confirm/dist/",
22
+ "package.json",
23
+ "tsconfig.json"
24
+ ],
25
+ "scripts": {
26
+ "start": "tsx src/server.ts",
27
+ "http": "tsx src/http.ts",
28
+ "dev": "LOG_LEVEL=debug tsx src/server.ts",
29
+ "build:ui:order": "vite build --config ui/order-confirm/vite.config.ts",
30
+ "build:ui": "npm run build:ui:order && npm run build:ui:cancel",
31
+ "test": "vitest run",
32
+ "test:watch": "vitest",
33
+ "test:e2e": "vitest run --config vitest.config.e2e.ts",
34
+ "test:coverage": "vitest run --coverage",
35
+ "stat": "tsx scripts/stat.ts",
36
+ "report": "tsx scripts/report.ts",
37
+ "typecheck": "tsc --noEmit -p tsconfig.json",
38
+ "ci:typecheck": "npm run gen:types && tsc --noEmit -p tsconfig.json",
39
+ "build": "npm run ci:typecheck",
40
+ "gen:types": "tsx scripts/gen_types.ts",
41
+ "lint": "oxlint src/ tools/ lib/",
42
+ "lint:fix": "oxlint --fix src/ tools/ lib/",
43
+ "format": "biome format --write src/ tools/ lib/",
44
+ "format:check": "biome check src/ tools/ lib/",
45
+ "postinstall": "mkdir -p assets && cp node_modules/lightweight-charts/dist/lightweight-charts.standalone.production.js assets/lightweight-charts.standalone.js || true",
46
+ "build:ui:cancel": "vite build --config ui/cancel-confirm/vite.config.ts"
47
+ },
48
+ "keywords": [],
49
+ "author": "",
50
+ "dependencies": {
51
+ "@modelcontextprotocol/ext-apps": "^1.7.0",
52
+ "@modelcontextprotocol/sdk": "^1.29.0",
53
+ "dayjs": "^1.11.19",
54
+ "dotenv": "^17.4.2",
55
+ "express": "^5.1.0",
56
+ "express-rate-limit": "^8.3.2",
57
+ "lightweight-charts": "^5.1.0",
58
+ "sharp": "^0.34.5",
59
+ "tsx": "^4.20.6",
60
+ "zod": "^4.3.6"
61
+ },
62
+ "devDependencies": {
63
+ "@biomejs/biome": "^2.4.7",
64
+ "@types/express": "^5.0.4",
65
+ "@types/node": "^24.5.0",
66
+ "@types/react": "^19.2.14",
67
+ "@types/react-dom": "^19.2.3",
68
+ "@vitejs/plugin-react": "^6.0.1",
69
+ "@vitest/coverage-v8": "^4.1.2",
70
+ "lefthook": "^2.1.4",
71
+ "oxlint": "^1.55.0",
72
+ "react": "^19.2.5",
73
+ "react-dom": "^19.2.5",
74
+ "typescript": "^5.9.3",
75
+ "vite": "^8.0.10",
76
+ "vite-plugin-singlefile": "^2.3.3",
77
+ "vitest": "^4.0.18"
78
+ }
79
+ }
package/src/env.ts ADDED
@@ -0,0 +1,4 @@
1
+ import dotenv from 'dotenv';
2
+
3
+ // dotenv 17 defaults quiet to false — console.log output on stdout breaks STDIO transport
4
+ dotenv.config({ quiet: true });