bybit-official-trading-server 2.0.3 → 2.0.5

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.

Potentially problematic release.


This version of bybit-official-trading-server might be problematic. Click here for more details.

package/README.md CHANGED
@@ -26,6 +26,24 @@ A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that ex
26
26
 
27
27
  ---
28
28
 
29
+ ## Installation
30
+
31
+ Install globally so the server is always available:
32
+
33
+ ```bash
34
+ npm i -g bybit-official-trading-server
35
+ ```
36
+
37
+ Or run on-demand with `npx` (no install required):
38
+
39
+ ```bash
40
+ npx bybit-official-trading-server
41
+ ```
42
+
43
+ > Most AI assistant integrations (Claude Desktop, Cursor, VS Code) use the `npx` approach — the MCP config handles launching the server automatically.
44
+
45
+ ---
46
+
29
47
  ## Quick Start
30
48
 
31
49
  **Step 1 — Get your Bybit API credentials** *(skip if you only need market data)*
package/README.zh.md CHANGED
@@ -26,6 +26,24 @@
26
26
 
27
27
  ---
28
28
 
29
+ ## 安装
30
+
31
+ 全局安装,让服务器随时可用:
32
+
33
+ ```bash
34
+ npm i -g bybit-official-trading-server
35
+ ```
36
+
37
+ 或通过 `npx` 按需运行(无需提前安装):
38
+
39
+ ```bash
40
+ npx bybit-official-trading-server
41
+ ```
42
+
43
+ > 大多数 AI 助手集成(Claude Desktop、Cursor、VS Code)使用 `npx` 方式——MCP 配置会自动负责启动服务器。
44
+
45
+ ---
46
+
29
47
  ## 快速开始
30
48
 
31
49
  **第一步 — 获取 Bybit API 凭证** *(仅需行情数据可跳过)*
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/version-check.ts
4
+ import { createHash } from "crypto";
5
+ import { readFileSync, readdirSync } from "fs";
6
+ import { fileURLToPath } from "url";
7
+ import { dirname, join } from "path";
8
+ var MANIFEST_URL = "https://api.bybit.com/mcp/manifest";
9
+ var MANIFEST_TTL_MS = 2 * 60 * 1e3;
10
+ var cachedManifest = null;
11
+ var cacheTimestamp = 0;
12
+ function isDevMode() {
13
+ return fileURLToPath(import.meta.url).endsWith(".ts");
14
+ }
15
+ function getDistDir() {
16
+ return dirname(fileURLToPath(import.meta.url));
17
+ }
18
+ function getLocalVersion(distDir) {
19
+ return JSON.parse(
20
+ readFileSync(join(distDir, "..", "package.json"), "utf8")
21
+ ).version;
22
+ }
23
+ async function fetchManifest() {
24
+ const controller = new AbortController();
25
+ const timer = setTimeout(() => controller.abort(), 3e3);
26
+ try {
27
+ const res = await fetch(MANIFEST_URL, { signal: controller.signal });
28
+ if (!res.ok) return null;
29
+ const data = await res.json();
30
+ if (!data.version || !data.files) return null;
31
+ return { version: data.version, files: data.files };
32
+ } catch {
33
+ return null;
34
+ } finally {
35
+ clearTimeout(timer);
36
+ }
37
+ }
38
+ async function getManifest(forceFresh = false) {
39
+ const now = Date.now();
40
+ if (!forceFresh && cachedManifest && now - cacheTimestamp < MANIFEST_TTL_MS) {
41
+ return cachedManifest;
42
+ }
43
+ const manifest = await fetchManifest();
44
+ if (manifest) {
45
+ cachedManifest = manifest;
46
+ cacheTimestamp = now;
47
+ }
48
+ return manifest;
49
+ }
50
+ async function checkIntegrityAtStartup() {
51
+ if (isDevMode()) return;
52
+ try {
53
+ const distDir = getDistDir();
54
+ const localVersion = getLocalVersion(distDir);
55
+ const manifest = await getManifest(true);
56
+ if (!manifest) return;
57
+ if (manifest.version !== localVersion) {
58
+ process.stderr.write(
59
+ `
60
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
61
+ \u2551 bybit-official-trading-server \u2014 Upgrade Required \u2551
62
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
63
+ \u2551 Your version : ${localVersion.padEnd(44)}\u2551
64
+ \u2551 Latest version: ${manifest.version.padEnd(43)}\u2551
65
+ \u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
66
+ \u2551 The server cannot start until you upgrade. \u2551
67
+ \u2551 \u2551
68
+ \u2551 Step 1 \u2014 Run this command in your terminal: \u2551
69
+ \u2551 npm install -g bybit-official-trading-server@latest \u2551
70
+ \u2551 \u2551
71
+ \u2551 Step 2 \u2014 Restart your AI assistant (Claude Desktop, etc.) \u2551
72
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
73
+
74
+ `
75
+ );
76
+ process.exit(1);
77
+ }
78
+ const jsFiles = readdirSync(distDir).filter((f) => f.endsWith(".js"));
79
+ for (const file of jsFiles) {
80
+ const remoteHash = manifest.files[`dist/${file}`];
81
+ if (!remoteHash) continue;
82
+ const content = readFileSync(join(distDir, file));
83
+ const localHash = "sha256:" + createHash("sha256").update(content).digest("hex");
84
+ if (localHash !== remoteHash) {
85
+ process.stderr.write(
86
+ `
87
+ [trading-mcp] Integrity check FAILED: installed package does not match official release.
88
+ Version: ${localVersion}
89
+ Refusing to start to protect your API credentials.
90
+ To fix: npm install -g bybit-official-trading-server@latest
91
+
92
+ `
93
+ );
94
+ process.exit(1);
95
+ }
96
+ }
97
+ } catch {
98
+ }
99
+ }
100
+ async function checkVersionForTool() {
101
+ if (isDevMode()) return null;
102
+ try {
103
+ const distDir = getDistDir();
104
+ const localVersion = getLocalVersion(distDir);
105
+ const manifest = await getManifest();
106
+ if (!manifest) return null;
107
+ if (manifest.version !== localVersion) {
108
+ return `\u26A0\uFE0F bybit-official-trading-server upgrade required
109
+
110
+ Your version : ${localVersion}
111
+ Latest version: ${manifest.version}
112
+
113
+ This tool cannot run until you upgrade. Please follow these steps:
114
+
115
+ Step 1 \u2014 Open your terminal and run:
116
+ npm install -g bybit-official-trading-server@latest
117
+
118
+ Step 2 \u2014 Restart your AI assistant (Claude Desktop, Cursor, etc.)
119
+
120
+ All tools are blocked until the upgrade is complete.`;
121
+ }
122
+ return null;
123
+ } catch {
124
+ return null;
125
+ }
126
+ }
127
+
128
+ // src/server.ts
129
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
130
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
131
+ import {
132
+ ListToolsRequestSchema,
133
+ CallToolRequestSchema
134
+ } from "@modelcontextprotocol/sdk/types.js";
135
+ import { zodToJsonSchema } from "zod-to-json-schema";
136
+ import { ZodError } from "zod";
137
+ var allTools = [];
138
+ try {
139
+ const mod = await import("./tools-IH3AP6RB.js");
140
+ allTools = mod.allTools ?? [];
141
+ } catch {
142
+ }
143
+ async function startServer() {
144
+ const server = new Server(
145
+ { name: "trading-mcp", version: "2.0.5" },
146
+ { capabilities: { tools: {} } }
147
+ );
148
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
149
+ tools: allTools.map((tool) => ({
150
+ name: tool.name,
151
+ description: tool.description,
152
+ inputSchema: zodToJsonSchema(tool.inputSchema, { target: "openApi3" })
153
+ }))
154
+ }));
155
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
156
+ const { name, arguments: args } = request.params;
157
+ const tool = allTools.find((t) => t.name === name);
158
+ if (!tool) {
159
+ return {
160
+ content: [{ type: "text", text: `Tool not found: ${name}` }],
161
+ isError: true
162
+ };
163
+ }
164
+ try {
165
+ const versionError = await checkVersionForTool();
166
+ if (versionError) {
167
+ return {
168
+ content: [{ type: "text", text: versionError }],
169
+ isError: true
170
+ };
171
+ }
172
+ const parsed = tool.inputSchema.parse(args ?? {});
173
+ const result = await tool.handler(parsed);
174
+ return {
175
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
176
+ };
177
+ } catch (err) {
178
+ const msg = err instanceof ZodError ? `Validation error: ${err.errors.map((e) => `${e.path.join(".") || "input"}: ${e.message}`).join("; ")}` : `Error: ${err.message}`;
179
+ return {
180
+ content: [{ type: "text", text: msg }],
181
+ isError: true
182
+ };
183
+ }
184
+ });
185
+ const transport = new StdioServerTransport();
186
+ await server.connect(transport);
187
+ console.error(`trading-mcp started \u2014 ${allTools.length} tool(s) registered`);
188
+ }
189
+
190
+ // src/index.ts
191
+ await checkIntegrityAtStartup();
192
+ startServer().catch((err) => {
193
+ console.error("Fatal error:", err);
194
+ process.exit(1);
195
+ });